From e56c431c3057fb2c0148021dd408e614900192cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=A3=AB=E4=BC=9F?= Date: Fri, 30 Nov 2018 15:01:02 +0800 Subject: [PATCH 01/36] Fix document spelling errors --- docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md index 12c913511f..a9e333690f 100644 --- a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md +++ b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md @@ -295,7 +295,7 @@ successfully created the book with id: f3f03580-c1aa-d6a9-072d-39e75c69f5c7 现在我们来创建一些可见的可用的东西,我们使用[Razor Pages UI](https://docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/razor-pages-start)代替经典的MVC.微软也推荐使用Razor Pages UI -在 `Acme.BookStore.Web`项目的`Pages`文件夹下创建一个新的文件夹叫`Books`并添加一个名叫`Index.html`的Razor Page. +在 `Acme.BookStore.Web`项目的`Pages`文件夹下创建一个新的文件夹叫`Books`并添加一个名叫`Index.cshtml`的Razor Page. ![bookstore-add-index-page](images/bookstore-add-index-page.png) From d90c14d1c39b239a10b8f484cc56ec1760474349 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 30 Nov 2018 15:04:38 +0800 Subject: [PATCH 02/36] Update Getting-Started-AspNetCore-MVC-Template.md --- docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md b/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md index ebb832c04b..6f274b5177 100644 --- a/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md +++ b/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md @@ -28,8 +28,6 @@ * ``.Web`` 为是表示层. * ``.EntityFrameworkCore`` 是EF Core集成. -The solution also contains unit & integration test projects properly configured to work with **EF Core** & **SQLite in-memory** database. - 解决方案还包含配置好的的单元&集成测试项目, 以便与 **EF Core** 和 **SQLite内存中** 数据库配合使用. ### 创建数据库 @@ -44,8 +42,6 @@ The solution also contains unit & integration test projects properly configured } ```` -The solution is configured to use **Entity Framework Core** with **MS SQL Server**. EF Core supports [various](https://docs.microsoft.com/en-us/ef/core/providers/) database providers, so you can use another DBMS if you want. - 解决方案使用 **Entity Framework Core** 和 **MS SQL Server**. EF Core支持[各种](https://docs.microsoft.com/en-us/ef/core/providers/)数据库提供程序,因此你可以根据实际需要使用其他DBMS. 右键单击`.Web`项目并**设置启动项目** From 5e460dfe65ad414c93b7b712799ef28bb5824ab7 Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Mon, 10 Dec 2018 09:01:33 +0300 Subject: [PATCH 03/36] Add best practice for DTOs of modules. --- docs/en/Best-Practices/Application-Services.md | 6 ++++++ docs/en/Best-Practices/Data-Transfer-Objects.md | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/en/Best-Practices/Application-Services.md b/docs/en/Best-Practices/Application-Services.md index c5d1b51393..9c17b6db21 100644 --- a/docs/en/Best-Practices/Application-Services.md +++ b/docs/en/Best-Practices/Application-Services.md @@ -26,6 +26,7 @@ Example: ```c# +[Serializable] public class IssueDto : FullAuditedEntityDto { public string Title { get; set; } @@ -34,6 +35,7 @@ public class IssueDto : FullAuditedEntityDto public Collection Labels { get; set; } } +[Serializable] public class IssueLabelDto { public Guid IssueId { get; set; } @@ -54,6 +56,7 @@ public class IssueLabelDto Example: ````C# +[Serializable] public class IssueWithDetailsDto : FullAuditedEntityDto { public string Title { get; set; } @@ -62,12 +65,14 @@ public class IssueWithDetailsDto : FullAuditedEntityDto public Collection Labels { get; set; } } +[Serializable] public class MilestoneDto : EntityDto { public string Name { get; set; } public bool IsClosed { get; set; } } +[Serializable] public class LabelDto : EntityDto { public string Name { get; set; } @@ -129,6 +134,7 @@ Task CreateAsync(CreateQuestionDto questionDto); The related **DTO**: ````C# +[Serializable] public class CreateQuestionDto { [Required] diff --git a/docs/en/Best-Practices/Data-Transfer-Objects.md b/docs/en/Best-Practices/Data-Transfer-Objects.md index 2d25ce7f41..0c8580abb7 100644 --- a/docs/en/Best-Practices/Data-Transfer-Objects.md +++ b/docs/en/Best-Practices/Data-Transfer-Objects.md @@ -4,4 +4,5 @@ * **Do** inherit from the pre-built **base DTO classes** where possible and necessary (like `EntityDto`, `CreationAuditedEntityDto`, `AuditedEntityDto`, `FullAuditedEntityDto` and so on). * **Do** define DTO members with **public getter and setter**. * **Do** use **data annotations** for **validation** on the properties of DTOs those are inputs of the service. -* **Do** not add any **logic** into DTOs except implementing `IValidatableObject` when necessary. \ No newline at end of file +* **Do** not add any **logic** into DTOs except implementing `IValidatableObject` when necessary. +* **Do** mark all DTOs as **[Serializable]** since they are already serializable and developers may want to binary serialize them. \ No newline at end of file From ba5b7809ba42f64e554ac93e4671ae895de07a62 Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Mon, 10 Dec 2018 09:06:54 +0300 Subject: [PATCH 04/36] Added note for app services --- docs/en/Best-Practices/Application-Services.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/Best-Practices/Application-Services.md b/docs/en/Best-Practices/Application-Services.md index 9c17b6db21..7624464e17 100644 --- a/docs/en/Best-Practices/Application-Services.md +++ b/docs/en/Best-Practices/Application-Services.md @@ -188,6 +188,8 @@ This method votes a question and returns the current score of the question. * **Do** implement application service interfaces in the **application layer**. * **Do** use the naming convention. Ex: Create `ProductAppService` class for the `IProductAppService` interface. * **Do** inherit from the `ApplicationService` base class. +* **Do** make all public methods **virtual**, so developers may inherit and override them. +* **Do not** make **private** methods. Instead make them **protected virtual**, so developers may inherit and override them. #### Using Repositories From f8857633e02126fe62ec49d09700e845c9301d40 Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Mon, 10 Dec 2018 10:08:10 +0300 Subject: [PATCH 05/36] Add @abp/docs to package.json --- abp_io/src/Volo.AbpWebSite.Web/package.json | 3 +- .../wwwroot/libs/anchor-js/anchor.js | 335 +++ .../wwwroot/libs/clipboard/clipboard.js | 978 +++++++ .../wwwroot/libs/clipboard/clipboard.min.js | 7 + .../jquery.mCustomScrollbar.concat.min.js | 5 + .../jquery.mCustomScrollbar.css | 1267 +++++++++ .../jquery.mCustomScrollbar.js | 2458 +++++++++++++++++ .../mCSB_buttons.png | Bin 0 -> 2998 bytes .../package.json | 37 + .../malihu-custom-scrollbar-plugin/readme.md | 82 + .../wwwroot/libs/popper.js/popper.min.js | 5 + .../wwwroot/libs/prismjs/CHANGELOG.md | 1334 +++++++++ .../wwwroot/libs/prismjs/README.md | 26 + .../wwwroot/libs/prismjs/components.js | 2 + .../wwwroot/libs/prismjs/components.json | 867 ++++++ .../wwwroot/libs/prismjs/components/index.js | 82 + .../libs/prismjs/components/prism-abap.js | 48 + .../libs/prismjs/components/prism-abap.min.js | 1 + .../prismjs/components/prism-actionscript.js | 17 + .../components/prism-actionscript.min.js | 1 + .../libs/prismjs/components/prism-ada.js | 19 + .../libs/prismjs/components/prism-ada.min.js | 1 + .../prismjs/components/prism-apacheconf.js | 47 + .../components/prism-apacheconf.min.js | 1 + .../libs/prismjs/components/prism-apl.js | 32 + .../libs/prismjs/components/prism-apl.min.js | 1 + .../prismjs/components/prism-applescript.js | 20 + .../components/prism-applescript.min.js | 1 + .../libs/prismjs/components/prism-arduino.js | 5 + .../prismjs/components/prism-arduino.min.js | 1 + .../libs/prismjs/components/prism-arff.js | 10 + .../libs/prismjs/components/prism-arff.min.js | 1 + .../libs/prismjs/components/prism-asciidoc.js | 271 ++ .../prismjs/components/prism-asciidoc.min.js | 1 + .../libs/prismjs/components/prism-asm6502.js | 28 + .../prismjs/components/prism-asm6502.min.js | 1 + .../libs/prismjs/components/prism-aspnet.js | 36 + .../prismjs/components/prism-aspnet.min.js | 1 + .../prismjs/components/prism-autohotkey.js | 27 + .../components/prism-autohotkey.min.js | 1 + .../libs/prismjs/components/prism-autoit.js | 34 + .../prismjs/components/prism-autoit.min.js | 1 + .../libs/prismjs/components/prism-bash.js | 84 + .../libs/prismjs/components/prism-bash.min.js | 1 + .../libs/prismjs/components/prism-basic.js | 17 + .../prismjs/components/prism-basic.min.js | 1 + .../libs/prismjs/components/prism-batch.js | 99 + .../prismjs/components/prism-batch.min.js | 1 + .../libs/prismjs/components/prism-bison.js | 39 + .../prismjs/components/prism-bison.min.js | 1 + .../prismjs/components/prism-brainfuck.js | 20 + .../prismjs/components/prism-brainfuck.min.js | 1 + .../libs/prismjs/components/prism-bro.js | 48 + .../libs/prismjs/components/prism-bro.min.js | 1 + .../libs/prismjs/components/prism-c.js | 33 + .../libs/prismjs/components/prism-c.min.js | 1 + .../libs/prismjs/components/prism-clike.js | 30 + .../prismjs/components/prism-clike.min.js | 1 + .../libs/prismjs/components/prism-clojure.js | 13 + .../prismjs/components/prism-clojure.min.js | 1 + .../prismjs/components/prism-coffeescript.js | 91 + .../components/prism-coffeescript.min.js | 1 + .../libs/prismjs/components/prism-core.js | 557 ++++ .../libs/prismjs/components/prism-core.min.js | 1 + .../libs/prismjs/components/prism-cpp.js | 20 + .../libs/prismjs/components/prism-cpp.min.js | 1 + .../libs/prismjs/components/prism-crystal.js | 51 + .../prismjs/components/prism-crystal.min.js | 1 + .../libs/prismjs/components/prism-csharp.js | 79 + .../prismjs/components/prism-csharp.min.js | 1 + .../libs/prismjs/components/prism-csp.js | 25 + .../libs/prismjs/components/prism-csp.min.js | 1 + .../prismjs/components/prism-css-extras.js | 16 + .../components/prism-css-extras.min.js | 1 + .../libs/prismjs/components/prism-css.js | 52 + .../libs/prismjs/components/prism-css.min.js | 1 + .../libs/prismjs/components/prism-d.js | 64 + .../libs/prismjs/components/prism-d.min.js | 1 + .../libs/prismjs/components/prism-dart.js | 24 + .../libs/prismjs/components/prism-dart.min.js | 1 + .../libs/prismjs/components/prism-diff.js | 20 + .../libs/prismjs/components/prism-diff.min.js | 1 + .../libs/prismjs/components/prism-django.js | 41 + .../prismjs/components/prism-django.min.js | 1 + .../libs/prismjs/components/prism-docker.js | 11 + .../prismjs/components/prism-docker.min.js | 1 + .../libs/prismjs/components/prism-eiffel.js | 37 + .../prismjs/components/prism-eiffel.min.js | 1 + .../libs/prismjs/components/prism-elixir.js | 93 + .../prismjs/components/prism-elixir.min.js | 1 + .../libs/prismjs/components/prism-elm.js | 44 + .../libs/prismjs/components/prism-elm.min.js | 1 + .../libs/prismjs/components/prism-erb.js | 20 + .../libs/prismjs/components/prism-erb.min.js | 1 + .../libs/prismjs/components/prism-erlang.js | 44 + .../prismjs/components/prism-erlang.min.js | 1 + .../libs/prismjs/components/prism-flow.js | 34 + .../libs/prismjs/components/prism-flow.min.js | 1 + .../libs/prismjs/components/prism-fortran.js | 40 + .../prismjs/components/prism-fortran.min.js | 1 + .../libs/prismjs/components/prism-fsharp.js | 36 + .../prismjs/components/prism-fsharp.min.js | 1 + .../libs/prismjs/components/prism-gedcom.js | 28 + .../prismjs/components/prism-gedcom.min.js | 1 + .../libs/prismjs/components/prism-gherkin.js | 79 + .../prismjs/components/prism-gherkin.min.js | 1 + .../libs/prismjs/components/prism-git.js | 68 + .../libs/prismjs/components/prism-git.min.js | 1 + .../libs/prismjs/components/prism-glsl.js | 16 + .../libs/prismjs/components/prism-glsl.min.js | 1 + .../libs/prismjs/components/prism-go.js | 12 + .../libs/prismjs/components/prism-go.min.js | 1 + .../libs/prismjs/components/prism-graphql.js | 24 + .../prismjs/components/prism-graphql.min.js | 1 + .../libs/prismjs/components/prism-groovy.js | 65 + .../prismjs/components/prism-groovy.min.js | 1 + .../libs/prismjs/components/prism-haml.js | 154 ++ .../libs/prismjs/components/prism-haml.min.js | 1 + .../prismjs/components/prism-handlebars.js | 37 + .../components/prism-handlebars.min.js | 1 + .../libs/prismjs/components/prism-haskell.js | 36 + .../prismjs/components/prism-haskell.min.js | 1 + .../libs/prismjs/components/prism-haxe.js | 45 + .../libs/prismjs/components/prism-haxe.min.js | 1 + .../libs/prismjs/components/prism-hpkp.js | 20 + .../libs/prismjs/components/prism-hpkp.min.js | 1 + .../libs/prismjs/components/prism-hsts.js | 20 + .../libs/prismjs/components/prism-hsts.min.js | 1 + .../libs/prismjs/components/prism-http.js | 50 + .../libs/prismjs/components/prism-http.min.js | 1 + .../prismjs/components/prism-ichigojam.js | 15 + .../prismjs/components/prism-ichigojam.min.js | 1 + .../libs/prismjs/components/prism-icon.js | 20 + .../libs/prismjs/components/prism-icon.min.js | 1 + .../libs/prismjs/components/prism-inform7.js | 61 + .../prismjs/components/prism-inform7.min.js | 1 + .../libs/prismjs/components/prism-ini.js | 11 + .../libs/prismjs/components/prism-ini.min.js | 1 + .../libs/prismjs/components/prism-io.js | 31 + .../libs/prismjs/components/prism-io.min.js | 1 + .../libs/prismjs/components/prism-j.js | 25 + .../libs/prismjs/components/prism-j.min.js | 1 + .../libs/prismjs/components/prism-java.js | 27 + .../libs/prismjs/components/prism-java.min.js | 1 + .../prismjs/components/prism-javascript.js | 56 + .../components/prism-javascript.min.js | 1 + .../libs/prismjs/components/prism-jolie.js | 56 + .../prismjs/components/prism-jolie.min.js | 1 + .../libs/prismjs/components/prism-json.js | 14 + .../libs/prismjs/components/prism-json.min.js | 1 + .../libs/prismjs/components/prism-jsx.js | 125 + .../libs/prismjs/components/prism-jsx.min.js | 1 + .../libs/prismjs/components/prism-julia.js | 12 + .../prismjs/components/prism-julia.min.js | 1 + .../libs/prismjs/components/prism-keyman.js | 14 + .../prismjs/components/prism-keyman.min.js | 1 + .../libs/prismjs/components/prism-kotlin.js | 62 + .../prismjs/components/prism-kotlin.min.js | 1 + .../libs/prismjs/components/prism-latex.js | 61 + .../prismjs/components/prism-latex.min.js | 1 + .../libs/prismjs/components/prism-less.js | 60 + .../libs/prismjs/components/prism-less.min.js | 1 + .../libs/prismjs/components/prism-liquid.js | 12 + .../prismjs/components/prism-liquid.min.js | 1 + .../libs/prismjs/components/prism-lisp.js | 197 ++ .../libs/prismjs/components/prism-lisp.min.js | 1 + .../prismjs/components/prism-livescript.js | 119 + .../components/prism-livescript.min.js | 1 + .../libs/prismjs/components/prism-lolcode.js | 55 + .../prismjs/components/prism-lolcode.min.js | 1 + .../libs/prismjs/components/prism-lua.js | 20 + .../libs/prismjs/components/prism-lua.min.js | 1 + .../libs/prismjs/components/prism-makefile.js | 34 + .../prismjs/components/prism-makefile.min.js | 1 + .../libs/prismjs/components/prism-markdown.js | 120 + .../prismjs/components/prism-markdown.min.js | 1 + .../components/prism-markup-templating.js | 89 + .../components/prism-markup-templating.min.js | 1 + .../libs/prismjs/components/prism-markup.js | 56 + .../prismjs/components/prism-markup.min.js | 1 + .../libs/prismjs/components/prism-matlab.js | 16 + .../prismjs/components/prism-matlab.min.js | 1 + .../libs/prismjs/components/prism-mel.js | 43 + .../libs/prismjs/components/prism-mel.min.js | 1 + .../libs/prismjs/components/prism-mizar.js | 12 + .../prismjs/components/prism-mizar.min.js | 1 + .../libs/prismjs/components/prism-monkey.js | 31 + .../prismjs/components/prism-monkey.min.js | 1 + .../libs/prismjs/components/prism-n4js.js | 14 + .../libs/prismjs/components/prism-n4js.min.js | 1 + .../libs/prismjs/components/prism-nasm.js | 24 + .../libs/prismjs/components/prism-nasm.min.js | 1 + .../libs/prismjs/components/prism-nginx.js | 11 + .../prismjs/components/prism-nginx.min.js | 1 + .../libs/prismjs/components/prism-nim.js | 33 + .../libs/prismjs/components/prism-nim.min.js | 1 + .../libs/prismjs/components/prism-nix.js | 40 + .../libs/prismjs/components/prism-nix.min.js | 1 + .../libs/prismjs/components/prism-nsis.js | 29 + .../libs/prismjs/components/prism-nsis.min.js | 1 + .../prismjs/components/prism-objectivec.js | 5 + .../components/prism-objectivec.min.js | 1 + .../libs/prismjs/components/prism-ocaml.js | 27 + .../prismjs/components/prism-ocaml.min.js | 1 + .../libs/prismjs/components/prism-opencl.js | 49 + .../prismjs/components/prism-opencl.min.js | 1 + .../libs/prismjs/components/prism-oz.js | 25 + .../libs/prismjs/components/prism-oz.min.js | 1 + .../libs/prismjs/components/prism-parigp.js | 30 + .../prismjs/components/prism-parigp.min.js | 1 + .../libs/prismjs/components/prism-parser.js | 67 + .../prismjs/components/prism-parser.min.js | 1 + .../libs/prismjs/components/prism-pascal.js | 55 + .../prismjs/components/prism-pascal.min.js | 1 + .../libs/prismjs/components/prism-perl.js | 191 ++ .../libs/prismjs/components/prism-perl.min.js | 1 + .../prismjs/components/prism-php-extras.js | 11 + .../components/prism-php-extras.min.js | 1 + .../libs/prismjs/components/prism-php.js | 124 + .../libs/prismjs/components/prism-php.min.js | 1 + .../libs/prismjs/components/prism-plsql.js | 20 + .../prismjs/components/prism-plsql.min.js | 1 + .../prismjs/components/prism-powershell.js | 55 + .../components/prism-powershell.min.js | 1 + .../prismjs/components/prism-processing.js | 18 + .../components/prism-processing.min.js | 1 + .../libs/prismjs/components/prism-prolog.js | 20 + .../prismjs/components/prism-prolog.min.js | 1 + .../prismjs/components/prism-properties.js | 9 + .../components/prism-properties.min.js | 1 + .../libs/prismjs/components/prism-protobuf.js | 8 + .../prismjs/components/prism-protobuf.min.js | 1 + .../libs/prismjs/components/prism-pug.js | 198 ++ .../libs/prismjs/components/prism-pug.min.js | 1 + .../libs/prismjs/components/prism-puppet.js | 136 + .../prismjs/components/prism-puppet.min.js | 1 + .../libs/prismjs/components/prism-pure.js | 81 + .../libs/prismjs/components/prism-pure.min.js | 1 + .../libs/prismjs/components/prism-python.js | 29 + .../prismjs/components/prism-python.min.js | 1 + .../libs/prismjs/components/prism-q.js | 51 + .../libs/prismjs/components/prism-q.min.js | 1 + .../libs/prismjs/components/prism-qore.js | 20 + .../libs/prismjs/components/prism-qore.min.js | 1 + .../libs/prismjs/components/prism-r.js | 22 + .../libs/prismjs/components/prism-r.min.js | 1 + .../libs/prismjs/components/prism-reason.js | 32 + .../prismjs/components/prism-reason.min.js | 1 + .../libs/prismjs/components/prism-renpy.js | 29 + .../prismjs/components/prism-renpy.min.js | 1 + .../libs/prismjs/components/prism-rest.js | 205 ++ .../libs/prismjs/components/prism-rest.min.js | 1 + .../libs/prismjs/components/prism-rip.js | 32 + .../libs/prismjs/components/prism-rip.min.js | 1 + .../libs/prismjs/components/prism-roboconf.js | 27 + .../prismjs/components/prism-roboconf.min.js | 1 + .../libs/prismjs/components/prism-ruby.js | 131 + .../libs/prismjs/components/prism-ruby.min.js | 1 + .../libs/prismjs/components/prism-rust.js | 68 + .../libs/prismjs/components/prism-rust.min.js | 1 + .../libs/prismjs/components/prism-sas.js | 34 + .../libs/prismjs/components/prism-sas.min.js | 1 + .../libs/prismjs/components/prism-sass.js | 73 + .../libs/prismjs/components/prism-sass.min.js | 1 + .../libs/prismjs/components/prism-scala.js | 18 + .../prismjs/components/prism-scala.min.js | 1 + .../libs/prismjs/components/prism-scheme.js | 29 + .../prismjs/components/prism-scheme.min.js | 1 + .../libs/prismjs/components/prism-scss.js | 75 + .../libs/prismjs/components/prism-scss.min.js | 1 + .../prismjs/components/prism-smalltalk.js | 31 + .../prismjs/components/prism-smalltalk.min.js | 1 + .../libs/prismjs/components/prism-smarty.js | 96 + .../prismjs/components/prism-smarty.min.js | 1 + .../libs/prismjs/components/prism-soy.js | 96 + .../libs/prismjs/components/prism-soy.min.js | 1 + .../libs/prismjs/components/prism-sql.js | 18 + .../libs/prismjs/components/prism-sql.min.js | 1 + .../libs/prismjs/components/prism-stylus.js | 111 + .../prismjs/components/prism-stylus.min.js | 1 + .../libs/prismjs/components/prism-swift.js | 25 + .../prismjs/components/prism-swift.min.js | 1 + .../libs/prismjs/components/prism-tap.js | 20 + .../libs/prismjs/components/prism-tap.min.js | 1 + .../libs/prismjs/components/prism-tcl.js | 46 + .../libs/prismjs/components/prism-tcl.min.js | 1 + .../libs/prismjs/components/prism-textile.js | 257 ++ .../prismjs/components/prism-textile.min.js | 1 + .../libs/prismjs/components/prism-tsx.js | 2 + .../libs/prismjs/components/prism-tsx.min.js | 1 + .../libs/prismjs/components/prism-tt2.js | 59 + .../libs/prismjs/components/prism-tt2.min.js | 1 + .../libs/prismjs/components/prism-twig.js | 46 + .../libs/prismjs/components/prism-twig.min.js | 1 + .../prismjs/components/prism-typescript.js | 7 + .../components/prism-typescript.min.js | 1 + .../libs/prismjs/components/prism-vbnet.js | 15 + .../prismjs/components/prism-vbnet.min.js | 1 + .../libs/prismjs/components/prism-velocity.js | 72 + .../prismjs/components/prism-velocity.min.js | 1 + .../libs/prismjs/components/prism-verilog.js | 20 + .../prismjs/components/prism-verilog.min.js | 1 + .../libs/prismjs/components/prism-vhdl.js | 23 + .../libs/prismjs/components/prism-vhdl.min.js | 1 + .../libs/prismjs/components/prism-vim.js | 10 + .../libs/prismjs/components/prism-vim.min.js | 1 + .../prismjs/components/prism-visual-basic.js | 34 + .../components/prism-visual-basic.min.js | 1 + .../libs/prismjs/components/prism-wasm.js | 31 + .../libs/prismjs/components/prism-wasm.min.js | 1 + .../libs/prismjs/components/prism-wiki.js | 81 + .../libs/prismjs/components/prism-wiki.min.js | 1 + .../libs/prismjs/components/prism-xeora.js | 114 + .../prismjs/components/prism-xeora.min.js | 1 + .../libs/prismjs/components/prism-xojo.js | 20 + .../libs/prismjs/components/prism-xojo.min.js | 1 + .../libs/prismjs/components/prism-xquery.js | 164 ++ .../prismjs/components/prism-xquery.min.js | 1 + .../libs/prismjs/components/prism-yaml.js | 45 + .../libs/prismjs/components/prism-yaml.min.js | 1 + .../wwwroot/libs/prismjs/package.json | 47 + .../plugins/autolinker/prism-autolinker.css | 3 + .../plugins/autolinker/prism-autolinker.js | 81 + .../autolinker/prism-autolinker.min.js | 1 + .../plugins/autoloader/prism-autoloader.js | 209 ++ .../autoloader/prism-autoloader.min.js | 1 + .../command-line/prism-command-line.css | 33 + .../command-line/prism-command-line.js | 139 + .../command-line/prism-command-line.min.js | 1 + .../prism-copy-to-clipboard.js | 75 + .../prism-copy-to-clipboard.min.js | 1 + .../custom-class/prism-custom-class.js | 31 + .../custom-class/prism-custom-class.min.js | 1 + .../prism-data-uri-highlight.js | 98 + .../prism-data-uri-highlight.min.js | 1 + .../file-highlight/prism-file-highlight.js | 90 + .../prism-file-highlight.min.js | 1 + .../prism-highlight-keywords.js | 17 + .../prism-highlight-keywords.min.js | 1 + .../jsonp-highlight/prism-jsonp-highlight.js | 151 + .../prism-jsonp-highlight.min.js | 1 + .../plugins/keep-markup/prism-keep-markup.js | 99 + .../keep-markup/prism-keep-markup.min.js | 1 + .../line-highlight/prism-line-highlight.css | 49 + .../line-highlight/prism-line-highlight.js | 181 ++ .../prism-line-highlight.min.js | 1 + .../line-numbers/prism-line-numbers.css | 41 + .../line-numbers/prism-line-numbers.js | 159 ++ .../line-numbers/prism-line-numbers.min.js | 1 + .../prism-normalize-whitespace.js | 190 ++ .../prism-normalize-whitespace.min.js | 1 + .../plugins/previewers/prism-previewers.css | 242 ++ .../plugins/previewers/prism-previewers.js | 715 +++++ .../previewers/prism-previewers.min.js | 1 + .../prism-remove-initial-line-feed.js | 21 + .../prism-remove-initial-line-feed.min.js | 1 + .../show-invisibles/prism-show-invisibles.css | 33 + .../show-invisibles/prism-show-invisibles.js | 21 + .../prism-show-invisibles.min.js | 1 + .../show-language/prism-show-language.js | 31 + .../show-language/prism-show-language.min.js | 1 + .../prismjs/plugins/toolbar/prism-toolbar.css | 58 + .../prismjs/plugins/toolbar/prism-toolbar.js | 137 + .../plugins/toolbar/prism-toolbar.min.js | 1 + .../prism-unescaped-markup.css | 10 + .../prism-unescaped-markup.js | 44 + .../prism-unescaped-markup.min.js | 1 + .../libs/prismjs/plugins/wpd/prism-wpd.css | 11 + .../libs/prismjs/plugins/wpd/prism-wpd.js | 169 ++ .../libs/prismjs/plugins/wpd/prism-wpd.min.js | 1 + .../wwwroot/libs/prismjs/prism.js | 875 ++++++ .../wwwroot/libs/prismjs/themes/prism-coy.css | 225 ++ .../libs/prismjs/themes/prism-dark.css | 128 + .../libs/prismjs/themes/prism-funky.css | 116 + .../libs/prismjs/themes/prism-okaidia.css | 122 + .../prismjs/themes/prism-solarizedlight.css | 149 + .../libs/prismjs/themes/prism-tomorrow.css | 121 + .../libs/prismjs/themes/prism-twilight.css | 198 ++ .../wwwroot/libs/prismjs/themes/prism.css | 138 + abp_io/src/Volo.AbpWebSite.Web/yarn.lock | 93 +- 380 files changed, 21090 insertions(+), 2 deletions(-) create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/anchor-js/anchor.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/clipboard/clipboard.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/clipboard/clipboard.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/package.json create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/readme.md create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/popper.js/popper.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/CHANGELOG.md create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/README.md create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components.json create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/index.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-abap.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-abap.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-actionscript.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-actionscript.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ada.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ada.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-apacheconf.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-apacheconf.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-apl.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-apl.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-applescript.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-applescript.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-arduino.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-arduino.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-arff.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-arff.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-asciidoc.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-asciidoc.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-asm6502.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-asm6502.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-aspnet.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-aspnet.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-autohotkey.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-autohotkey.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-autoit.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-autoit.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-bash.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-bash.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-basic.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-basic.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-batch.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-batch.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-bison.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-bison.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-brainfuck.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-brainfuck.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-bro.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-bro.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-c.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-c.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-clike.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-clike.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-clojure.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-clojure.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-coffeescript.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-coffeescript.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-core.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-core.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-cpp.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-cpp.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-crystal.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-crystal.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-csharp.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-csharp.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-csp.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-csp.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-css-extras.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-css-extras.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-css.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-css.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-d.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-d.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-dart.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-dart.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-diff.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-diff.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-django.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-django.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-docker.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-docker.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-eiffel.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-eiffel.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-elixir.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-elixir.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-elm.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-elm.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-erb.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-erb.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-erlang.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-erlang.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-flow.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-flow.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-fortran.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-fortran.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-fsharp.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-fsharp.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-gedcom.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-gedcom.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-gherkin.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-gherkin.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-git.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-git.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-glsl.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-glsl.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-go.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-go.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-graphql.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-graphql.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-groovy.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-groovy.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-haml.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-haml.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-handlebars.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-handlebars.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-haskell.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-haskell.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-haxe.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-haxe.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-hpkp.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-hpkp.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-hsts.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-hsts.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-http.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-http.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ichigojam.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ichigojam.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-icon.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-icon.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-inform7.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-inform7.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ini.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ini.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-io.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-io.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-j.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-j.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-java.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-java.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-javascript.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-javascript.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-jolie.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-jolie.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-json.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-json.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-jsx.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-jsx.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-julia.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-julia.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-keyman.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-keyman.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-kotlin.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-kotlin.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-latex.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-latex.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-less.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-less.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-liquid.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-liquid.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-lisp.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-lisp.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-livescript.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-livescript.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-lolcode.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-lolcode.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-lua.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-lua.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-makefile.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-makefile.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-markdown.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-markdown.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-markup-templating.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-markup-templating.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-markup.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-markup.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-matlab.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-matlab.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-mel.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-mel.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-mizar.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-mizar.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-monkey.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-monkey.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-n4js.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-n4js.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nasm.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nasm.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nginx.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nginx.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nim.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nim.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nix.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nix.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nsis.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-nsis.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-objectivec.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-objectivec.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ocaml.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ocaml.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-opencl.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-opencl.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-oz.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-oz.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-parigp.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-parigp.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-parser.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-parser.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-pascal.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-pascal.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-perl.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-perl.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-php-extras.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-php-extras.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-php.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-php.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-plsql.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-plsql.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-powershell.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-powershell.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-processing.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-processing.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-prolog.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-prolog.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-properties.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-properties.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-protobuf.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-protobuf.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-pug.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-pug.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-puppet.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-puppet.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-pure.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-pure.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-python.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-python.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-q.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-q.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-qore.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-qore.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-r.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-r.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-reason.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-reason.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-renpy.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-renpy.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-rest.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-rest.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-rip.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-rip.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-roboconf.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-roboconf.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ruby.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-ruby.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-rust.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-rust.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-sas.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-sas.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-sass.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-sass.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-scala.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-scala.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-scheme.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-scheme.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-scss.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-scss.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-smalltalk.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-smalltalk.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-smarty.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-smarty.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-soy.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-soy.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-sql.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-sql.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-stylus.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-stylus.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-swift.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-swift.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-tap.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-tap.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-tcl.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-tcl.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-textile.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-textile.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-tsx.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-tsx.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-tt2.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-tt2.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-twig.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-twig.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-typescript.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-typescript.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-vbnet.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-vbnet.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-velocity.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-velocity.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-verilog.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-verilog.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-vhdl.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-vhdl.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-vim.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-vim.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-visual-basic.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-visual-basic.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-wasm.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-wasm.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-wiki.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-wiki.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-xeora.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-xeora.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-xojo.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-xojo.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-xquery.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-xquery.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-yaml.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/components/prism-yaml.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/package.json create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/autolinker/prism-autolinker.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/autolinker/prism-autolinker.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/autolinker/prism-autolinker.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/autoloader/prism-autoloader.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/autoloader/prism-autoloader.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/command-line/prism-command-line.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/command-line/prism-command-line.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/command-line/prism-command-line.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/custom-class/prism-custom-class.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/custom-class/prism-custom-class.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/data-uri-highlight/prism-data-uri-highlight.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/data-uri-highlight/prism-data-uri-highlight.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/file-highlight/prism-file-highlight.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/file-highlight/prism-file-highlight.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/highlight-keywords/prism-highlight-keywords.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/highlight-keywords/prism-highlight-keywords.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/jsonp-highlight/prism-jsonp-highlight.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/jsonp-highlight/prism-jsonp-highlight.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/keep-markup/prism-keep-markup.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/keep-markup/prism-keep-markup.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/line-highlight/prism-line-highlight.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/line-highlight/prism-line-highlight.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/line-highlight/prism-line-highlight.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/line-numbers/prism-line-numbers.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/line-numbers/prism-line-numbers.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/line-numbers/prism-line-numbers.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/normalize-whitespace/prism-normalize-whitespace.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/normalize-whitespace/prism-normalize-whitespace.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/previewers/prism-previewers.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/previewers/prism-previewers.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/previewers/prism-previewers.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/show-invisibles/prism-show-invisibles.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/show-invisibles/prism-show-invisibles.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/show-invisibles/prism-show-invisibles.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/show-language/prism-show-language.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/show-language/prism-show-language.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/toolbar/prism-toolbar.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/toolbar/prism-toolbar.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/toolbar/prism-toolbar.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/unescaped-markup/prism-unescaped-markup.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/unescaped-markup/prism-unescaped-markup.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/unescaped-markup/prism-unescaped-markup.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.min.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/prism.js create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-coy.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-dark.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-funky.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-okaidia.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-solarizedlight.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-tomorrow.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-twilight.css create mode 100644 abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism.css diff --git a/abp_io/src/Volo.AbpWebSite.Web/package.json b/abp_io/src/Volo.AbpWebSite.Web/package.json index 082a9cd899..4ea43ebe02 100644 --- a/abp_io/src/Volo.AbpWebSite.Web/package.json +++ b/abp_io/src/Volo.AbpWebSite.Web/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@abp/aspnetcore.mvc.ui.theme.basic": "^0.4.9", - "@abp/blogging": "^0.4.9" + "@abp/blogging": "^0.4.9", + "@abp/docs": "^0.5.1" } } diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/anchor-js/anchor.js b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/anchor-js/anchor.js new file mode 100644 index 0000000000..38a3b62a66 --- /dev/null +++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/anchor-js/anchor.js @@ -0,0 +1,335 @@ +/* eslint-env amd, node */ + +// https://github.com/umdjs/umd/blob/master/templates/returnExports.js +(function (root, factory) { + 'use strict'; + + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof module === 'object' && module.exports) { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.AnchorJS = factory(); + root.anchors = new root.AnchorJS(); + } +}(this, function () { + 'use strict'; + + function AnchorJS(options) { + this.options = options || {}; + this.elements = []; + + /** + * Assigns options to the internal options object, and provides defaults. + * @param {Object} opts - Options object + */ + function _applyRemainingDefaultOptions(opts) { + opts.icon = opts.hasOwnProperty('icon') ? opts.icon : '\ue9cb'; // Accepts characters (and also URLs?), like '#', '¶', '❡', or '§'. + opts.visible = opts.hasOwnProperty('visible') ? opts.visible : 'hover'; // Also accepts 'always' & 'touch' + opts.placement = opts.hasOwnProperty('placement') ? opts.placement : 'right'; // Also accepts 'left' + opts.ariaLabel = opts.hasOwnProperty('ariaLabel') ? opts.ariaLabel : 'Anchor'; // Accepts any text. + opts.class = opts.hasOwnProperty('class') ? opts.class : ''; // Accepts any class name. + // Using Math.floor here will ensure the value is Number-cast and an integer. + opts.truncate = opts.hasOwnProperty('truncate') ? Math.floor(opts.truncate) : 64; // Accepts any value that can be typecast to a number. + } + + _applyRemainingDefaultOptions(this.options); + + /** + * Checks to see if this device supports touch. Uses criteria pulled from Modernizr: + * https://github.com/Modernizr/Modernizr/blob/da22eb27631fc4957f67607fe6042e85c0a84656/feature-detects/touchevents.js#L40 + * @return {Boolean} - true if the current device supports touch. + */ + this.isTouchDevice = function() { + return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); + }; + + /** + * Add anchor links to page elements. + * @param {String|Array|Nodelist} selector - A CSS selector for targeting the elements you wish to add anchor links + * to. Also accepts an array or nodeList containing the relavant elements. + * @return {this} - The AnchorJS object + */ + this.add = function(selector) { + var elements, + elsWithIds, + idList, + elementID, + i, + index, + count, + tidyText, + newTidyText, + readableID, + anchor, + visibleOptionToUse, + indexesToDrop = []; + + // We reapply options here because somebody may have overwritten the default options object when setting options. + // For example, this overwrites all options but visible: + // + // anchors.options = { visible: 'always'; } + _applyRemainingDefaultOptions(this.options); + + visibleOptionToUse = this.options.visible; + if (visibleOptionToUse === 'touch') { + visibleOptionToUse = this.isTouchDevice() ? 'always' : 'hover'; + } + + // Provide a sensible default selector, if none is given. + if (!selector) { + selector = 'h2, h3, h4, h5, h6'; + } + + elements = _getElements(selector); + + if (elements.length === 0) { + return this; + } + + _addBaselineStyles(); + + // We produce a list of existing IDs so we don't generate a duplicate. + elsWithIds = document.querySelectorAll('[id]'); + idList = [].map.call(elsWithIds, function assign(el) { + return el.id; + }); + + for (i = 0; i < elements.length; i++) { + if (this.hasAnchorJSLink(elements[i])) { + indexesToDrop.push(i); + continue; + } + + if (elements[i].hasAttribute('id')) { + elementID = elements[i].getAttribute('id'); + } else if (elements[i].hasAttribute('data-anchor-id')) { + elementID = elements[i].getAttribute('data-anchor-id'); + } else { + tidyText = this.urlify(elements[i].textContent); + + // Compare our generated ID to existing IDs (and increment it if needed) + // before we add it to the page. + newTidyText = tidyText; + count = 0; + do { + if (index !== undefined) { + newTidyText = tidyText + '-' + count; + } + + index = idList.indexOf(newTidyText); + count += 1; + } while (index !== -1); + index = undefined; + idList.push(newTidyText); + + elements[i].setAttribute('id', newTidyText); + elementID = newTidyText; + } + + readableID = elementID.replace(/-/g, ' '); + + // The following code builds the following DOM structure in a more effiecient (albeit opaque) way. + // ''; + anchor = document.createElement('a'); + anchor.className = 'anchorjs-link ' + this.options.class; + anchor.href = '#' + elementID; + anchor.setAttribute('aria-label', this.options.ariaLabel); + anchor.setAttribute('data-anchorjs-icon', this.options.icon); + + if (visibleOptionToUse === 'always') { + anchor.style.opacity = '1'; + } + + if (this.options.icon === '\ue9cb') { + anchor.style.font = '1em/1 anchorjs-icons'; + + // We set lineHeight = 1 here because the `anchorjs-icons` font family could otherwise affect the + // height of the heading. This isn't the case for icons with `placement: left`, so we restore + // line-height: inherit in that case, ensuring they remain positioned correctly. For more info, + // see https://github.com/bryanbraun/anchorjs/issues/39. + if (this.options.placement === 'left') { + anchor.style.lineHeight = 'inherit'; + } + } + + if (this.options.placement === 'left') { + anchor.style.position = 'absolute'; + anchor.style.marginLeft = '-1em'; + anchor.style.paddingRight = '0.5em'; + elements[i].insertBefore(anchor, elements[i].firstChild); + } else { // if the option provided is `right` (or anything else). + anchor.style.paddingLeft = '0.375em'; + elements[i].appendChild(anchor); + } + } + + for (i = 0; i < indexesToDrop.length; i++) { + elements.splice(indexesToDrop[i] - i, 1); + } + this.elements = this.elements.concat(elements); + + return this; + }; + + /** + * Removes all anchorjs-links from elements targed by the selector. + * @param {String|Array|Nodelist} selector - A CSS selector string targeting elements with anchor links, + * OR a nodeList / array containing the DOM elements. + * @return {this} - The AnchorJS object + */ + this.remove = function(selector) { + var index, + domAnchor, + elements = _getElements(selector); + + for (var i = 0; i < elements.length; i++) { + domAnchor = elements[i].querySelector('.anchorjs-link'); + if (domAnchor) { + // Drop the element from our main list, if it's in there. + index = this.elements.indexOf(elements[i]); + if (index !== -1) { + this.elements.splice(index, 1); + } + // Remove the anchor from the DOM. + elements[i].removeChild(domAnchor); + } + } + return this; + }; + + /** + * Removes all anchorjs links. Mostly used for tests. + */ + this.removeAll = function() { + this.remove(this.elements); + }; + + /** + * Urlify - Refine text so it makes a good ID. + * + * To do this, we remove apostrophes, replace nonsafe characters with hyphens, + * remove extra hyphens, truncate, trim hyphens, and make lowercase. + * + * @param {String} text - Any text. Usually pulled from the webpage element we are linking to. + * @return {String} - hyphen-delimited text for use in IDs and URLs. + */ + this.urlify = function(text) { + // Regex for finding the nonsafe URL characters (many need escaping): & +$,:;=?@"#{}|^~[`%!'<>]./()*\ (newlines, tabs, backspace, & vertical tabs) + var nonsafeChars = /[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\\n\t\b\v]/g, + urlText; + + // The reason we include this _applyRemainingDefaultOptions is so urlify can be called independently, + // even after setting options. This can be useful for tests or other applications. + if (!this.options.truncate) { + _applyRemainingDefaultOptions(this.options); + } + + // Note: we trim hyphens after truncating because truncating can cause dangling hyphens. + // Example string: // " ⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean." + urlText = text.trim() // "⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean." + .replace(/\'/gi, '') // "⚡⚡ Dont forget: URL fragments should be i18n-friendly, hyphenated, short, and clean." + .replace(nonsafeChars, '-') // "⚡⚡-Dont-forget--URL-fragments-should-be-i18n-friendly--hyphenated--short--and-clean-" + .replace(/-{2,}/g, '-') // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-short-and-clean-" + .substring(0, this.options.truncate) // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-" + .replace(/^-+|-+$/gm, '') // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated" + .toLowerCase(); // "⚡⚡-dont-forget-url-fragments-should-be-i18n-friendly-hyphenated" + + return urlText; + }; + + /** + * Determines if this element already has an AnchorJS link on it. + * Uses this technique: http://stackoverflow.com/a/5898748/1154642 + * @param {HTMLElemnt} el - a DOM node + * @return {Boolean} true/false + */ + this.hasAnchorJSLink = function(el) { + var hasLeftAnchor = el.firstChild && ((' ' + el.firstChild.className + ' ').indexOf(' anchorjs-link ') > -1), + hasRightAnchor = el.lastChild && ((' ' + el.lastChild.className + ' ').indexOf(' anchorjs-link ') > -1); + + return hasLeftAnchor || hasRightAnchor || false; + }; + + /** + * Turns a selector, nodeList, or array of elements into an array of elements (so we can use array methods). + * It also throws errors on any other inputs. Used to handle inputs to .add and .remove. + * @param {String|Array|Nodelist} input - A CSS selector string targeting elements with anchor links, + * OR a nodeList / array containing the DOM elements. + * @return {Array} - An array containing the elements we want. + */ + function _getElements(input) { + var elements; + if (typeof input === 'string' || input instanceof String) { + // See https://davidwalsh.name/nodelist-array for the technique transforming nodeList -> Array. + elements = [].slice.call(document.querySelectorAll(input)); + // I checked the 'input instanceof NodeList' test in IE9 and modern browsers and it worked for me. + } else if (Array.isArray(input) || input instanceof NodeList) { + elements = [].slice.call(input); + } else { + throw new Error('The selector provided to AnchorJS was invalid.'); + } + return elements; + } + + /** + * _addBaselineStyles + * Adds baseline styles to the page, used by all AnchorJS links irregardless of configuration. + */ + function _addBaselineStyles() { + // We don't want to add global baseline styles if they've been added before. + if (document.head.querySelector('style.anchorjs') !== null) { + return; + } + + var style = document.createElement('style'), + linkRule = + ' .anchorjs-link {' + + ' opacity: 0;' + + ' text-decoration: none;' + + ' -webkit-font-smoothing: antialiased;' + + ' -moz-osx-font-smoothing: grayscale;' + + ' }', + hoverRule = + ' *:hover > .anchorjs-link,' + + ' .anchorjs-link:focus {' + + ' opacity: 1;' + + ' }', + anchorjsLinkFontFace = + ' @font-face {' + + ' font-family: "anchorjs-icons";' + // Icon from icomoon; 10px wide & 10px tall; 2 empty below & 4 above + ' src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype");' + + ' }', + pseudoElContent = + ' [data-anchorjs-icon]::after {' + + ' content: attr(data-anchorjs-icon);' + + ' }', + firstStyleEl; + + style.className = 'anchorjs'; + style.appendChild(document.createTextNode('')); // Necessary for Webkit. + + // We place it in the head with the other style tags, if possible, so as to + // not look out of place. We insert before the others so these styles can be + // overridden if necessary. + firstStyleEl = document.head.querySelector('[rel="stylesheet"], style'); + if (firstStyleEl === undefined) { + document.head.appendChild(style); + } else { + document.head.insertBefore(style, firstStyleEl); + } + + style.sheet.insertRule(linkRule, style.sheet.cssRules.length); + style.sheet.insertRule(hoverRule, style.sheet.cssRules.length); + style.sheet.insertRule(pseudoElContent, style.sheet.cssRules.length); + style.sheet.insertRule(anchorjsLinkFontFace, style.sheet.cssRules.length); + } + } + + return AnchorJS; +})); diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/clipboard/clipboard.js b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/clipboard/clipboard.js new file mode 100644 index 0000000000..14cb08654f --- /dev/null +++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/clipboard/clipboard.js @@ -0,0 +1,978 @@ +/*! + * clipboard.js v2.0.4 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["ClipboardJS"] = factory(); + else + root["ClipboardJS"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _clipboardAction = __webpack_require__(1); + +var _clipboardAction2 = _interopRequireDefault(_clipboardAction); + +var _tinyEmitter = __webpack_require__(3); + +var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter); + +var _goodListener = __webpack_require__(4); + +var _goodListener2 = _interopRequireDefault(_goodListener); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +/** + * Base class which takes one or more elements, adds event listeners to them, + * and instantiates a new `ClipboardAction` on each click. + */ +var Clipboard = function (_Emitter) { + _inherits(Clipboard, _Emitter); + + /** + * @param {String|HTMLElement|HTMLCollection|NodeList} trigger + * @param {Object} options + */ + function Clipboard(trigger, options) { + _classCallCheck(this, Clipboard); + + var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this)); + + _this.resolveOptions(options); + _this.listenClick(trigger); + return _this; + } + + /** + * Defines if attributes would be resolved using internal setter functions + * or custom functions that were passed in the constructor. + * @param {Object} options + */ + + + _createClass(Clipboard, [{ + key: 'resolveOptions', + value: function resolveOptions() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + this.action = typeof options.action === 'function' ? options.action : this.defaultAction; + this.target = typeof options.target === 'function' ? options.target : this.defaultTarget; + this.text = typeof options.text === 'function' ? options.text : this.defaultText; + this.container = _typeof(options.container) === 'object' ? options.container : document.body; + } + + /** + * Adds a click event listener to the passed trigger. + * @param {String|HTMLElement|HTMLCollection|NodeList} trigger + */ + + }, { + key: 'listenClick', + value: function listenClick(trigger) { + var _this2 = this; + + this.listener = (0, _goodListener2.default)(trigger, 'click', function (e) { + return _this2.onClick(e); + }); + } + + /** + * Defines a new `ClipboardAction` on each click event. + * @param {Event} e + */ + + }, { + key: 'onClick', + value: function onClick(e) { + var trigger = e.delegateTarget || e.currentTarget; + + if (this.clipboardAction) { + this.clipboardAction = null; + } + + this.clipboardAction = new _clipboardAction2.default({ + action: this.action(trigger), + target: this.target(trigger), + text: this.text(trigger), + container: this.container, + trigger: trigger, + emitter: this + }); + } + + /** + * Default `action` lookup function. + * @param {Element} trigger + */ + + }, { + key: 'defaultAction', + value: function defaultAction(trigger) { + return getAttributeValue('action', trigger); + } + + /** + * Default `target` lookup function. + * @param {Element} trigger + */ + + }, { + key: 'defaultTarget', + value: function defaultTarget(trigger) { + var selector = getAttributeValue('target', trigger); + + if (selector) { + return document.querySelector(selector); + } + } + + /** + * Returns the support of the given action, or all actions if no action is + * given. + * @param {String} [action] + */ + + }, { + key: 'defaultText', + + + /** + * Default `text` lookup function. + * @param {Element} trigger + */ + value: function defaultText(trigger) { + return getAttributeValue('text', trigger); + } + + /** + * Destroy lifecycle. + */ + + }, { + key: 'destroy', + value: function destroy() { + this.listener.destroy(); + + if (this.clipboardAction) { + this.clipboardAction.destroy(); + this.clipboardAction = null; + } + } + }], [{ + key: 'isSupported', + value: function isSupported() { + var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut']; + + var actions = typeof action === 'string' ? [action] : action; + var support = !!document.queryCommandSupported; + + actions.forEach(function (action) { + support = support && !!document.queryCommandSupported(action); + }); + + return support; + } + }]); + + return Clipboard; +}(_tinyEmitter2.default); + +/** + * Helper function to retrieve attribute value. + * @param {String} suffix + * @param {Element} element + */ + + +function getAttributeValue(suffix, element) { + var attribute = 'data-clipboard-' + suffix; + + if (!element.hasAttribute(attribute)) { + return; + } + + return element.getAttribute(attribute); +} + +module.exports = Clipboard; + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _select = __webpack_require__(2); + +var _select2 = _interopRequireDefault(_select); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** + * Inner class which performs selection from either `text` or `target` + * properties and then executes copy or cut operations. + */ +var ClipboardAction = function () { + /** + * @param {Object} options + */ + function ClipboardAction(options) { + _classCallCheck(this, ClipboardAction); + + this.resolveOptions(options); + this.initSelection(); + } + + /** + * Defines base properties passed from constructor. + * @param {Object} options + */ + + + _createClass(ClipboardAction, [{ + key: 'resolveOptions', + value: function resolveOptions() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + this.action = options.action; + this.container = options.container; + this.emitter = options.emitter; + this.target = options.target; + this.text = options.text; + this.trigger = options.trigger; + + this.selectedText = ''; + } + + /** + * Decides which selection strategy is going to be applied based + * on the existence of `text` and `target` properties. + */ + + }, { + key: 'initSelection', + value: function initSelection() { + if (this.text) { + this.selectFake(); + } else if (this.target) { + this.selectTarget(); + } + } + + /** + * Creates a fake textarea element, sets its value from `text` property, + * and makes a selection on it. + */ + + }, { + key: 'selectFake', + value: function selectFake() { + var _this = this; + + var isRTL = document.documentElement.getAttribute('dir') == 'rtl'; + + this.removeFake(); + + this.fakeHandlerCallback = function () { + return _this.removeFake(); + }; + this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true; + + this.fakeElem = document.createElement('textarea'); + // Prevent zooming on iOS + this.fakeElem.style.fontSize = '12pt'; + // Reset box model + this.fakeElem.style.border = '0'; + this.fakeElem.style.padding = '0'; + this.fakeElem.style.margin = '0'; + // Move element out of screen horizontally + this.fakeElem.style.position = 'absolute'; + this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px'; + // Move element to the same position vertically + var yPosition = window.pageYOffset || document.documentElement.scrollTop; + this.fakeElem.style.top = yPosition + 'px'; + + this.fakeElem.setAttribute('readonly', ''); + this.fakeElem.value = this.text; + + this.container.appendChild(this.fakeElem); + + this.selectedText = (0, _select2.default)(this.fakeElem); + this.copyText(); + } + + /** + * Only removes the fake element after another click event, that way + * a user can hit `Ctrl+C` to copy because selection still exists. + */ + + }, { + key: 'removeFake', + value: function removeFake() { + if (this.fakeHandler) { + this.container.removeEventListener('click', this.fakeHandlerCallback); + this.fakeHandler = null; + this.fakeHandlerCallback = null; + } + + if (this.fakeElem) { + this.container.removeChild(this.fakeElem); + this.fakeElem = null; + } + } + + /** + * Selects the content from element passed on `target` property. + */ + + }, { + key: 'selectTarget', + value: function selectTarget() { + this.selectedText = (0, _select2.default)(this.target); + this.copyText(); + } + + /** + * Executes the copy operation based on the current selection. + */ + + }, { + key: 'copyText', + value: function copyText() { + var succeeded = void 0; + + try { + succeeded = document.execCommand(this.action); + } catch (err) { + succeeded = false; + } + + this.handleResult(succeeded); + } + + /** + * Fires an event based on the copy operation result. + * @param {Boolean} succeeded + */ + + }, { + key: 'handleResult', + value: function handleResult(succeeded) { + this.emitter.emit(succeeded ? 'success' : 'error', { + action: this.action, + text: this.selectedText, + trigger: this.trigger, + clearSelection: this.clearSelection.bind(this) + }); + } + + /** + * Moves focus away from `target` and back to the trigger, removes current selection. + */ + + }, { + key: 'clearSelection', + value: function clearSelection() { + if (this.trigger) { + this.trigger.focus(); + } + + window.getSelection().removeAllRanges(); + } + + /** + * Sets the `action` to be performed which can be either 'copy' or 'cut'. + * @param {String} action + */ + + }, { + key: 'destroy', + + + /** + * Destroy lifecycle. + */ + value: function destroy() { + this.removeFake(); + } + }, { + key: 'action', + set: function set() { + var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy'; + + this._action = action; + + if (this._action !== 'copy' && this._action !== 'cut') { + throw new Error('Invalid "action" value, use either "copy" or "cut"'); + } + } + + /** + * Gets the `action` property. + * @return {String} + */ + , + get: function get() { + return this._action; + } + + /** + * Sets the `target` property using an element + * that will be have its content copied. + * @param {Element} target + */ + + }, { + key: 'target', + set: function set(target) { + if (target !== undefined) { + if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) { + if (this.action === 'copy' && target.hasAttribute('disabled')) { + throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'); + } + + if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) { + throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes'); + } + + this._target = target; + } else { + throw new Error('Invalid "target" value, use a valid Element'); + } + } + } + + /** + * Gets the `target` property. + * @return {String|HTMLElement} + */ + , + get: function get() { + return this._target; + } + }]); + + return ClipboardAction; +}(); + +module.exports = ClipboardAction; + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + +function select(element) { + var selectedText; + + if (element.nodeName === 'SELECT') { + element.focus(); + + selectedText = element.value; + } + else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') { + var isReadOnly = element.hasAttribute('readonly'); + + if (!isReadOnly) { + element.setAttribute('readonly', ''); + } + + element.select(); + element.setSelectionRange(0, element.value.length); + + if (!isReadOnly) { + element.removeAttribute('readonly'); + } + + selectedText = element.value; + } + else { + if (element.hasAttribute('contenteditable')) { + element.focus(); + } + + var selection = window.getSelection(); + var range = document.createRange(); + + range.selectNodeContents(element); + selection.removeAllRanges(); + selection.addRange(range); + + selectedText = selection.toString(); + } + + return selectedText; +} + +module.exports = select; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + +function E () { + // Keep this empty so it's easier to inherit from + // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3) +} + +E.prototype = { + on: function (name, callback, ctx) { + var e = this.e || (this.e = {}); + + (e[name] || (e[name] = [])).push({ + fn: callback, + ctx: ctx + }); + + return this; + }, + + once: function (name, callback, ctx) { + var self = this; + function listener () { + self.off(name, listener); + callback.apply(ctx, arguments); + }; + + listener._ = callback + return this.on(name, listener, ctx); + }, + + emit: function (name) { + var data = [].slice.call(arguments, 1); + var evtArr = ((this.e || (this.e = {}))[name] || []).slice(); + var i = 0; + var len = evtArr.length; + + for (i; i < len; i++) { + evtArr[i].fn.apply(evtArr[i].ctx, data); + } + + return this; + }, + + off: function (name, callback) { + var e = this.e || (this.e = {}); + var evts = e[name]; + var liveEvents = []; + + if (evts && callback) { + for (var i = 0, len = evts.length; i < len; i++) { + if (evts[i].fn !== callback && evts[i].fn._ !== callback) + liveEvents.push(evts[i]); + } + } + + // Remove event from queue to prevent memory leak + // Suggested by https://github.com/lazd + // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910 + + (liveEvents.length) + ? e[name] = liveEvents + : delete e[name]; + + return this; + } +}; + +module.exports = E; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +var is = __webpack_require__(5); +var delegate = __webpack_require__(6); + +/** + * Validates all params and calls the right + * listener function based on its target type. + * + * @param {String|HTMLElement|HTMLCollection|NodeList} target + * @param {String} type + * @param {Function} callback + * @return {Object} + */ +function listen(target, type, callback) { + if (!target && !type && !callback) { + throw new Error('Missing required arguments'); + } + + if (!is.string(type)) { + throw new TypeError('Second argument must be a String'); + } + + if (!is.fn(callback)) { + throw new TypeError('Third argument must be a Function'); + } + + if (is.node(target)) { + return listenNode(target, type, callback); + } + else if (is.nodeList(target)) { + return listenNodeList(target, type, callback); + } + else if (is.string(target)) { + return listenSelector(target, type, callback); + } + else { + throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList'); + } +} + +/** + * Adds an event listener to a HTML element + * and returns a remove listener function. + * + * @param {HTMLElement} node + * @param {String} type + * @param {Function} callback + * @return {Object} + */ +function listenNode(node, type, callback) { + node.addEventListener(type, callback); + + return { + destroy: function() { + node.removeEventListener(type, callback); + } + } +} + +/** + * Add an event listener to a list of HTML elements + * and returns a remove listener function. + * + * @param {NodeList|HTMLCollection} nodeList + * @param {String} type + * @param {Function} callback + * @return {Object} + */ +function listenNodeList(nodeList, type, callback) { + Array.prototype.forEach.call(nodeList, function(node) { + node.addEventListener(type, callback); + }); + + return { + destroy: function() { + Array.prototype.forEach.call(nodeList, function(node) { + node.removeEventListener(type, callback); + }); + } + } +} + +/** + * Add an event listener to a selector + * and returns a remove listener function. + * + * @param {String} selector + * @param {String} type + * @param {Function} callback + * @return {Object} + */ +function listenSelector(selector, type, callback) { + return delegate(document.body, selector, type, callback); +} + +module.exports = listen; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + +/** + * Check if argument is a HTML element. + * + * @param {Object} value + * @return {Boolean} + */ +exports.node = function(value) { + return value !== undefined + && value instanceof HTMLElement + && value.nodeType === 1; +}; + +/** + * Check if argument is a list of HTML elements. + * + * @param {Object} value + * @return {Boolean} + */ +exports.nodeList = function(value) { + var type = Object.prototype.toString.call(value); + + return value !== undefined + && (type === '[object NodeList]' || type === '[object HTMLCollection]') + && ('length' in value) + && (value.length === 0 || exports.node(value[0])); +}; + +/** + * Check if argument is a string. + * + * @param {Object} value + * @return {Boolean} + */ +exports.string = function(value) { + return typeof value === 'string' + || value instanceof String; +}; + +/** + * Check if argument is a function. + * + * @param {Object} value + * @return {Boolean} + */ +exports.fn = function(value) { + var type = Object.prototype.toString.call(value); + + return type === '[object Function]'; +}; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +var closest = __webpack_require__(7); + +/** + * Delegates event to a selector. + * + * @param {Element} element + * @param {String} selector + * @param {String} type + * @param {Function} callback + * @param {Boolean} useCapture + * @return {Object} + */ +function _delegate(element, selector, type, callback, useCapture) { + var listenerFn = listener.apply(this, arguments); + + element.addEventListener(type, listenerFn, useCapture); + + return { + destroy: function() { + element.removeEventListener(type, listenerFn, useCapture); + } + } +} + +/** + * Delegates event to a selector. + * + * @param {Element|String|Array} [elements] + * @param {String} selector + * @param {String} type + * @param {Function} callback + * @param {Boolean} useCapture + * @return {Object} + */ +function delegate(elements, selector, type, callback, useCapture) { + // Handle the regular Element usage + if (typeof elements.addEventListener === 'function') { + return _delegate.apply(null, arguments); + } + + // Handle Element-less usage, it defaults to global delegation + if (typeof type === 'function') { + // Use `document` as the first parameter, then apply arguments + // This is a short way to .unshift `arguments` without running into deoptimizations + return _delegate.bind(null, document).apply(null, arguments); + } + + // Handle Selector-based usage + if (typeof elements === 'string') { + elements = document.querySelectorAll(elements); + } + + // Handle Array-like based usage + return Array.prototype.map.call(elements, function (element) { + return _delegate(element, selector, type, callback, useCapture); + }); +} + +/** + * Finds closest match and invokes callback. + * + * @param {Element} element + * @param {String} selector + * @param {String} type + * @param {Function} callback + * @return {Function} + */ +function listener(element, selector, type, callback) { + return function(e) { + e.delegateTarget = closest(e.target, selector); + + if (e.delegateTarget) { + callback.call(element, e); + } + } +} + +module.exports = delegate; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports) { + +var DOCUMENT_NODE_TYPE = 9; + +/** + * A polyfill for Element.matches() + */ +if (typeof Element !== 'undefined' && !Element.prototype.matches) { + var proto = Element.prototype; + + proto.matches = proto.matchesSelector || + proto.mozMatchesSelector || + proto.msMatchesSelector || + proto.oMatchesSelector || + proto.webkitMatchesSelector; +} + +/** + * Finds the closest parent that matches a selector. + * + * @param {Element} element + * @param {String} selector + * @return {Function} + */ +function closest (element, selector) { + while (element && element.nodeType !== DOCUMENT_NODE_TYPE) { + if (typeof element.matches === 'function' && + element.matches(selector)) { + return element; + } + element = element.parentNode; + } +} + +module.exports = closest; + + +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/clipboard/clipboard.min.js b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/clipboard/clipboard.min.js new file mode 100644 index 0000000000..02c549e35c --- /dev/null +++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/clipboard/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.4 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;nn)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})}); +/* == malihu jquery custom scrollbar plugin == Version: 3.1.5, License: MIT License (MIT) */ +!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"undefined"!=typeof module&&module.exports?module.exports=e:e(jQuery,window,document)}(function(e){!function(t){var o="function"==typeof define&&define.amd,a="undefined"!=typeof module&&module.exports,n="https:"==document.location.protocol?"https:":"http:",i="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js";o||(a?require("jquery-mousewheel")(e):e.event.special.mousewheel||e("head").append(decodeURI("%3Cscript src="+n+"//"+i+"%3E%3C/script%3E"))),t()}(function(){var t,o="mCustomScrollbar",a="mCS",n=".mCustomScrollbar",i={setTop:0,setLeft:0,axis:"y",scrollbarPosition:"inside",scrollInertia:950,autoDraggerLength:!0,alwaysShowScrollbar:0,snapOffset:0,mouseWheel:{enable:!0,scrollAmount:"auto",axis:"y",deltaFactor:"auto",disableOver:["select","option","keygen","datalist","textarea"]},scrollButtons:{scrollType:"stepless",scrollAmount:"auto"},keyboard:{enable:!0,scrollType:"stepless",scrollAmount:"auto"},contentTouchScroll:25,documentTouchScroll:!0,advanced:{autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']",updateOnContentResize:!0,updateOnImageLoad:"auto",autoUpdateTimeout:60},theme:"light",callbacks:{onTotalScrollOffset:0,onTotalScrollBackOffset:0,alwaysTriggerOffsets:!0}},r=0,l={},s=window.attachEvent&&!window.addEventListener?1:0,c=!1,d=["mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar","mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer","mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight"],u={init:function(t){var t=e.extend(!0,{},i,t),o=f.call(this);if(t.live){var s=t.liveSelector||this.selector||n,c=e(s);if("off"===t.live)return void m(s);l[s]=setTimeout(function(){c.mCustomScrollbar(t),"once"===t.live&&c.length&&m(s)},500)}else m(s);return t.setWidth=t.set_width?t.set_width:t.setWidth,t.setHeight=t.set_height?t.set_height:t.setHeight,t.axis=t.horizontalScroll?"x":p(t.axis),t.scrollInertia=t.scrollInertia>0&&t.scrollInertia<17?17:t.scrollInertia,"object"!=typeof t.mouseWheel&&1==t.mouseWheel&&(t.mouseWheel={enable:!0,scrollAmount:"auto",axis:"y",preventDefault:!1,deltaFactor:"auto",normalizeDelta:!1,invert:!1}),t.mouseWheel.scrollAmount=t.mouseWheelPixels?t.mouseWheelPixels:t.mouseWheel.scrollAmount,t.mouseWheel.normalizeDelta=t.advanced.normalizeMouseWheelDelta?t.advanced.normalizeMouseWheelDelta:t.mouseWheel.normalizeDelta,t.scrollButtons.scrollType=g(t.scrollButtons.scrollType),h(t),e(o).each(function(){var o=e(this);if(!o.data(a)){o.data(a,{idx:++r,opt:t,scrollRatio:{y:null,x:null},overflowed:null,contentReset:{y:null,x:null},bindEvents:!1,tweenRunning:!1,sequential:{},langDir:o.css("direction"),cbOffsets:null,trigger:null,poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}}});var n=o.data(a),i=n.opt,l=o.data("mcs-axis"),s=o.data("mcs-scrollbar-position"),c=o.data("mcs-theme");l&&(i.axis=l),s&&(i.scrollbarPosition=s),c&&(i.theme=c,h(i)),v.call(this),n&&i.callbacks.onCreate&&"function"==typeof i.callbacks.onCreate&&i.callbacks.onCreate.call(this),e("#mCSB_"+n.idx+"_container img:not(."+d[2]+")").addClass(d[2]),u.update.call(null,o)}})},update:function(t,o){var n=t||f.call(this);return e(n).each(function(){var t=e(this);if(t.data(a)){var n=t.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container"),l=e("#mCSB_"+n.idx),s=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];if(!r.length)return;n.tweenRunning&&Q(t),o&&n&&i.callbacks.onBeforeUpdate&&"function"==typeof i.callbacks.onBeforeUpdate&&i.callbacks.onBeforeUpdate.call(this),t.hasClass(d[3])&&t.removeClass(d[3]),t.hasClass(d[4])&&t.removeClass(d[4]),l.css("max-height","none"),l.height()!==t.height()&&l.css("max-height",t.height()),_.call(this),"y"===i.axis||i.advanced.autoExpandHorizontalScroll||r.css("width",x(r)),n.overflowed=y.call(this),M.call(this),i.autoDraggerLength&&S.call(this),b.call(this),T.call(this);var c=[Math.abs(r[0].offsetTop),Math.abs(r[0].offsetLeft)];"x"!==i.axis&&(n.overflowed[0]?s[0].height()>s[0].parent().height()?B.call(this):(G(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}),n.contentReset.y=null):(B.call(this),"y"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[1]&&G(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}))),"y"!==i.axis&&(n.overflowed[1]?s[1].width()>s[1].parent().width()?B.call(this):(G(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}),n.contentReset.x=null):(B.call(this),"x"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[0]&&G(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}))),o&&n&&(2===o&&i.callbacks.onImageLoad&&"function"==typeof i.callbacks.onImageLoad?i.callbacks.onImageLoad.call(this):3===o&&i.callbacks.onSelectorChange&&"function"==typeof i.callbacks.onSelectorChange?i.callbacks.onSelectorChange.call(this):i.callbacks.onUpdate&&"function"==typeof i.callbacks.onUpdate&&i.callbacks.onUpdate.call(this)),N.call(this)}})},scrollTo:function(t,o){if("undefined"!=typeof t&&null!=t){var n=f.call(this);return e(n).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l={trigger:"external",scrollInertia:r.scrollInertia,scrollEasing:"mcsEaseInOut",moveDragger:!1,timeout:60,callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},s=e.extend(!0,{},l,o),c=Y.call(this,t),d=s.scrollInertia>0&&s.scrollInertia<17?17:s.scrollInertia;c[0]=X.call(this,c[0],"y"),c[1]=X.call(this,c[1],"x"),s.moveDragger&&(c[0]*=i.scrollRatio.y,c[1]*=i.scrollRatio.x),s.dur=ne()?0:d,setTimeout(function(){null!==c[0]&&"undefined"!=typeof c[0]&&"x"!==r.axis&&i.overflowed[0]&&(s.dir="y",s.overwrite="all",G(n,c[0].toString(),s)),null!==c[1]&&"undefined"!=typeof c[1]&&"y"!==r.axis&&i.overflowed[1]&&(s.dir="x",s.overwrite="none",G(n,c[1].toString(),s))},s.timeout)}})}},stop:function(){var t=f.call(this);return e(t).each(function(){var t=e(this);t.data(a)&&Q(t)})},disable:function(t){var o=f.call(this);return e(o).each(function(){var o=e(this);if(o.data(a)){o.data(a);N.call(this,"remove"),k.call(this),t&&B.call(this),M.call(this,!0),o.addClass(d[3])}})},destroy:function(){var t=f.call(this);return e(t).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx),s=e("#mCSB_"+i.idx+"_container"),c=e(".mCSB_"+i.idx+"_scrollbar");r.live&&m(r.liveSelector||e(t).selector),N.call(this,"remove"),k.call(this),B.call(this),n.removeData(a),$(this,"mcs"),c.remove(),s.find("img."+d[2]).removeClass(d[2]),l.replaceWith(s.contents()),n.removeClass(o+" _"+a+"_"+i.idx+" "+d[6]+" "+d[7]+" "+d[5]+" "+d[3]).addClass(d[4])}})}},f=function(){return"object"!=typeof e(this)||e(this).length<1?n:this},h=function(t){var o=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"],a=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"],n=["minimal","minimal-dark"],i=["minimal","minimal-dark"],r=["minimal","minimal-dark"];t.autoDraggerLength=e.inArray(t.theme,o)>-1?!1:t.autoDraggerLength,t.autoExpandScrollbar=e.inArray(t.theme,a)>-1?!1:t.autoExpandScrollbar,t.scrollButtons.enable=e.inArray(t.theme,n)>-1?!1:t.scrollButtons.enable,t.autoHideScrollbar=e.inArray(t.theme,i)>-1?!0:t.autoHideScrollbar,t.scrollbarPosition=e.inArray(t.theme,r)>-1?"outside":t.scrollbarPosition},m=function(e){l[e]&&(clearTimeout(l[e]),$(l,e))},p=function(e){return"yx"===e||"xy"===e||"auto"===e?"yx":"x"===e||"horizontal"===e?"x":"y"},g=function(e){return"stepped"===e||"pixels"===e||"step"===e||"click"===e?"stepped":"stepless"},v=function(){var t=e(this),n=t.data(a),i=n.opt,r=i.autoExpandScrollbar?" "+d[1]+"_expand":"",l=["
","
"],s="yx"===i.axis?"mCSB_vertical_horizontal":"x"===i.axis?"mCSB_horizontal":"mCSB_vertical",c="yx"===i.axis?l[0]+l[1]:"x"===i.axis?l[1]:l[0],u="yx"===i.axis?"
":"",f=i.autoHideScrollbar?" "+d[6]:"",h="x"!==i.axis&&"rtl"===n.langDir?" "+d[7]:"";i.setWidth&&t.css("width",i.setWidth),i.setHeight&&t.css("height",i.setHeight),i.setLeft="y"!==i.axis&&"rtl"===n.langDir?"989999px":i.setLeft,t.addClass(o+" _"+a+"_"+n.idx+f+h).wrapInner("
");var m=e("#mCSB_"+n.idx),p=e("#mCSB_"+n.idx+"_container");"y"===i.axis||i.advanced.autoExpandHorizontalScroll||p.css("width",x(p)),"outside"===i.scrollbarPosition?("static"===t.css("position")&&t.css("position","relative"),t.css("overflow","visible"),m.addClass("mCSB_outside").after(c)):(m.addClass("mCSB_inside").append(c),p.wrap(u)),w.call(this);var g=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];g[0].css("min-height",g[0].height()),g[1].css("min-width",g[1].width())},x=function(t){var o=[t[0].scrollWidth,Math.max.apply(Math,t.children().map(function(){return e(this).outerWidth(!0)}).get())],a=t.parent().width();return o[0]>a?o[0]:o[1]>a?o[1]:"100%"},_=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx+"_container");if(n.advanced.autoExpandHorizontalScroll&&"y"!==n.axis){i.css({width:"auto","min-width":0,"overflow-x":"scroll"});var r=Math.ceil(i[0].scrollWidth);3===n.advanced.autoExpandHorizontalScroll||2!==n.advanced.autoExpandHorizontalScroll&&r>i.parent().width()?i.css({width:r,"min-width":"100%","overflow-x":"inherit"}):i.css({"overflow-x":"inherit",position:"absolute"}).wrap("
").css({width:Math.ceil(i[0].getBoundingClientRect().right+.4)-Math.floor(i[0].getBoundingClientRect().left),"min-width":"100%",position:"relative"}).unwrap()}},w=function(){var t=e(this),o=t.data(a),n=o.opt,i=e(".mCSB_"+o.idx+"_scrollbar:first"),r=oe(n.scrollButtons.tabindex)?"tabindex='"+n.scrollButtons.tabindex+"'":"",l=["","","",""],s=["x"===n.axis?l[2]:l[0],"x"===n.axis?l[3]:l[1],l[2],l[3]];n.scrollButtons.enable&&i.prepend(s[0]).append(s[1]).next(".mCSB_scrollTools").prepend(s[2]).append(s[3])},S=function(){var t=e(this),o=t.data(a),n=e("#mCSB_"+o.idx),i=e("#mCSB_"+o.idx+"_container"),r=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")],l=[n.height()/i.outerHeight(!1),n.width()/i.outerWidth(!1)],c=[parseInt(r[0].css("min-height")),Math.round(l[0]*r[0].parent().height()),parseInt(r[1].css("min-width")),Math.round(l[1]*r[1].parent().width())],d=s&&c[1]r&&(r=s),c>l&&(l=c),[r>n.height(),l>n.width()]},B=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx),r=e("#mCSB_"+o.idx+"_container"),l=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")];if(Q(t),("x"!==n.axis&&!o.overflowed[0]||"y"===n.axis&&o.overflowed[0])&&(l[0].add(r).css("top",0),G(t,"_resetY")),"y"!==n.axis&&!o.overflowed[1]||"x"===n.axis&&o.overflowed[1]){var s=dx=0;"rtl"===o.langDir&&(s=i.width()-r.outerWidth(!1),dx=Math.abs(s/o.scrollRatio.x)),r.css("left",s),l[1].css("left",dx),G(t,"_resetX")}},T=function(){function t(){r=setTimeout(function(){e.event.special.mousewheel?(clearTimeout(r),W.call(o[0])):t()},100)}var o=e(this),n=o.data(a),i=n.opt;if(!n.bindEvents){if(I.call(this),i.contentTouchScroll&&D.call(this),E.call(this),i.mouseWheel.enable){var r;t()}P.call(this),U.call(this),i.advanced.autoScrollOnFocus&&H.call(this),i.scrollButtons.enable&&F.call(this),i.keyboard.enable&&q.call(this),n.bindEvents=!0}},k=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=".mCSB_"+o.idx+"_scrollbar",l=e("#mCSB_"+o.idx+",#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,"+r+" ."+d[12]+",#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal,"+r+">a"),s=e("#mCSB_"+o.idx+"_container");n.advanced.releaseDraggableSelectors&&l.add(e(n.advanced.releaseDraggableSelectors)),n.advanced.extraDraggableSelectors&&l.add(e(n.advanced.extraDraggableSelectors)),o.bindEvents&&(e(document).add(e(!A()||top.document)).unbind("."+i),l.each(function(){e(this).unbind("."+i)}),clearTimeout(t[0]._focusTimeout),$(t[0],"_focusTimeout"),clearTimeout(o.sequential.step),$(o.sequential,"step"),clearTimeout(s[0].onCompleteTimeout),$(s[0],"onCompleteTimeout"),o.bindEvents=!1)},M=function(t){var o=e(this),n=o.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container_wrapper"),l=r.length?r:e("#mCSB_"+n.idx+"_container"),s=[e("#mCSB_"+n.idx+"_scrollbar_vertical"),e("#mCSB_"+n.idx+"_scrollbar_horizontal")],c=[s[0].find(".mCSB_dragger"),s[1].find(".mCSB_dragger")];"x"!==i.axis&&(n.overflowed[0]&&!t?(s[0].add(c[0]).add(s[0].children("a")).css("display","block"),l.removeClass(d[8]+" "+d[10])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[0].css("display","none"),l.removeClass(d[10])):(s[0].css("display","none"),l.addClass(d[10])),l.addClass(d[8]))),"y"!==i.axis&&(n.overflowed[1]&&!t?(s[1].add(c[1]).add(s[1].children("a")).css("display","block"),l.removeClass(d[9]+" "+d[11])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[1].css("display","none"),l.removeClass(d[11])):(s[1].css("display","none"),l.addClass(d[11])),l.addClass(d[9]))),n.overflowed[0]||n.overflowed[1]?o.removeClass(d[5]):o.addClass(d[5])},O=function(t){var o=t.type,a=t.target.ownerDocument!==document&&null!==frameElement?[e(frameElement).offset().top,e(frameElement).offset().left]:null,n=A()&&t.target.ownerDocument!==top.document&&null!==frameElement?[e(t.view.frameElement).offset().top,e(t.view.frameElement).offset().left]:[0,0];switch(o){case"pointerdown":case"MSPointerDown":case"pointermove":case"MSPointerMove":case"pointerup":case"MSPointerUp":return a?[t.originalEvent.pageY-a[0]+n[0],t.originalEvent.pageX-a[1]+n[1],!1]:[t.originalEvent.pageY,t.originalEvent.pageX,!1];case"touchstart":case"touchmove":case"touchend":var i=t.originalEvent.touches[0]||t.originalEvent.changedTouches[0],r=t.originalEvent.touches.length||t.originalEvent.changedTouches.length;return t.target.ownerDocument!==document?[i.screenY,i.screenX,r>1]:[i.pageY,i.pageX,r>1];default:return a?[t.pageY-a[0]+n[0],t.pageX-a[1]+n[1],!1]:[t.pageY,t.pageX,!1]}},I=function(){function t(e,t,a,n){if(h[0].idleTimer=d.scrollInertia<233?250:0,o.attr("id")===f[1])var i="x",s=(o[0].offsetLeft-t+n)*l.scrollRatio.x;else var i="y",s=(o[0].offsetTop-e+a)*l.scrollRatio.y;G(r,s.toString(),{dir:i,drag:!0})}var o,n,i,r=e(this),l=r.data(a),d=l.opt,u=a+"_"+l.idx,f=["mCSB_"+l.idx+"_dragger_vertical","mCSB_"+l.idx+"_dragger_horizontal"],h=e("#mCSB_"+l.idx+"_container"),m=e("#"+f[0]+",#"+f[1]),p=d.advanced.releaseDraggableSelectors?m.add(e(d.advanced.releaseDraggableSelectors)):m,g=d.advanced.extraDraggableSelectors?e(!A()||top.document).add(e(d.advanced.extraDraggableSelectors)):e(!A()||top.document);m.bind("contextmenu."+u,function(e){e.preventDefault()}).bind("mousedown."+u+" touchstart."+u+" pointerdown."+u+" MSPointerDown."+u,function(t){if(t.stopImmediatePropagation(),t.preventDefault(),ee(t)){c=!0,s&&(document.onselectstart=function(){return!1}),L.call(h,!1),Q(r),o=e(this);var a=o.offset(),l=O(t)[0]-a.top,u=O(t)[1]-a.left,f=o.height()+a.top,m=o.width()+a.left;f>l&&l>0&&m>u&&u>0&&(n=l,i=u),C(o,"active",d.autoExpandScrollbar)}}).bind("touchmove."+u,function(e){e.stopImmediatePropagation(),e.preventDefault();var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;t(n,i,r,l)}),e(document).add(g).bind("mousemove."+u+" pointermove."+u+" MSPointerMove."+u,function(e){if(o){var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;if(n===r&&i===l)return;t(n,i,r,l)}}).add(p).bind("mouseup."+u+" touchend."+u+" pointerup."+u+" MSPointerUp."+u,function(){o&&(C(o,"active",d.autoExpandScrollbar),o=null),c=!1,s&&(document.onselectstart=null),L.call(h,!0)})},D=function(){function o(e){if(!te(e)||c||O(e)[2])return void(t=0);t=1,b=0,C=0,d=1,y.removeClass("mCS_touch_action");var o=I.offset();u=O(e)[0]-o.top,f=O(e)[1]-o.left,z=[O(e)[0],O(e)[1]]}function n(e){if(te(e)&&!c&&!O(e)[2]&&(T.documentTouchScroll||e.preventDefault(),e.stopImmediatePropagation(),(!C||b)&&d)){g=K();var t=M.offset(),o=O(e)[0]-t.top,a=O(e)[1]-t.left,n="mcsLinearOut";if(E.push(o),W.push(a),z[2]=Math.abs(O(e)[0]-z[0]),z[3]=Math.abs(O(e)[1]-z[1]),B.overflowed[0])var i=D[0].parent().height()-D[0].height(),r=u-o>0&&o-u>-(i*B.scrollRatio.y)&&(2*z[3]0&&a-f>-(l*B.scrollRatio.x)&&(2*z[2]30)){_=1e3/(v-p);var n="mcsEaseOut",i=2.5>_,r=i?[E[E.length-2],W[W.length-2]]:[0,0];x=i?[o-r[0],a-r[1]]:[o-h,a-m];var u=[Math.abs(x[0]),Math.abs(x[1])];_=i?[Math.abs(x[0]/4),Math.abs(x[1]/4)]:[_,_];var f=[Math.abs(I[0].offsetTop)-x[0]*l(u[0]/_[0],_[0]),Math.abs(I[0].offsetLeft)-x[1]*l(u[1]/_[1],_[1])];w="yx"===T.axis?[f[0],f[1]]:"x"===T.axis?[null,f[1]]:[f[0],null],S=[4*u[0]+T.scrollInertia,4*u[1]+T.scrollInertia];var y=parseInt(T.contentTouchScroll)||0;w[0]=u[0]>y?w[0]:0,w[1]=u[1]>y?w[1]:0,B.overflowed[0]&&s(w[0],S[0],n,"y",L,!1),B.overflowed[1]&&s(w[1],S[1],n,"x",L,!1)}}}function l(e,t){var o=[1.5*t,2*t,t/1.5,t/2];return e>90?t>4?o[0]:o[3]:e>60?t>3?o[3]:o[2]:e>30?t>8?o[1]:t>6?o[0]:t>4?t:o[2]:t>8?t:o[3]}function s(e,t,o,a,n,i){e&&G(y,e.toString(),{dur:t,scrollEasing:o,dir:a,overwrite:n,drag:i})}var d,u,f,h,m,p,g,v,x,_,w,S,b,C,y=e(this),B=y.data(a),T=B.opt,k=a+"_"+B.idx,M=e("#mCSB_"+B.idx),I=e("#mCSB_"+B.idx+"_container"),D=[e("#mCSB_"+B.idx+"_dragger_vertical"),e("#mCSB_"+B.idx+"_dragger_horizontal")],E=[],W=[],R=0,L="yx"===T.axis?"none":"all",z=[],P=I.find("iframe"),H=["touchstart."+k+" pointerdown."+k+" MSPointerDown."+k,"touchmove."+k+" pointermove."+k+" MSPointerMove."+k,"touchend."+k+" pointerup."+k+" MSPointerUp."+k],U=void 0!==document.body.style.touchAction&&""!==document.body.style.touchAction;I.bind(H[0],function(e){o(e)}).bind(H[1],function(e){n(e)}),M.bind(H[0],function(e){i(e)}).bind(H[2],function(e){r(e)}),P.length&&P.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(H[0],function(e){o(e),i(e)}).bind(H[1],function(e){n(e)}).bind(H[2],function(e){r(e)})})})},E=function(){function o(){return window.getSelection?window.getSelection().toString():document.selection&&"Control"!=document.selection.type?document.selection.createRange().text:0}function n(e,t,o){d.type=o&&i?"stepped":"stepless",d.scrollAmount=10,j(r,e,t,"mcsLinearOut",o?60:null)}var i,r=e(this),l=r.data(a),s=l.opt,d=l.sequential,u=a+"_"+l.idx,f=e("#mCSB_"+l.idx+"_container"),h=f.parent();f.bind("mousedown."+u,function(){t||i||(i=1,c=!0)}).add(document).bind("mousemove."+u,function(e){if(!t&&i&&o()){var a=f.offset(),r=O(e)[0]-a.top+f[0].offsetTop,c=O(e)[1]-a.left+f[0].offsetLeft;r>0&&r0&&cr?n("on",38):r>h.height()&&n("on",40)),"y"!==s.axis&&l.overflowed[1]&&(0>c?n("on",37):c>h.width()&&n("on",39)))}}).bind("mouseup."+u+" dragend."+u,function(){t||(i&&(i=0,n("off",null)),c=!1)})},W=function(){function t(t,a){if(Q(o),!z(o,t.target)){var r="auto"!==i.mouseWheel.deltaFactor?parseInt(i.mouseWheel.deltaFactor):s&&t.deltaFactor<100?100:t.deltaFactor||100,d=i.scrollInertia;if("x"===i.axis||"x"===i.mouseWheel.axis)var u="x",f=[Math.round(r*n.scrollRatio.x),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.width()?.9*l.width():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetLeft),p=c[1][0].offsetLeft,g=c[1].parent().width()-c[1].width(),v="y"===i.mouseWheel.axis?t.deltaY||a:t.deltaX;else var u="y",f=[Math.round(r*n.scrollRatio.y),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.height()?.9*l.height():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetTop),p=c[0][0].offsetTop,g=c[0].parent().height()-c[0].height(),v=t.deltaY||a;"y"===u&&!n.overflowed[0]||"x"===u&&!n.overflowed[1]||((i.mouseWheel.invert||t.webkitDirectionInvertedFromDevice)&&(v=-v),i.mouseWheel.normalizeDelta&&(v=0>v?-1:1),(v>0&&0!==p||0>v&&p!==g||i.mouseWheel.preventDefault)&&(t.stopImmediatePropagation(),t.preventDefault()),t.deltaFactor<5&&!i.mouseWheel.normalizeDelta&&(h=t.deltaFactor,d=17),G(o,(m-v*h).toString(),{dir:u,dur:d}))}}if(e(this).data(a)){var o=e(this),n=o.data(a),i=n.opt,r=a+"_"+n.idx,l=e("#mCSB_"+n.idx),c=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")],d=e("#mCSB_"+n.idx+"_container").find("iframe");d.length&&d.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind("mousewheel."+r,function(e,o){t(e,o)})})}),l.bind("mousewheel."+r,function(e,o){t(e,o)})}},R=new Object,A=function(t){var o=!1,a=!1,n=null;if(void 0===t?a="#empty":void 0!==e(t).attr("id")&&(a=e(t).attr("id")),a!==!1&&void 0!==R[a])return R[a];if(t){try{var i=t.contentDocument||t.contentWindow.document;n=i.body.innerHTML}catch(r){}o=null!==n}else{try{var i=top.document;n=i.body.innerHTML}catch(r){}o=null!==n}return a!==!1&&(R[a]=o),o},L=function(e){var t=this.find("iframe");if(t.length){var o=e?"auto":"none";t.css("pointer-events",o)}},z=function(t,o){var n=o.nodeName.toLowerCase(),i=t.data(a).opt.mouseWheel.disableOver,r=["select","textarea"];return e.inArray(n,i)>-1&&!(e.inArray(n,r)>-1&&!e(o).is(":focus"))},P=function(){var t,o=e(this),n=o.data(a),i=a+"_"+n.idx,r=e("#mCSB_"+n.idx+"_container"),l=r.parent(),s=e(".mCSB_"+n.idx+"_scrollbar ."+d[12]);s.bind("mousedown."+i+" touchstart."+i+" pointerdown."+i+" MSPointerDown."+i,function(o){c=!0,e(o.target).hasClass("mCSB_dragger")||(t=1)}).bind("touchend."+i+" pointerup."+i+" MSPointerUp."+i,function(){c=!1}).bind("click."+i,function(a){if(t&&(t=0,e(a.target).hasClass(d[12])||e(a.target).hasClass("mCSB_draggerRail"))){Q(o);var i=e(this),s=i.find(".mCSB_dragger");if(i.parent(".mCSB_scrollTools_horizontal").length>0){if(!n.overflowed[1])return;var c="x",u=a.pageX>s.offset().left?-1:1,f=Math.abs(r[0].offsetLeft)-u*(.9*l.width())}else{if(!n.overflowed[0])return;var c="y",u=a.pageY>s.offset().top?-1:1,f=Math.abs(r[0].offsetTop)-u*(.9*l.height())}G(o,f.toString(),{dir:c,scrollEasing:"mcsEaseInOut"})}})},H=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=e("#mCSB_"+o.idx+"_container"),l=r.parent();r.bind("focusin."+i,function(){var o=e(document.activeElement),a=r.find(".mCustomScrollBox").length,i=0;o.is(n.advanced.autoScrollOnFocus)&&(Q(t),clearTimeout(t[0]._focusTimeout),t[0]._focusTimer=a?(i+17)*a:0,t[0]._focusTimeout=setTimeout(function(){var e=[ae(o)[0],ae(o)[1]],a=[r[0].offsetTop,r[0].offsetLeft],s=[a[0]+e[0]>=0&&a[0]+e[0]=0&&a[0]+e[1]a");s.bind("contextmenu."+r,function(e){e.preventDefault()}).bind("mousedown."+r+" touchstart."+r+" pointerdown."+r+" MSPointerDown."+r+" mouseup."+r+" touchend."+r+" pointerup."+r+" MSPointerUp."+r+" mouseout."+r+" pointerout."+r+" MSPointerOut."+r+" click."+r,function(a){function r(e,o){i.scrollAmount=n.scrollButtons.scrollAmount,j(t,e,o)}if(a.preventDefault(),ee(a)){var l=e(this).attr("class");switch(i.type=n.scrollButtons.scrollType,a.type){case"mousedown":case"touchstart":case"pointerdown":case"MSPointerDown":if("stepped"===i.type)return;c=!0,o.tweenRunning=!1,r("on",l);break;case"mouseup":case"touchend":case"pointerup":case"MSPointerUp":case"mouseout":case"pointerout":case"MSPointerOut":if("stepped"===i.type)return;c=!1,i.dir&&r("off",l);break;case"click":if("stepped"!==i.type||o.tweenRunning)return;r("on",l)}}})},q=function(){function t(t){function a(e,t){r.type=i.keyboard.scrollType,r.scrollAmount=i.keyboard.scrollAmount,"stepped"===r.type&&n.tweenRunning||j(o,e,t)}switch(t.type){case"blur":n.tweenRunning&&r.dir&&a("off",null);break;case"keydown":case"keyup":var l=t.keyCode?t.keyCode:t.which,s="on";if("x"!==i.axis&&(38===l||40===l)||"y"!==i.axis&&(37===l||39===l)){if((38===l||40===l)&&!n.overflowed[0]||(37===l||39===l)&&!n.overflowed[1])return;"keyup"===t.type&&(s="off"),e(document.activeElement).is(u)||(t.preventDefault(),t.stopImmediatePropagation(),a(s,l))}else if(33===l||34===l){if((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type){Q(o);var f=34===l?-1:1;if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=Math.abs(c[0].offsetLeft)-f*(.9*d.width());else var h="y",m=Math.abs(c[0].offsetTop)-f*(.9*d.height());G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}else if((35===l||36===l)&&!e(document.activeElement).is(u)&&((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type)){if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=35===l?Math.abs(d.width()-c.outerWidth(!1)):0;else var h="y",m=35===l?Math.abs(d.height()-c.outerHeight(!1)):0;G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}}var o=e(this),n=o.data(a),i=n.opt,r=n.sequential,l=a+"_"+n.idx,s=e("#mCSB_"+n.idx),c=e("#mCSB_"+n.idx+"_container"),d=c.parent(),u="input,textarea,select,datalist,keygen,[contenteditable='true']",f=c.find("iframe"),h=["blur."+l+" keydown."+l+" keyup."+l];f.length&&f.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(h[0],function(e){t(e)})})}),s.attr("tabindex","0").bind(h[0],function(e){t(e)})},j=function(t,o,n,i,r){function l(e){u.snapAmount&&(f.scrollAmount=u.snapAmount instanceof Array?"x"===f.dir[0]?u.snapAmount[1]:u.snapAmount[0]:u.snapAmount);var o="stepped"!==f.type,a=r?r:e?o?p/1.5:g:1e3/60,n=e?o?7.5:40:2.5,s=[Math.abs(h[0].offsetTop),Math.abs(h[0].offsetLeft)],d=[c.scrollRatio.y>10?10:c.scrollRatio.y,c.scrollRatio.x>10?10:c.scrollRatio.x],m="x"===f.dir[0]?s[1]+f.dir[1]*(d[1]*n):s[0]+f.dir[1]*(d[0]*n),v="x"===f.dir[0]?s[1]+f.dir[1]*parseInt(f.scrollAmount):s[0]+f.dir[1]*parseInt(f.scrollAmount),x="auto"!==f.scrollAmount?v:m,_=i?i:e?o?"mcsLinearOut":"mcsEaseInOut":"mcsLinear",w=!!e;return e&&17>a&&(x="x"===f.dir[0]?s[1]:s[0]),G(t,x.toString(),{dir:f.dir[0],scrollEasing:_,dur:a,onComplete:w}),e?void(f.dir=!1):(clearTimeout(f.step),void(f.step=setTimeout(function(){l()},a)))}function s(){clearTimeout(f.step),$(f,"step"),Q(t)}var c=t.data(a),u=c.opt,f=c.sequential,h=e("#mCSB_"+c.idx+"_container"),m="stepped"===f.type,p=u.scrollInertia<26?26:u.scrollInertia,g=u.scrollInertia<1?17:u.scrollInertia;switch(o){case"on":if(f.dir=[n===d[16]||n===d[15]||39===n||37===n?"x":"y",n===d[13]||n===d[15]||38===n||37===n?-1:1],Q(t),oe(n)&&"stepped"===f.type)return;l(m);break;case"off":s(),(m||c.tweenRunning&&f.dir)&&l(!0)}},Y=function(t){var o=e(this).data(a).opt,n=[];return"function"==typeof t&&(t=t()),t instanceof Array?n=t.length>1?[t[0],t[1]]:"x"===o.axis?[null,t[0]]:[t[0],null]:(n[0]=t.y?t.y:t.x||"x"===o.axis?null:t,n[1]=t.x?t.x:t.y||"y"===o.axis?null:t),"function"==typeof n[0]&&(n[0]=n[0]()),"function"==typeof n[1]&&(n[1]=n[1]()),n},X=function(t,o){if(null!=t&&"undefined"!=typeof t){var n=e(this),i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx+"_container"),s=l.parent(),c=typeof t;o||(o="x"===r.axis?"x":"y");var d="x"===o?l.outerWidth(!1)-s.width():l.outerHeight(!1)-s.height(),f="x"===o?l[0].offsetLeft:l[0].offsetTop,h="x"===o?"left":"top";switch(c){case"function":return t();case"object":var m=t.jquery?t:e(t);if(!m.length)return;return"x"===o?ae(m)[1]:ae(m)[0];case"string":case"number":if(oe(t))return Math.abs(t);if(-1!==t.indexOf("%"))return Math.abs(d*parseInt(t)/100);if(-1!==t.indexOf("-="))return Math.abs(f-parseInt(t.split("-=")[1]));if(-1!==t.indexOf("+=")){var p=f+parseInt(t.split("+=")[1]);return p>=0?0:Math.abs(p)}if(-1!==t.indexOf("px")&&oe(t.split("px")[0]))return Math.abs(t.split("px")[0]);if("top"===t||"left"===t)return 0;if("bottom"===t)return Math.abs(s.height()-l.outerHeight(!1));if("right"===t)return Math.abs(s.width()-l.outerWidth(!1));if("first"===t||"last"===t){var m=l.find(":"+t);return"x"===o?ae(m)[1]:ae(m)[0]}return e(t).length?"x"===o?ae(e(t))[1]:ae(e(t))[0]:(l.css(h,t),void u.update.call(null,n[0]))}}},N=function(t){function o(){return clearTimeout(f[0].autoUpdate),0===l.parents("html").length?void(l=null):void(f[0].autoUpdate=setTimeout(function(){return c.advanced.updateOnSelectorChange&&(s.poll.change.n=i(),s.poll.change.n!==s.poll.change.o)?(s.poll.change.o=s.poll.change.n,void r(3)):c.advanced.updateOnContentResize&&(s.poll.size.n=l[0].scrollHeight+l[0].scrollWidth+f[0].offsetHeight+l[0].offsetHeight+l[0].offsetWidth,s.poll.size.n!==s.poll.size.o)?(s.poll.size.o=s.poll.size.n,void r(1)):!c.advanced.updateOnImageLoad||"auto"===c.advanced.updateOnImageLoad&&"y"===c.axis||(s.poll.img.n=f.find("img").length,s.poll.img.n===s.poll.img.o)?void((c.advanced.updateOnSelectorChange||c.advanced.updateOnContentResize||c.advanced.updateOnImageLoad)&&o()):(s.poll.img.o=s.poll.img.n,void f.find("img").each(function(){n(this)}))},c.advanced.autoUpdateTimeout))}function n(t){function o(e,t){return function(){ +return t.apply(e,arguments)}}function a(){this.onload=null,e(t).addClass(d[2]),r(2)}if(e(t).hasClass(d[2]))return void r();var n=new Image;n.onload=o(n,a),n.src=t.src}function i(){c.advanced.updateOnSelectorChange===!0&&(c.advanced.updateOnSelectorChange="*");var e=0,t=f.find(c.advanced.updateOnSelectorChange);return c.advanced.updateOnSelectorChange&&t.length>0&&t.each(function(){e+=this.offsetHeight+this.offsetWidth}),e}function r(e){clearTimeout(f[0].autoUpdate),u.update.call(null,l[0],e)}var l=e(this),s=l.data(a),c=s.opt,f=e("#mCSB_"+s.idx+"_container");return t?(clearTimeout(f[0].autoUpdate),void $(f[0],"autoUpdate")):void o()},V=function(e,t,o){return Math.round(e/t)*t-o},Q=function(t){var o=t.data(a),n=e("#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal");n.each(function(){Z.call(this)})},G=function(t,o,n){function i(e){return s&&c.callbacks[e]&&"function"==typeof c.callbacks[e]}function r(){return[c.callbacks.alwaysTriggerOffsets||w>=S[0]+y,c.callbacks.alwaysTriggerOffsets||-B>=w]}function l(){var e=[h[0].offsetTop,h[0].offsetLeft],o=[x[0].offsetTop,x[0].offsetLeft],a=[h.outerHeight(!1),h.outerWidth(!1)],i=[f.height(),f.width()];t[0].mcs={content:h,top:e[0],left:e[1],draggerTop:o[0],draggerLeft:o[1],topPct:Math.round(100*Math.abs(e[0])/(Math.abs(a[0])-i[0])),leftPct:Math.round(100*Math.abs(e[1])/(Math.abs(a[1])-i[1])),direction:n.dir}}var s=t.data(a),c=s.opt,d={trigger:"internal",dir:"y",scrollEasing:"mcsEaseOut",drag:!1,dur:c.scrollInertia,overwrite:"all",callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},n=e.extend(d,n),u=[n.dur,n.drag?0:n.dur],f=e("#mCSB_"+s.idx),h=e("#mCSB_"+s.idx+"_container"),m=h.parent(),p=c.callbacks.onTotalScrollOffset?Y.call(t,c.callbacks.onTotalScrollOffset):[0,0],g=c.callbacks.onTotalScrollBackOffset?Y.call(t,c.callbacks.onTotalScrollBackOffset):[0,0];if(s.trigger=n.trigger,0===m.scrollTop()&&0===m.scrollLeft()||(e(".mCSB_"+s.idx+"_scrollbar").css("visibility","visible"),m.scrollTop(0).scrollLeft(0)),"_resetY"!==o||s.contentReset.y||(i("onOverflowYNone")&&c.callbacks.onOverflowYNone.call(t[0]),s.contentReset.y=1),"_resetX"!==o||s.contentReset.x||(i("onOverflowXNone")&&c.callbacks.onOverflowXNone.call(t[0]),s.contentReset.x=1),"_resetY"!==o&&"_resetX"!==o){if(!s.contentReset.y&&t[0].mcs||!s.overflowed[0]||(i("onOverflowY")&&c.callbacks.onOverflowY.call(t[0]),s.contentReset.x=null),!s.contentReset.x&&t[0].mcs||!s.overflowed[1]||(i("onOverflowX")&&c.callbacks.onOverflowX.call(t[0]),s.contentReset.x=null),c.snapAmount){var v=c.snapAmount instanceof Array?"x"===n.dir?c.snapAmount[1]:c.snapAmount[0]:c.snapAmount;o=V(o,v,c.snapOffset)}switch(n.dir){case"x":var x=e("#mCSB_"+s.idx+"_dragger_horizontal"),_="left",w=h[0].offsetLeft,S=[f.width()-h.outerWidth(!1),x.parent().width()-x.width()],b=[o,0===o?0:o/s.scrollRatio.x],y=p[1],B=g[1],T=y>0?y/s.scrollRatio.x:0,k=B>0?B/s.scrollRatio.x:0;break;case"y":var x=e("#mCSB_"+s.idx+"_dragger_vertical"),_="top",w=h[0].offsetTop,S=[f.height()-h.outerHeight(!1),x.parent().height()-x.height()],b=[o,0===o?0:o/s.scrollRatio.y],y=p[0],B=g[0],T=y>0?y/s.scrollRatio.y:0,k=B>0?B/s.scrollRatio.y:0}b[1]<0||0===b[0]&&0===b[1]?b=[0,0]:b[1]>=S[1]?b=[S[0],S[1]]:b[0]=-b[0],t[0].mcs||(l(),i("onInit")&&c.callbacks.onInit.call(t[0])),clearTimeout(h[0].onCompleteTimeout),J(x[0],_,Math.round(b[1]),u[1],n.scrollEasing),!s.tweenRunning&&(0===w&&b[0]>=0||w===S[0]&&b[0]<=S[0])||J(h[0],_,Math.round(b[0]),u[0],n.scrollEasing,n.overwrite,{onStart:function(){n.callbacks&&n.onStart&&!s.tweenRunning&&(i("onScrollStart")&&(l(),c.callbacks.onScrollStart.call(t[0])),s.tweenRunning=!0,C(x),s.cbOffsets=r())},onUpdate:function(){n.callbacks&&n.onUpdate&&i("whileScrolling")&&(l(),c.callbacks.whileScrolling.call(t[0]))},onComplete:function(){if(n.callbacks&&n.onComplete){"yx"===c.axis&&clearTimeout(h[0].onCompleteTimeout);var e=h[0].idleTimer||0;h[0].onCompleteTimeout=setTimeout(function(){i("onScroll")&&(l(),c.callbacks.onScroll.call(t[0])),i("onTotalScroll")&&b[1]>=S[1]-T&&s.cbOffsets[0]&&(l(),c.callbacks.onTotalScroll.call(t[0])),i("onTotalScrollBack")&&b[1]<=k&&s.cbOffsets[1]&&(l(),c.callbacks.onTotalScrollBack.call(t[0])),s.tweenRunning=!1,h[0].idleTimer=0,C(x,"hide")},e)}}})}},J=function(e,t,o,a,n,i,r){function l(){S.stop||(x||m.call(),x=K()-v,s(),x>=S.time&&(S.time=x>S.time?x+f-(x-S.time):x+f-1,S.time0?(S.currVal=u(S.time,_,b,a,n),w[t]=Math.round(S.currVal)+"px"):w[t]=o+"px",p.call()}function c(){f=1e3/60,S.time=x+f,h=window.requestAnimationFrame?window.requestAnimationFrame:function(e){return s(),setTimeout(e,.01)},S.id=h(l)}function d(){null!=S.id&&(window.requestAnimationFrame?window.cancelAnimationFrame(S.id):clearTimeout(S.id),S.id=null)}function u(e,t,o,a,n){switch(n){case"linear":case"mcsLinear":return o*e/a+t;case"mcsLinearOut":return e/=a,e--,o*Math.sqrt(1-e*e)+t;case"easeInOutSmooth":return e/=a/2,1>e?o/2*e*e+t:(e--,-o/2*(e*(e-2)-1)+t);case"easeInOutStrong":return e/=a/2,1>e?o/2*Math.pow(2,10*(e-1))+t:(e--,o/2*(-Math.pow(2,-10*e)+2)+t);case"easeInOut":case"mcsEaseInOut":return e/=a/2,1>e?o/2*e*e*e+t:(e-=2,o/2*(e*e*e+2)+t);case"easeOutSmooth":return e/=a,e--,-o*(e*e*e*e-1)+t;case"easeOutStrong":return o*(-Math.pow(2,-10*e/a)+1)+t;case"easeOut":case"mcsEaseOut":default:var i=(e/=a)*e,r=i*e;return t+o*(.499999999999997*r*i+-2.5*i*i+5.5*r+-6.5*i+4*e)}}e._mTween||(e._mTween={top:{},left:{}});var f,h,r=r||{},m=r.onStart||function(){},p=r.onUpdate||function(){},g=r.onComplete||function(){},v=K(),x=0,_=e.offsetTop,w=e.style,S=e._mTween[t];"left"===t&&(_=e.offsetLeft);var b=o-_;S.stop=0,"none"!==i&&d(),c()},K=function(){return window.performance&&window.performance.now?window.performance.now():window.performance&&window.performance.webkitNow?window.performance.webkitNow():Date.now?Date.now():(new Date).getTime()},Z=function(){var e=this;e._mTween||(e._mTween={top:{},left:{}});for(var t=["top","left"],o=0;o=0&&a[0]+ae(n)[0]=0&&a[1]+ae(n)[1]=0&&r[1]-i[1]*l[1][0]<0&&r[1]+n[1]-i[1]*l[1][1]>=0},mcsOverflow:e.expr[":"].mcsOverflow||function(t){var o=e(t).data(a);if(o)return o.overflowed[0]||o.overflowed[1]}})})})}); \ No newline at end of file diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css new file mode 100644 index 0000000000..45152c1bec --- /dev/null +++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css @@ -0,0 +1,1267 @@ +/* +== malihu jquery custom scrollbar plugin == +Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller +*/ + + + +/* +CONTENTS: + 1. BASIC STYLE - Plugin's basic/essential CSS properties (normally, should not be edited). + 2. VERTICAL SCROLLBAR - Positioning and dimensions of vertical scrollbar. + 3. HORIZONTAL SCROLLBAR - Positioning and dimensions of horizontal scrollbar. + 4. VERTICAL AND HORIZONTAL SCROLLBARS - Positioning and dimensions of 2-axis scrollbars. + 5. TRANSITIONS - CSS3 transitions for hover events, auto-expanded and auto-hidden scrollbars. + 6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS + 6.1 THEMES - Scrollbar colors, opacity, dimensions, backgrounds etc. via ready-to-use themes. +*/ + + + +/* +------------------------------------------------------------------------------------------------------------------------ +1. BASIC STYLE +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCustomScrollbar{ -ms-touch-action: pinch-zoom; touch-action: pinch-zoom; /* direct pointer events to js */ } + .mCustomScrollbar.mCS_no_scrollbar, .mCustomScrollbar.mCS_touch_action{ -ms-touch-action: auto; touch-action: auto; } + + .mCustomScrollBox{ /* contains plugin's markup */ + position: relative; + overflow: hidden; + height: 100%; + max-width: 100%; + outline: none; + direction: ltr; + } + + .mCSB_container{ /* contains the original content */ + overflow: hidden; + width: auto; + height: auto; + } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +2. VERTICAL SCROLLBAR +y-axis +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_inside > .mCSB_container{ margin-right: 30px; } + + .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-right: 0; } /* non-visible scrollbar */ + + .mCS-dir-rtl > .mCSB_inside > .mCSB_container{ /* RTL direction/left-side scrollbar */ + margin-right: 0; + margin-left: 30px; + } + + .mCS-dir-rtl > .mCSB_inside > .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-left: 0; } /* RTL direction/left-side scrollbar */ + + .mCSB_scrollTools{ /* contains scrollbar markup (draggable element, dragger rail, buttons etc.) */ + position: absolute; + width: 16px; + height: auto; + left: auto; + top: 0; + right: 0; + bottom: 0; + } + + .mCSB_outside + .mCSB_scrollTools{ right: -26px; } /* scrollbar position: outside */ + + .mCS-dir-rtl > .mCSB_inside > .mCSB_scrollTools, + .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ /* RTL direction/left-side scrollbar */ + right: auto; + left: 0; + } + + .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ left: -26px; } /* RTL direction/left-side scrollbar (scrollbar position: outside) */ + + .mCSB_scrollTools .mCSB_draggerContainer{ /* contains the draggable element and dragger rail markup */ + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + height: auto; + } + + .mCSB_scrollTools a + .mCSB_draggerContainer{ margin: 20px 0; } + + .mCSB_scrollTools .mCSB_draggerRail{ + width: 2px; + height: 100%; + margin: 0 auto; + -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; + } + + .mCSB_scrollTools .mCSB_dragger{ /* the draggable element */ + cursor: pointer; + width: 100%; + height: 30px; /* minimum dragger height */ + z-index: 1; + } + + .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ /* the dragger element */ + position: relative; + width: 4px; + height: 100%; + margin: 0 auto; + -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; + text-align: center; + } + + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ width: 12px; /* auto-expanded scrollbar */ } + + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 8px; /* auto-expanded scrollbar */ } + + .mCSB_scrollTools .mCSB_buttonUp, + .mCSB_scrollTools .mCSB_buttonDown{ + display: block; + position: absolute; + height: 20px; + width: 100%; + overflow: hidden; + margin: 0 auto; + cursor: pointer; + } + + .mCSB_scrollTools .mCSB_buttonDown{ bottom: 0; } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +3. HORIZONTAL SCROLLBAR +x-axis +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_horizontal.mCSB_inside > .mCSB_container{ + margin-right: 0; + margin-bottom: 30px; + } + + .mCSB_horizontal.mCSB_outside > .mCSB_container{ min-height: 100%; } + + .mCSB_horizontal > .mCSB_container.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } /* non-visible scrollbar */ + + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ + width: auto; + height: 16px; + top: auto; + right: 0; + bottom: 0; + left: 0; + } + + .mCustomScrollBox + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ bottom: -26px; } /* scrollbar position: outside */ + + .mCSB_scrollTools.mCSB_scrollTools_horizontal a + .mCSB_draggerContainer{ margin: 0 20px; } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 2px; + margin: 7px 0; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger{ + width: 30px; /* minimum dragger width */ + height: 100%; + left: 0; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 4px; + margin: 6px auto; + } + + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ + height: 12px; /* auto-expanded scrollbar */ + margin: 2px auto; + } + + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + height: 8px; /* auto-expanded scrollbar */ + margin: 4px 0; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft, + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ + display: block; + position: absolute; + width: 20px; + height: 100%; + overflow: hidden; + margin: 0 auto; + cursor: pointer; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft{ left: 0; } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ right: 0; } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +4. VERTICAL AND HORIZONTAL SCROLLBARS +yx-axis +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_container_wrapper{ + position: absolute; + height: auto; + width: auto; + overflow: hidden; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin-right: 30px; + margin-bottom: 30px; + } + + .mCSB_container_wrapper > .mCSB_container{ + padding-right: 30px; + padding-bottom: 30px; + -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; + } + + .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 20px; } + + .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 20px; } + + /* non-visible horizontal scrollbar */ + .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden + .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 0; } + + /* non-visible vertical scrollbar/RTL direction/left-side scrollbar */ + .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 0; } + + /* RTL direction/left-side scrollbar */ + .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 20px; } + + /* non-visible scrollbar/RTL direction/left-side scrollbar */ + .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 0; } + + .mCS-dir-rtl > .mCSB_inside > .mCSB_container_wrapper{ /* RTL direction/left-side scrollbar */ + margin-right: 0; + margin-left: 30px; + } + + .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden > .mCSB_container{ padding-right: 0; } + + .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden > .mCSB_container{ padding-bottom: 0; } + + .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden{ + margin-right: 0; /* non-visible scrollbar */ + margin-left: 0; + } + + /* non-visible horizontal scrollbar */ + .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +5. TRANSITIONS +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_scrollTools, + .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCSB_scrollTools .mCSB_buttonUp, + .mCSB_scrollTools .mCSB_buttonDown, + .mCSB_scrollTools .mCSB_buttonLeft, + .mCSB_scrollTools .mCSB_buttonRight{ + -webkit-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + -moz-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + -o-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + } + + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, /* auto-expanded scrollbar */ + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail{ + -webkit-transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + -moz-transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + -o-transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS +------------------------------------------------------------------------------------------------------------------------ +*/ + + /* + ---------------------------------------- + 6.1 THEMES + ---------------------------------------- + */ + + /* default theme ("light") */ + + .mCSB_scrollTools{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } + + .mCS-autoHide > .mCustomScrollBox > .mCSB_scrollTools, + .mCS-autoHide > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 0; filter: "alpha(opacity=0)"; -ms-filter: "alpha(opacity=0)"; } + + .mCustomScrollbar > .mCustomScrollBox > .mCSB_scrollTools.mCSB_scrollTools_onDrag, + .mCustomScrollbar > .mCustomScrollBox ~ .mCSB_scrollTools.mCSB_scrollTools_onDrag, + .mCustomScrollBox:hover > .mCSB_scrollTools, + .mCustomScrollBox:hover ~ .mCSB_scrollTools, + .mCS-autoHide:hover > .mCustomScrollBox > .mCSB_scrollTools, + .mCS-autoHide:hover > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 1; filter: "alpha(opacity=100)"; -ms-filter: "alpha(opacity=100)"; } + + .mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.4); + filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; + } + + .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.75); + filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; + } + + .mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.85); + filter: "alpha(opacity=85)"; -ms-filter: "alpha(opacity=85)"; + } + .mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.9); + filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; + } + + .mCSB_scrollTools .mCSB_buttonUp, + .mCSB_scrollTools .mCSB_buttonDown, + .mCSB_scrollTools .mCSB_buttonLeft, + .mCSB_scrollTools .mCSB_buttonRight{ + background-image: url(mCSB_buttons.png); /* css sprites */ + background-repeat: no-repeat; + opacity: 0.4; filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; + } + + .mCSB_scrollTools .mCSB_buttonUp{ + background-position: 0 0; + /* + sprites locations + light: 0 0, -16px 0, -32px 0, -48px 0, 0 -72px, -16px -72px, -32px -72px + dark: -80px 0, -96px 0, -112px 0, -128px 0, -80px -72px, -96px -72px, -112px -72px + */ + } + + .mCSB_scrollTools .mCSB_buttonDown{ + background-position: 0 -20px; + /* + sprites locations + light: 0 -20px, -16px -20px, -32px -20px, -48px -20px, 0 -92px, -16px -92px, -32px -92px + dark: -80px -20px, -96px -20px, -112px -20px, -128px -20px, -80px -92px, -96px -92px, -112 -92px + */ + } + + .mCSB_scrollTools .mCSB_buttonLeft{ + background-position: 0 -40px; + /* + sprites locations + light: 0 -40px, -20px -40px, -40px -40px, -60px -40px, 0 -112px, -20px -112px, -40px -112px + dark: -80px -40px, -100px -40px, -120px -40px, -140px -40px, -80px -112px, -100px -112px, -120px -112px + */ + } + + .mCSB_scrollTools .mCSB_buttonRight{ + background-position: 0 -56px; + /* + sprites locations + light: 0 -56px, -20px -56px, -40px -56px, -60px -56px, 0 -128px, -20px -128px, -40px -128px + dark: -80px -56px, -100px -56px, -120px -56px, -140px -56px, -80px -128px, -100px -128px, -120px -128px + */ + } + + .mCSB_scrollTools .mCSB_buttonUp:hover, + .mCSB_scrollTools .mCSB_buttonDown:hover, + .mCSB_scrollTools .mCSB_buttonLeft:hover, + .mCSB_scrollTools .mCSB_buttonRight:hover{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } + + .mCSB_scrollTools .mCSB_buttonUp:active, + .mCSB_scrollTools .mCSB_buttonDown:active, + .mCSB_scrollTools .mCSB_buttonLeft:active, + .mCSB_scrollTools .mCSB_buttonRight:active{ opacity: 0.9; filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; } + + + /* theme: "dark" */ + + .mCS-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } + + .mCS-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.85); } + + .mCS-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.9); } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } + + /* ---------------------------------------- */ + + + + /* theme: "light-2", "dark-2" */ + + .mCS-light-2.mCSB_scrollTools .mCSB_draggerRail, + .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ + width: 4px; + background-color: #fff; background-color: rgba(255,255,255,0.1); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-light-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 4px; + background-color: #fff; background-color: rgba(255,255,255,0.75); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 4px; + margin: 6px auto; + } + + .mCS-light-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } + + .mCS-light-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-light-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px 0; } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -20px; } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -40px; } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -56px; } + + + /* theme: "dark-2" */ + + .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.1); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.75); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px 0; } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -20px; } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -40px; } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -56px; } + + /* ---------------------------------------- */ + + + + /* theme: "light-thick", "dark-thick" */ + + .mCS-light-thick.mCSB_scrollTools .mCSB_draggerRail, + .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ + width: 4px; + background-color: #fff; background-color: rgba(255,255,255,0.1); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 6px; + background-color: #fff; background-color: rgba(255,255,255,0.75); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 4px; + margin: 6px 0; + } + + .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 6px; + margin: 5px auto; + } + + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } + + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px 0; } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -20px; } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -40px; } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -56px; } + + + /* theme: "dark-thick" */ + + .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.1); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.75); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px 0; } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -20px; } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -40px; } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -56px; } + + /* ---------------------------------------- */ + + + + /* theme: "light-thin", "dark-thin" */ + + .mCS-light-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.1); } + + .mCS-light-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 2px; } + + .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail{ width: 100%; } + + .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 2px; + margin: 7px auto; + } + + + /* theme "dark-thin" */ + + .mCS-dark-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } + + /* ---------------------------------------- */ + + + + /* theme "rounded", "rounded-dark", "rounded-dots", "rounded-dots-dark" */ + + .mCS-rounded.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.15); } + + .mCS-rounded.mCSB_scrollTools .mCSB_dragger, + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger, + .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger{ height: 14px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 14px; + margin: 0 1px; + } + + .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 14px; } + + .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + height: 14px; + margin: 1px 0; + } + + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ + width: 16px; /* auto-expanded scrollbar */ + height: 16px; + margin: -1px 0; + } + + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 4px; /* auto-expanded scrollbar */ } + + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ + height: 16px; /* auto-expanded scrollbar */ + width: 16px; + margin: 0 -1px; + } + + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + height: 4px; /* auto-expanded scrollbar */ + margin: 6px 0; + } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonUp{ background-position: 0 -72px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonDown{ background-position: 0 -92px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonLeft{ background-position: 0 -112px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonRight{ background-position: 0 -128px; } + + + /* theme "rounded-dark", "rounded-dots-dark" */ + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px -72px; } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -92px; } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -112px; } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -128px; } + + + /* theme "rounded-dots", "rounded-dots-dark" */ + + .mCS-rounded-dots.mCSB_scrollTools_vertical .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools_vertical .mCSB_draggerRail{ width: 4px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + background-color: transparent; + background-position: center; + } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAANElEQVQYV2NkIAAYiVbw//9/Y6DiM1ANJoyMjGdBbLgJQAX/kU0DKgDLkaQAvxW4HEvQFwCRcxIJK1XznAAAAABJRU5ErkJggg=="); + background-repeat: repeat-y; + opacity: 0.3; + filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; + } + + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + height: 4px; + margin: 6px 0; + background-repeat: repeat-x; + } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px -72px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -92px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -112px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -128px; } + + + /* theme "rounded-dots-dark" */ + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAALElEQVQYV2NkIAAYSVFgDFR8BqrBBEifBbGRTfiPZhpYjiQFBK3A6l6CvgAAE9kGCd1mvgEAAAAASUVORK5CYII="); + } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px -72px; } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -92px; } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -112px; } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -128px; } + + /* ---------------------------------------- */ + + + + /* theme "3d", "3d-dark", "3d-thick", "3d-thick-dark" */ + + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-repeat: repeat-y; + background-image: -moz-linear-gradient(left, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); + background-image: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); + background-image: -webkit-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -o-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -ms-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: linear-gradient(to right, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + background-repeat: repeat-x; + background-image: -moz-linear-gradient(top, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); + background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -o-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -ms-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: linear-gradient(to bottom, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + } + + + /* theme "3d", "3d-dark" */ + + .mCS-3d.mCSB_scrollTools_vertical .mCSB_dragger, + .mCS-3d-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 70px; } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 70px; } + + .mCS-3d.mCSB_scrollTools, + .mCS-3d-dark.mCSB_scrollTools{ + opacity: 1; + filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; + } + + .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; } + + .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, + .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ + width: 8px; + background-color: #000; background-color: rgba(0,0,0,0.2); + box-shadow: inset 1px 0 1px rgba(0,0,0,0.5), inset -1px 0 1px rgba(255,255,255,0.2); + } + + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } + + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 8px; } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 8px; + margin: 4px 0; + box-shadow: inset 0 1px 1px rgba(0,0,0,0.5), inset 0 -1px 1px rgba(255,255,255,0.2); + } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 8px; + margin: 4px auto; + } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme "3d-dark" */ + + .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.1); + box-shadow: inset 1px 0 1px rgba(0,0,0,0.1); + } + + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + /* ---------------------------------------- */ + + + + /* theme: "3d-thick", "3d-thick-dark" */ + + .mCS-3d-thick.mCSB_scrollTools, + .mCS-3d-thick-dark.mCSB_scrollTools{ + opacity: 1; + filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; + } + + .mCS-3d-thick.mCSB_scrollTools, + .mCS-3d-thick-dark.mCSB_scrollTools, + .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ -webkit-border-radius: 7px; -moz-border-radius: 7px; border-radius: 7px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } + + .mCSB_inside + .mCS-3d-thick.mCSB_scrollTools_vertical, + .mCSB_inside + .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ right: 1px; } + + .mCS-3d-thick.mCSB_scrollTools_vertical, + .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ box-shadow: inset 1px 0 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); } + + .mCS-3d-thick.mCSB_scrollTools_horizontal, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ + bottom: 1px; + box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); + } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + box-shadow: inset 1px 0 0 rgba(255,255,255,0.4); + width: 12px; + margin: 2px; + position: absolute; + height: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4); } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } + + .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + height: 12px; + width: auto; + } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer{ + background-color: #000; background-color: rgba(0,0,0,0.05); + box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); + } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme: "3d-thick-dark" */ + + .mCS-3d-thick-dark.mCSB_scrollTools{ box-shadow: inset 0 0 14px rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 1px 0 0 rgba(255,255,255,0.4), inset -1px 0 0 rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), inset 0 -1px 0 rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #777; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ + background-color: #fff; background-color: rgba(0,0,0,0.05); + box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); + } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + /* ---------------------------------------- */ + + + + /* theme: "minimal", "minimal-dark" */ + + .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, + .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ + right: 0; + margin: 12px 0; + } + + .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ + bottom: 0; + margin: 0 12px; + } + + /* RTL direction/left-side scrollbar */ + .mCS-dir-rtl > .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, + .mCS-dir-rtl > .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ + left: 0; + right: auto; + } + + .mCS-minimal.mCSB_scrollTools .mCSB_draggerRail, + .mCS-minimal-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } + + .mCS-minimal.mCSB_scrollTools_vertical .mCSB_dragger, + .mCS-minimal-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 50px; } + + .mCS-minimal.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-minimal-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 50px; } + + .mCS-minimal.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.2); + filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; + } + + .mCS-minimal.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-minimal.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.5); + filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; + } + + + /* theme: "minimal-dark" */ + + .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.2); + filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; + } + + .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.5); + filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; + } + + /* ---------------------------------------- */ + + + + /* theme "light-3", "dark-3" */ + + .mCS-light-3.mCSB_scrollTools .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ + width: 6px; + background-color: #000; background-color: rgba(0,0,0,0.2); + } + + .mCS-light-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 6px; } + + .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 6px; + margin: 5px 0; + } + + .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + width: 12px; + } + + .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + height: 12px; + margin: 2px 0; + } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme "dark-3" */ + + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + /* ---------------------------------------- */ + + + + /* theme "inset", "inset-dark", "inset-2", "inset-2-dark", "inset-3", "inset-3-dark" */ + + .mCS-inset.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ + width: 12px; + background-color: #000; background-color: rgba(0,0,0,0.2); + } + + .mCS-inset.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 6px; + margin: 3px 5px; + position: absolute; + height: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .mCS-inset.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + height: 6px; + margin: 5px 3px; + position: absolute; + width: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .mCS-inset.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 12px; + margin: 2px 0; + } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme "inset-dark", "inset-2-dark", "inset-3-dark" */ + + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + + /* theme "inset-2", "inset-2-dark" */ + + .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-color: transparent; + border-width: 1px; + border-style: solid; + border-color: #fff; + border-color: rgba(255,255,255,0.2); + -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; + } + + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ border-color: #000; border-color: rgba(0,0,0,0.2); } + + + /* theme "inset-3", "inset-3-dark" */ + + .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.6); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.6); } + + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.75); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } + + /* ---------------------------------------- */ diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js new file mode 100644 index 0000000000..4c9a0b2e52 --- /dev/null +++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js @@ -0,0 +1,2458 @@ +/* +== malihu jquery custom scrollbar plugin == +Version: 3.1.5 +Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller +Author: malihu +Author URI: http://manos.malihu.gr +License: MIT License (MIT) +*/ + +/* +Copyright Manos Malihutsakis (email: manos@malihu.gr) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* +The code below is fairly long, fully commented and should be normally used in development. +For production, use either the minified jquery.mCustomScrollbar.min.js script or +the production-ready jquery.mCustomScrollbar.concat.min.js which contains the plugin +and dependencies (minified). +*/ + +(function(factory){ + if(typeof define==="function" && define.amd){ + define(["jquery"],factory); + }else if(typeof module!=="undefined" && module.exports){ + module.exports=factory; + }else{ + factory(jQuery,window,document); + } +}(function($){ +(function(init){ + var _rjs=typeof define==="function" && define.amd, /* RequireJS */ + _njs=typeof module !== "undefined" && module.exports, /* NodeJS */ + _dlp=("https:"==document.location.protocol) ? "https:" : "http:", /* location protocol */ + _url="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"; + if(!_rjs){ + if(_njs){ + require("jquery-mousewheel")($); + }else{ + /* load jquery-mousewheel plugin (via CDN) if it's not present or not loaded via RequireJS + (works when mCustomScrollbar fn is called on window load) */ + $.event.special.mousewheel || $("head").append(decodeURI("%3Cscript src="+_dlp+"//"+_url+"%3E%3C/script%3E")); + } + } + init(); +}(function(){ + + /* + ---------------------------------------- + PLUGIN NAMESPACE, PREFIX, DEFAULT SELECTOR(S) + ---------------------------------------- + */ + + var pluginNS="mCustomScrollbar", + pluginPfx="mCS", + defaultSelector=".mCustomScrollbar", + + + + + + /* + ---------------------------------------- + DEFAULT OPTIONS + ---------------------------------------- + */ + + defaults={ + /* + set element/content width/height programmatically + values: boolean, pixels, percentage + option default + ------------------------------------- + setWidth false + setHeight false + */ + /* + set the initial css top property of content + values: string (e.g. "-100px", "10%" etc.) + */ + setTop:0, + /* + set the initial css left property of content + values: string (e.g. "-100px", "10%" etc.) + */ + setLeft:0, + /* + scrollbar axis (vertical and/or horizontal scrollbars) + values (string): "y", "x", "yx" + */ + axis:"y", + /* + position of scrollbar relative to content + values (string): "inside", "outside" ("outside" requires elements with position:relative) + */ + scrollbarPosition:"inside", + /* + scrolling inertia + values: integer (milliseconds) + */ + scrollInertia:950, + /* + auto-adjust scrollbar dragger length + values: boolean + */ + autoDraggerLength:true, + /* + auto-hide scrollbar when idle + values: boolean + option default + ------------------------------------- + autoHideScrollbar false + */ + /* + auto-expands scrollbar on mouse-over and dragging + values: boolean + option default + ------------------------------------- + autoExpandScrollbar false + */ + /* + always show scrollbar, even when there's nothing to scroll + values: integer (0=disable, 1=always show dragger rail and buttons, 2=always show dragger rail, dragger and buttons), boolean + */ + alwaysShowScrollbar:0, + /* + scrolling always snaps to a multiple of this number in pixels + values: integer, array ([y,x]) + option default + ------------------------------------- + snapAmount null + */ + /* + when snapping, snap with this number in pixels as an offset + values: integer + */ + snapOffset:0, + /* + mouse-wheel scrolling + */ + mouseWheel:{ + /* + enable mouse-wheel scrolling + values: boolean + */ + enable:true, + /* + scrolling amount in pixels + values: "auto", integer + */ + scrollAmount:"auto", + /* + mouse-wheel scrolling axis + the default scrolling direction when both vertical and horizontal scrollbars are present + values (string): "y", "x" + */ + axis:"y", + /* + prevent the default behaviour which automatically scrolls the parent element(s) when end of scrolling is reached + values: boolean + option default + ------------------------------------- + preventDefault null + */ + /* + the reported mouse-wheel delta value. The number of lines (translated to pixels) one wheel notch scrolls. + values: "auto", integer + "auto" uses the default OS/browser value + */ + deltaFactor:"auto", + /* + normalize mouse-wheel delta to -1 or 1 (disables mouse-wheel acceleration) + values: boolean + option default + ------------------------------------- + normalizeDelta null + */ + /* + invert mouse-wheel scrolling direction + values: boolean + option default + ------------------------------------- + invert null + */ + /* + the tags that disable mouse-wheel when cursor is over them + */ + disableOver:["select","option","keygen","datalist","textarea"] + }, + /* + scrollbar buttons + */ + scrollButtons:{ + /* + enable scrollbar buttons + values: boolean + option default + ------------------------------------- + enable null + */ + /* + scrollbar buttons scrolling type + values (string): "stepless", "stepped" + */ + scrollType:"stepless", + /* + scrolling amount in pixels + values: "auto", integer + */ + scrollAmount:"auto" + /* + tabindex of the scrollbar buttons + values: false, integer + option default + ------------------------------------- + tabindex null + */ + }, + /* + keyboard scrolling + */ + keyboard:{ + /* + enable scrolling via keyboard + values: boolean + */ + enable:true, + /* + keyboard scrolling type + values (string): "stepless", "stepped" + */ + scrollType:"stepless", + /* + scrolling amount in pixels + values: "auto", integer + */ + scrollAmount:"auto" + }, + /* + enable content touch-swipe scrolling + values: boolean, integer, string (number) + integer values define the axis-specific minimum amount required for scrolling momentum + */ + contentTouchScroll:25, + /* + enable/disable document (default) touch-swipe scrolling + */ + documentTouchScroll:true, + /* + advanced option parameters + */ + advanced:{ + /* + auto-expand content horizontally (for "x" or "yx" axis) + values: boolean, integer (the value 2 forces the non scrollHeight/scrollWidth method, the value 3 forces the scrollHeight/scrollWidth method) + option default + ------------------------------------- + autoExpandHorizontalScroll null + */ + /* + auto-scroll to elements with focus + */ + autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']", + /* + auto-update scrollbars on content, element or viewport resize + should be true for fluid layouts/elements, adding/removing content dynamically, hiding/showing elements, content with images etc. + values: boolean + */ + updateOnContentResize:true, + /* + auto-update scrollbars each time each image inside the element is fully loaded + values: "auto", boolean + */ + updateOnImageLoad:"auto", + /* + auto-update scrollbars based on the amount and size changes of specific selectors + useful when you need to update the scrollbar(s) automatically, each time a type of element is added, removed or changes its size + values: boolean, string (e.g. "ul li" will auto-update scrollbars each time list-items inside the element are changed) + a value of true (boolean) will auto-update scrollbars each time any element is changed + option default + ------------------------------------- + updateOnSelectorChange null + */ + /* + extra selectors that'll allow scrollbar dragging upon mousemove/up, pointermove/up, touchend etc. (e.g. "selector-1, selector-2") + option default + ------------------------------------- + extraDraggableSelectors null + */ + /* + extra selectors that'll release scrollbar dragging upon mouseup, pointerup, touchend etc. (e.g. "selector-1, selector-2") + option default + ------------------------------------- + releaseDraggableSelectors null + */ + /* + auto-update timeout + values: integer (milliseconds) + */ + autoUpdateTimeout:60 + }, + /* + scrollbar theme + values: string (see CSS/plugin URI for a list of ready-to-use themes) + */ + theme:"light", + /* + user defined callback functions + */ + callbacks:{ + /* + Available callbacks: + callback default + ------------------------------------- + onCreate null + onInit null + onScrollStart null + onScroll null + onTotalScroll null + onTotalScrollBack null + whileScrolling null + onOverflowY null + onOverflowX null + onOverflowYNone null + onOverflowXNone null + onImageLoad null + onSelectorChange null + onBeforeUpdate null + onUpdate null + */ + onTotalScrollOffset:0, + onTotalScrollBackOffset:0, + alwaysTriggerOffsets:true + } + /* + add scrollbar(s) on all elements matching the current selector, now and in the future + values: boolean, string + string values: "on" (enable), "once" (disable after first invocation), "off" (disable) + liveSelector values: string (selector) + option default + ------------------------------------- + live false + liveSelector null + */ + }, + + + + + + /* + ---------------------------------------- + VARS, CONSTANTS + ---------------------------------------- + */ + + totalInstances=0, /* plugin instances amount */ + liveTimers={}, /* live option timers */ + oldIE=(window.attachEvent && !window.addEventListener) ? 1 : 0, /* detect IE < 9 */ + touchActive=false,touchable, /* global touch vars (for touch and pointer events) */ + /* general plugin classes */ + classes=[ + "mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar", + "mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer", + "mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight" + ], + + + + + + /* + ---------------------------------------- + METHODS + ---------------------------------------- + */ + + methods={ + + /* + plugin initialization method + creates the scrollbar(s), plugin data object and options + ---------------------------------------- + */ + + init:function(options){ + + var options=$.extend(true,{},defaults,options), + selector=_selector.call(this); /* validate selector */ + + /* + if live option is enabled, monitor for elements matching the current selector and + apply scrollbar(s) when found (now and in the future) + */ + if(options.live){ + var liveSelector=options.liveSelector || this.selector || defaultSelector, /* live selector(s) */ + $liveSelector=$(liveSelector); /* live selector(s) as jquery object */ + if(options.live==="off"){ + /* + disable live if requested + usage: $(selector).mCustomScrollbar({live:"off"}); + */ + removeLiveTimers(liveSelector); + return; + } + liveTimers[liveSelector]=setTimeout(function(){ + /* call mCustomScrollbar fn on live selector(s) every half-second */ + $liveSelector.mCustomScrollbar(options); + if(options.live==="once" && $liveSelector.length){ + /* disable live after first invocation */ + removeLiveTimers(liveSelector); + } + },500); + }else{ + removeLiveTimers(liveSelector); + } + + /* options backward compatibility (for versions < 3.0.0) and normalization */ + options.setWidth=(options.set_width) ? options.set_width : options.setWidth; + options.setHeight=(options.set_height) ? options.set_height : options.setHeight; + options.axis=(options.horizontalScroll) ? "x" : _findAxis(options.axis); + options.scrollInertia=options.scrollInertia>0 && options.scrollInertia<17 ? 17 : options.scrollInertia; + if(typeof options.mouseWheel!=="object" && options.mouseWheel==true){ /* old school mouseWheel option (non-object) */ + options.mouseWheel={enable:true,scrollAmount:"auto",axis:"y",preventDefault:false,deltaFactor:"auto",normalizeDelta:false,invert:false} + } + options.mouseWheel.scrollAmount=!options.mouseWheelPixels ? options.mouseWheel.scrollAmount : options.mouseWheelPixels; + options.mouseWheel.normalizeDelta=!options.advanced.normalizeMouseWheelDelta ? options.mouseWheel.normalizeDelta : options.advanced.normalizeMouseWheelDelta; + options.scrollButtons.scrollType=_findScrollButtonsType(options.scrollButtons.scrollType); + + _theme(options); /* theme-specific options */ + + /* plugin constructor */ + return $(selector).each(function(){ + + var $this=$(this); + + if(!$this.data(pluginPfx)){ /* prevent multiple instantiations */ + + /* store options and create objects in jquery data */ + $this.data(pluginPfx,{ + idx:++totalInstances, /* instance index */ + opt:options, /* options */ + scrollRatio:{y:null,x:null}, /* scrollbar to content ratio */ + overflowed:null, /* overflowed axis */ + contentReset:{y:null,x:null}, /* object to check when content resets */ + bindEvents:false, /* object to check if events are bound */ + tweenRunning:false, /* object to check if tween is running */ + sequential:{}, /* sequential scrolling object */ + langDir:$this.css("direction"), /* detect/store direction (ltr or rtl) */ + cbOffsets:null, /* object to check whether callback offsets always trigger */ + /* + object to check how scrolling events where last triggered + "internal" (default - triggered by this script), "external" (triggered by other scripts, e.g. via scrollTo method) + usage: object.data("mCS").trigger + */ + trigger:null, + /* + object to check for changes in elements in order to call the update method automatically + */ + poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}} + }); + + var d=$this.data(pluginPfx),o=d.opt, + /* HTML data attributes */ + htmlDataAxis=$this.data("mcs-axis"),htmlDataSbPos=$this.data("mcs-scrollbar-position"),htmlDataTheme=$this.data("mcs-theme"); + + if(htmlDataAxis){o.axis=htmlDataAxis;} /* usage example: data-mcs-axis="y" */ + if(htmlDataSbPos){o.scrollbarPosition=htmlDataSbPos;} /* usage example: data-mcs-scrollbar-position="outside" */ + if(htmlDataTheme){ /* usage example: data-mcs-theme="minimal" */ + o.theme=htmlDataTheme; + _theme(o); /* theme-specific options */ + } + + _pluginMarkup.call(this); /* add plugin markup */ + + if(d && o.callbacks.onCreate && typeof o.callbacks.onCreate==="function"){o.callbacks.onCreate.call(this);} /* callbacks: onCreate */ + + $("#mCSB_"+d.idx+"_container img:not(."+classes[2]+")").addClass(classes[2]); /* flag loaded images */ + + methods.update.call(null,$this); /* call the update method */ + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin update method + updates content and scrollbar(s) values, events and status + ---------------------------------------- + usage: $(selector).mCustomScrollbar("update"); + */ + + update:function(el,cb){ + + var selector=el || _selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; + + if(!mCSB_container.length){return;} + + if(d.tweenRunning){_stop($this);} /* stop any running tweens while updating */ + + if(cb && d && o.callbacks.onBeforeUpdate && typeof o.callbacks.onBeforeUpdate==="function"){o.callbacks.onBeforeUpdate.call(this);} /* callbacks: onBeforeUpdate */ + + /* if element was disabled or destroyed, remove class(es) */ + if($this.hasClass(classes[3])){$this.removeClass(classes[3]);} + if($this.hasClass(classes[4])){$this.removeClass(classes[4]);} + + /* css flexbox fix, detect/set max-height */ + mCustomScrollBox.css("max-height","none"); + if(mCustomScrollBox.height()!==$this.height()){mCustomScrollBox.css("max-height",$this.height());} + + _expandContentHorizontally.call(this); /* expand content horizontally */ + + if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ + mCSB_container.css("width",_contentWidth(mCSB_container)); + } + + d.overflowed=_overflowed.call(this); /* determine if scrolling is required */ + + _scrollbarVisibility.call(this); /* show/hide scrollbar(s) */ + + /* auto-adjust scrollbar dragger length analogous to content */ + if(o.autoDraggerLength){_setDraggerLength.call(this);} + + _scrollRatio.call(this); /* calculate and store scrollbar to content ratio */ + + _bindEvents.call(this); /* bind scrollbar events */ + + /* reset scrolling position and/or events */ + var to=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)]; + if(o.axis!=="x"){ /* y/yx axis */ + if(!d.overflowed[0]){ /* y scrolling is not required */ + _resetContentPosition.call(this); /* reset content position */ + if(o.axis==="y"){ + _unbindEvents.call(this); + }else if(o.axis==="yx" && d.overflowed[1]){ + _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); + } + }else if(mCSB_dragger[0].height()>mCSB_dragger[0].parent().height()){ + _resetContentPosition.call(this); /* reset content position */ + }else{ /* y scrolling is required */ + _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); + d.contentReset.y=null; + } + } + if(o.axis!=="y"){ /* x/yx axis */ + if(!d.overflowed[1]){ /* x scrolling is not required */ + _resetContentPosition.call(this); /* reset content position */ + if(o.axis==="x"){ + _unbindEvents.call(this); + }else if(o.axis==="yx" && d.overflowed[0]){ + _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); + } + }else if(mCSB_dragger[1].width()>mCSB_dragger[1].parent().width()){ + _resetContentPosition.call(this); /* reset content position */ + }else{ /* x scrolling is required */ + _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); + d.contentReset.x=null; + } + } + + /* callbacks: onImageLoad, onSelectorChange, onUpdate */ + if(cb && d){ + if(cb===2 && o.callbacks.onImageLoad && typeof o.callbacks.onImageLoad==="function"){ + o.callbacks.onImageLoad.call(this); + }else if(cb===3 && o.callbacks.onSelectorChange && typeof o.callbacks.onSelectorChange==="function"){ + o.callbacks.onSelectorChange.call(this); + }else if(o.callbacks.onUpdate && typeof o.callbacks.onUpdate==="function"){ + o.callbacks.onUpdate.call(this); + } + } + + _autoUpdate.call(this); /* initialize automatic updating (for dynamic content, fluid layouts etc.) */ + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin scrollTo method + triggers a scrolling event to a specific value + ---------------------------------------- + usage: $(selector).mCustomScrollbar("scrollTo",value,options); + */ + + scrollTo:function(val,options){ + + /* prevent silly things like $(selector).mCustomScrollbar("scrollTo",undefined); */ + if(typeof val=="undefined" || val==null){return;} + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx),o=d.opt, + /* method default options */ + methodDefaults={ + trigger:"external", /* method is by default triggered externally (e.g. from other scripts) */ + scrollInertia:o.scrollInertia, /* scrolling inertia (animation duration) */ + scrollEasing:"mcsEaseInOut", /* animation easing */ + moveDragger:false, /* move dragger instead of content */ + timeout:60, /* scroll-to delay */ + callbacks:true, /* enable/disable callbacks */ + onStart:true, + onUpdate:true, + onComplete:true + }, + methodOptions=$.extend(true,{},methodDefaults,options), + to=_arr.call(this,val),dur=methodOptions.scrollInertia>0 && methodOptions.scrollInertia<17 ? 17 : methodOptions.scrollInertia; + + /* translate yx values to actual scroll-to positions */ + to[0]=_to.call(this,to[0],"y"); + to[1]=_to.call(this,to[1],"x"); + + /* + check if scroll-to value moves the dragger instead of content. + Only pixel values apply on dragger (e.g. 100, "100px", "-=100" etc.) + */ + if(methodOptions.moveDragger){ + to[0]*=d.scrollRatio.y; + to[1]*=d.scrollRatio.x; + } + + methodOptions.dur=_isTabHidden() ? 0 : dur; //skip animations if browser tab is hidden + + setTimeout(function(){ + /* do the scrolling */ + if(to[0]!==null && typeof to[0]!=="undefined" && o.axis!=="x" && d.overflowed[0]){ /* scroll y */ + methodOptions.dir="y"; + methodOptions.overwrite="all"; + _scrollTo($this,to[0].toString(),methodOptions); + } + if(to[1]!==null && typeof to[1]!=="undefined" && o.axis!=="y" && d.overflowed[1]){ /* scroll x */ + methodOptions.dir="x"; + methodOptions.overwrite="none"; + _scrollTo($this,to[1].toString(),methodOptions); + } + },methodOptions.timeout); + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin stop method + stops scrolling animation + ---------------------------------------- + usage: $(selector).mCustomScrollbar("stop"); + */ + stop:function(){ + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + _stop($this); + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin disable method + temporarily disables the scrollbar(s) + ---------------------------------------- + usage: $(selector).mCustomScrollbar("disable",reset); + reset (boolean): resets content position to 0 + */ + disable:function(r){ + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx); + + _autoUpdate.call(this,"remove"); /* remove automatic updating */ + + _unbindEvents.call(this); /* unbind events */ + + if(r){_resetContentPosition.call(this);} /* reset content position */ + + _scrollbarVisibility.call(this,true); /* show/hide scrollbar(s) */ + + $this.addClass(classes[3]); /* add disable class */ + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin destroy method + completely removes the scrollbar(s) and returns the element to its original state + ---------------------------------------- + usage: $(selector).mCustomScrollbar("destroy"); + */ + destroy:function(){ + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx),o=d.opt, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + scrollbar=$(".mCSB_"+d.idx+"_scrollbar"); + + if(o.live){removeLiveTimers(o.liveSelector || $(selector).selector);} /* remove live timers */ + + _autoUpdate.call(this,"remove"); /* remove automatic updating */ + + _unbindEvents.call(this); /* unbind events */ + + _resetContentPosition.call(this); /* reset content position */ + + $this.removeData(pluginPfx); /* remove plugin data object */ + + _delete(this,"mcs"); /* delete callbacks object */ + + /* remove plugin markup */ + scrollbar.remove(); /* remove scrollbar(s) first (those can be either inside or outside plugin's inner wrapper) */ + mCSB_container.find("img."+classes[2]).removeClass(classes[2]); /* remove loaded images flag */ + mCustomScrollBox.replaceWith(mCSB_container.contents()); /* replace plugin's inner wrapper with the original content */ + /* remove plugin classes from the element and add destroy class */ + $this.removeClass(pluginNS+" _"+pluginPfx+"_"+d.idx+" "+classes[6]+" "+classes[7]+" "+classes[5]+" "+classes[3]).addClass(classes[4]); + + } + + }); + + } + /* ---------------------------------------- */ + + }, + + + + + + /* + ---------------------------------------- + FUNCTIONS + ---------------------------------------- + */ + + /* validates selector (if selector is invalid or undefined uses the default one) */ + _selector=function(){ + return (typeof $(this)!=="object" || $(this).length<1) ? defaultSelector : this; + }, + /* -------------------- */ + + + /* changes options according to theme */ + _theme=function(obj){ + var fixedSizeScrollbarThemes=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"], + nonExpandedScrollbarThemes=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"], + disabledScrollButtonsThemes=["minimal","minimal-dark"], + enabledAutoHideScrollbarThemes=["minimal","minimal-dark"], + scrollbarPositionOutsideThemes=["minimal","minimal-dark"]; + obj.autoDraggerLength=$.inArray(obj.theme,fixedSizeScrollbarThemes) > -1 ? false : obj.autoDraggerLength; + obj.autoExpandScrollbar=$.inArray(obj.theme,nonExpandedScrollbarThemes) > -1 ? false : obj.autoExpandScrollbar; + obj.scrollButtons.enable=$.inArray(obj.theme,disabledScrollButtonsThemes) > -1 ? false : obj.scrollButtons.enable; + obj.autoHideScrollbar=$.inArray(obj.theme,enabledAutoHideScrollbarThemes) > -1 ? true : obj.autoHideScrollbar; + obj.scrollbarPosition=$.inArray(obj.theme,scrollbarPositionOutsideThemes) > -1 ? "outside" : obj.scrollbarPosition; + }, + /* -------------------- */ + + + /* live option timers removal */ + removeLiveTimers=function(selector){ + if(liveTimers[selector]){ + clearTimeout(liveTimers[selector]); + _delete(liveTimers,selector); + } + }, + /* -------------------- */ + + + /* normalizes axis option to valid values: "y", "x", "yx" */ + _findAxis=function(val){ + return (val==="yx" || val==="xy" || val==="auto") ? "yx" : (val==="x" || val==="horizontal") ? "x" : "y"; + }, + /* -------------------- */ + + + /* normalizes scrollButtons.scrollType option to valid values: "stepless", "stepped" */ + _findScrollButtonsType=function(val){ + return (val==="stepped" || val==="pixels" || val==="step" || val==="click") ? "stepped" : "stepless"; + }, + /* -------------------- */ + + + /* generates plugin markup */ + _pluginMarkup=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + expandClass=o.autoExpandScrollbar ? " "+classes[1]+"_expand" : "", + scrollbar=["
","
"], + wrapperClass=o.axis==="yx" ? "mCSB_vertical_horizontal" : o.axis==="x" ? "mCSB_horizontal" : "mCSB_vertical", + scrollbars=o.axis==="yx" ? scrollbar[0]+scrollbar[1] : o.axis==="x" ? scrollbar[1] : scrollbar[0], + contentWrapper=o.axis==="yx" ? "
" : "", + autoHideClass=o.autoHideScrollbar ? " "+classes[6] : "", + scrollbarDirClass=(o.axis!=="x" && d.langDir==="rtl") ? " "+classes[7] : ""; + if(o.setWidth){$this.css("width",o.setWidth);} /* set element width */ + if(o.setHeight){$this.css("height",o.setHeight);} /* set element height */ + o.setLeft=(o.axis!=="y" && d.langDir==="rtl") ? "989999px" : o.setLeft; /* adjust left position for rtl direction */ + $this.addClass(pluginNS+" _"+pluginPfx+"_"+d.idx+autoHideClass+scrollbarDirClass).wrapInner("
"); + var mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ + mCSB_container.css("width",_contentWidth(mCSB_container)); + } + if(o.scrollbarPosition==="outside"){ + if($this.css("position")==="static"){ /* requires elements with non-static position */ + $this.css("position","relative"); + } + $this.css("overflow","visible"); + mCustomScrollBox.addClass("mCSB_outside").after(scrollbars); + }else{ + mCustomScrollBox.addClass("mCSB_inside").append(scrollbars); + mCSB_container.wrap(contentWrapper); + } + _scrollButtons.call(this); /* add scrollbar buttons */ + /* minimum dragger length */ + var mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; + mCSB_dragger[0].css("min-height",mCSB_dragger[0].height()); + mCSB_dragger[1].css("min-width",mCSB_dragger[1].width()); + }, + /* -------------------- */ + + + /* calculates content width */ + _contentWidth=function(el){ + var val=[el[0].scrollWidth,Math.max.apply(Math,el.children().map(function(){return $(this).outerWidth(true);}).get())],w=el.parent().width(); + return val[0]>w ? val[0] : val[1]>w ? val[1] : "100%"; + }, + /* -------------------- */ + + + /* expands content horizontally */ + _expandContentHorizontally=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(o.advanced.autoExpandHorizontalScroll && o.axis!=="y"){ + /* calculate scrollWidth */ + mCSB_container.css({"width":"auto","min-width":0,"overflow-x":"scroll"}); + var w=Math.ceil(mCSB_container[0].scrollWidth); + if(o.advanced.autoExpandHorizontalScroll===3 || (o.advanced.autoExpandHorizontalScroll!==2 && w>mCSB_container.parent().width())){ + mCSB_container.css({"width":w,"min-width":"100%","overflow-x":"inherit"}); + }else{ + /* + wrap content with an infinite width div and set its position to absolute and width to auto. + Setting width to auto before calculating the actual width is important! + We must let the browser set the width as browser zoom values are impossible to calculate. + */ + mCSB_container.css({"overflow-x":"inherit","position":"absolute"}) + .wrap("
") + .css({ /* set actual width, original position and un-wrap */ + /* + get the exact width (with decimals) and then round-up. + Using jquery outerWidth() will round the width value which will mess up with inner elements that have non-integer width + */ + "width":(Math.ceil(mCSB_container[0].getBoundingClientRect().right+0.4)-Math.floor(mCSB_container[0].getBoundingClientRect().left)), + "min-width":"100%", + "position":"relative" + }).unwrap(); + } + } + }, + /* -------------------- */ + + + /* adds scrollbar buttons */ + _scrollButtons=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_scrollTools=$(".mCSB_"+d.idx+"_scrollbar:first"), + tabindex=!_isNumeric(o.scrollButtons.tabindex) ? "" : "tabindex='"+o.scrollButtons.tabindex+"'", + btnHTML=[ + "", + "", + "", + "" + ], + btn=[(o.axis==="x" ? btnHTML[2] : btnHTML[0]),(o.axis==="x" ? btnHTML[3] : btnHTML[1]),btnHTML[2],btnHTML[3]]; + if(o.scrollButtons.enable){ + mCSB_scrollTools.prepend(btn[0]).append(btn[1]).next(".mCSB_scrollTools").prepend(btn[2]).append(btn[3]); + } + }, + /* -------------------- */ + + + /* auto-adjusts scrollbar dragger length */ + _setDraggerLength=function(){ + var $this=$(this),d=$this.data(pluginPfx), + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], + ratio=[mCustomScrollBox.height()/mCSB_container.outerHeight(false),mCustomScrollBox.width()/mCSB_container.outerWidth(false)], + l=[ + parseInt(mCSB_dragger[0].css("min-height")),Math.round(ratio[0]*mCSB_dragger[0].parent().height()), + parseInt(mCSB_dragger[1].css("min-width")),Math.round(ratio[1]*mCSB_dragger[1].parent().width()) + ], + h=oldIE && (l[1]contentHeight){contentHeight=h;} + if(w>contentWidth){contentWidth=w;} + return [contentHeight>mCustomScrollBox.height(),contentWidth>mCustomScrollBox.width()]; + }, + /* -------------------- */ + + + /* resets content position to 0 */ + _resetContentPosition=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; + _stop($this); /* stop any current scrolling before resetting */ + if((o.axis!=="x" && !d.overflowed[0]) || (o.axis==="y" && d.overflowed[0])){ /* reset y */ + mCSB_dragger[0].add(mCSB_container).css("top",0); + _scrollTo($this,"_resetY"); + } + if((o.axis!=="y" && !d.overflowed[1]) || (o.axis==="x" && d.overflowed[1])){ /* reset x */ + var cx=dx=0; + if(d.langDir==="rtl"){ /* adjust left position for rtl direction */ + cx=mCustomScrollBox.width()-mCSB_container.outerWidth(false); + dx=Math.abs(cx/d.scrollRatio.x); + } + mCSB_container.css("left",cx); + mCSB_dragger[1].css("left",dx); + _scrollTo($this,"_resetX"); + } + }, + /* -------------------- */ + + + /* binds scrollbar events */ + _bindEvents=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt; + if(!d.bindEvents){ /* check if events are already bound */ + _draggable.call(this); + if(o.contentTouchScroll){_contentDraggable.call(this);} + _selectable.call(this); + if(o.mouseWheel.enable){ /* bind mousewheel fn when plugin is available */ + function _mwt(){ + mousewheelTimeout=setTimeout(function(){ + if(!$.event.special.mousewheel){ + _mwt(); + }else{ + clearTimeout(mousewheelTimeout); + _mousewheel.call($this[0]); + } + },100); + } + var mousewheelTimeout; + _mwt(); + } + _draggerRail.call(this); + _wrapperScroll.call(this); + if(o.advanced.autoScrollOnFocus){_focus.call(this);} + if(o.scrollButtons.enable){_buttons.call(this);} + if(o.keyboard.enable){_keyboard.call(this);} + d.bindEvents=true; + } + }, + /* -------------------- */ + + + /* unbinds scrollbar events */ + _unbindEvents=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + sb=".mCSB_"+d.idx+"_scrollbar", + sel=$("#mCSB_"+d.idx+",#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,"+sb+" ."+classes[12]+",#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal,"+sb+">a"), + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(o.advanced.releaseDraggableSelectors){sel.add($(o.advanced.releaseDraggableSelectors));} + if(o.advanced.extraDraggableSelectors){sel.add($(o.advanced.extraDraggableSelectors));} + if(d.bindEvents){ /* check if events are bound */ + /* unbind namespaced events from document/selectors */ + $(document).add($(!_canAccessIFrame() || top.document)).unbind("."+namespace); + sel.each(function(){ + $(this).unbind("."+namespace); + }); + /* clear and delete timeouts/objects */ + clearTimeout($this[0]._focusTimeout); _delete($this[0],"_focusTimeout"); + clearTimeout(d.sequential.step); _delete(d.sequential,"step"); + clearTimeout(mCSB_container[0].onCompleteTimeout); _delete(mCSB_container[0],"onCompleteTimeout"); + d.bindEvents=false; + } + }, + /* -------------------- */ + + + /* toggles scrollbar visibility */ + _scrollbarVisibility=function(disabled){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + contentWrapper=$("#mCSB_"+d.idx+"_container_wrapper"), + content=contentWrapper.length ? contentWrapper : $("#mCSB_"+d.idx+"_container"), + scrollbar=[$("#mCSB_"+d.idx+"_scrollbar_vertical"),$("#mCSB_"+d.idx+"_scrollbar_horizontal")], + mCSB_dragger=[scrollbar[0].find(".mCSB_dragger"),scrollbar[1].find(".mCSB_dragger")]; + if(o.axis!=="x"){ + if(d.overflowed[0] && !disabled){ + scrollbar[0].add(mCSB_dragger[0]).add(scrollbar[0].children("a")).css("display","block"); + content.removeClass(classes[8]+" "+classes[10]); + }else{ + if(o.alwaysShowScrollbar){ + if(o.alwaysShowScrollbar!==2){mCSB_dragger[0].css("display","none");} + content.removeClass(classes[10]); + }else{ + scrollbar[0].css("display","none"); + content.addClass(classes[10]); + } + content.addClass(classes[8]); + } + } + if(o.axis!=="y"){ + if(d.overflowed[1] && !disabled){ + scrollbar[1].add(mCSB_dragger[1]).add(scrollbar[1].children("a")).css("display","block"); + content.removeClass(classes[9]+" "+classes[11]); + }else{ + if(o.alwaysShowScrollbar){ + if(o.alwaysShowScrollbar!==2){mCSB_dragger[1].css("display","none");} + content.removeClass(classes[11]); + }else{ + scrollbar[1].css("display","none"); + content.addClass(classes[11]); + } + content.addClass(classes[9]); + } + } + if(!d.overflowed[0] && !d.overflowed[1]){ + $this.addClass(classes[5]); + }else{ + $this.removeClass(classes[5]); + } + }, + /* -------------------- */ + + + /* returns input coordinates of pointer, touch and mouse events (relative to document) */ + _coordinates=function(e){ + var t=e.type,o=e.target.ownerDocument!==document && frameElement!==null ? [$(frameElement).offset().top,$(frameElement).offset().left] : null, + io=_canAccessIFrame() && e.target.ownerDocument!==top.document && frameElement!==null ? [$(e.view.frameElement).offset().top,$(e.view.frameElement).offset().left] : [0,0]; + switch(t){ + case "pointerdown": case "MSPointerDown": case "pointermove": case "MSPointerMove": case "pointerup": case "MSPointerUp": + return o ? [e.originalEvent.pageY-o[0]+io[0],e.originalEvent.pageX-o[1]+io[1],false] : [e.originalEvent.pageY,e.originalEvent.pageX,false]; + break; + case "touchstart": case "touchmove": case "touchend": + var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0], + touches=e.originalEvent.touches.length || e.originalEvent.changedTouches.length; + return e.target.ownerDocument!==document ? [touch.screenY,touch.screenX,touches>1] : [touch.pageY,touch.pageX,touches>1]; + break; + default: + return o ? [e.pageY-o[0]+io[0],e.pageX-o[1]+io[1],false] : [e.pageY,e.pageX,false]; + } + }, + /* -------------------- */ + + + /* + SCROLLBAR DRAG EVENTS + scrolls content via scrollbar dragging + */ + _draggable=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + draggerId=["mCSB_"+d.idx+"_dragger_vertical","mCSB_"+d.idx+"_dragger_horizontal"], + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=$("#"+draggerId[0]+",#"+draggerId[1]), + draggable,dragY,dragX, + rds=o.advanced.releaseDraggableSelectors ? mCSB_dragger.add($(o.advanced.releaseDraggableSelectors)) : mCSB_dragger, + eds=o.advanced.extraDraggableSelectors ? $(!_canAccessIFrame() || top.document).add($(o.advanced.extraDraggableSelectors)) : $(!_canAccessIFrame() || top.document); + mCSB_dragger.bind("contextmenu."+namespace,function(e){ + e.preventDefault(); //prevent right click + }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ + e.stopImmediatePropagation(); + e.preventDefault(); + if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ + touchActive=true; + if(oldIE){document.onselectstart=function(){return false;}} /* disable text selection for IE < 9 */ + _iframe.call(mCSB_container,false); /* enable scrollbar dragging over iframes by disabling their events */ + _stop($this); + draggable=$(this); + var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, + h=draggable.height()+offset.top,w=draggable.width()+offset.left; + if(y0 && x0){ + dragY=y; + dragX=x; + } + _onDragClasses(draggable,"active",o.autoExpandScrollbar); + }).bind("touchmove."+namespace,function(e){ + e.stopImmediatePropagation(); + e.preventDefault(); + var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; + _drag(dragY,dragX,y,x); + }); + $(document).add(eds).bind("mousemove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace,function(e){ + if(draggable){ + var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; + if(dragY===y && dragX===x){return;} /* has it really moved? */ + _drag(dragY,dragX,y,x); + } + }).add(rds).bind("mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ + if(draggable){ + _onDragClasses(draggable,"active",o.autoExpandScrollbar); + draggable=null; + } + touchActive=false; + if(oldIE){document.onselectstart=null;} /* enable text selection for IE < 9 */ + _iframe.call(mCSB_container,true); /* enable iframes events */ + }); + function _drag(dragY,dragX,y,x){ + mCSB_container[0].idleTimer=o.scrollInertia<233 ? 250 : 0; + if(draggable.attr("id")===draggerId[1]){ + var dir="x",to=((draggable[0].offsetLeft-dragX)+x)*d.scrollRatio.x; + }else{ + var dir="y",to=((draggable[0].offsetTop-dragY)+y)*d.scrollRatio.y; + } + _scrollTo($this,to.toString(),{dir:dir,drag:true}); + } + }, + /* -------------------- */ + + + /* + TOUCH SWIPE EVENTS + scrolls content via touch swipe + Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices + */ + _contentDraggable=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], + draggable,dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount, + durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[],touchDrag,docDrag, + iframe=mCSB_container.find("iframe"), + events=[ + "touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace, //start + "touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace, //move + "touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace //end + ], + touchAction=document.body.style.touchAction!==undefined && document.body.style.touchAction!==""; + mCSB_container.bind(events[0],function(e){ + _onTouchstart(e); + }).bind(events[1],function(e){ + _onTouchmove(e); + }); + mCustomScrollBox.bind(events[0],function(e){ + _onTouchstart2(e); + }).bind(events[2],function(e){ + _onTouchend(e); + }); + if(iframe.length){ + iframe.each(function(){ + $(this).bind("load",function(){ + /* bind events on accessible iframes */ + if(_canAccessIFrame(this)){ + $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ + _onTouchstart(e); + _onTouchstart2(e); + }).bind(events[1],function(e){ + _onTouchmove(e); + }).bind(events[2],function(e){ + _onTouchend(e); + }); + } + }); + }); + } + function _onTouchstart(e){ + if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;} + touchable=1; touchDrag=0; docDrag=0; draggable=1; + $this.removeClass("mCS_touch_action"); + var offset=mCSB_container.offset(); + dragY=_coordinates(e)[0]-offset.top; + dragX=_coordinates(e)[1]-offset.left; + touchIntent=[_coordinates(e)[0],_coordinates(e)[1]]; + } + function _onTouchmove(e){ + if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;} + if(!o.documentTouchScroll){e.preventDefault();} + e.stopImmediatePropagation(); + if(docDrag && !touchDrag){return;} + if(draggable){ + runningTime=_getTime(); + var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, + easing="mcsLinearOut"; + touchMoveY.push(y); + touchMoveX.push(x); + touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]); + if(d.overflowed[0]){ + var limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), + prevent=((dragY-y)>0 && (y-dragY)>-(limit*d.scrollRatio.y) && (touchIntent[3]*20 && (x-dragX)>-(limitX*d.scrollRatio.x) && (touchIntent[2]*230){return;} + speed=1000/(endTime-startTime); + var easing="mcsEaseOut",slow=speed<2.5, + diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0]; + distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX]; + var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])]; + speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed]; + var a=[ + Math.abs(mCSB_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])), + Math.abs(mCSB_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1])) + ]; + amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null]; + durB=[(absDistance[0]*4)+o.scrollInertia,(absDistance[1]*4)+o.scrollInertia]; + var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */ + amount[0]=absDistance[0]>md ? amount[0] : 0; + amount[1]=absDistance[1]>md ? amount[1] : 0; + if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite,false);} + if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite,false);} + } + function _m(ds,s){ + var r=[s*1.5,s*2,s/1.5,s/2]; + if(ds>90){ + return s>4 ? r[0] : r[3]; + }else if(ds>60){ + return s>3 ? r[3] : r[2]; + }else if(ds>30){ + return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2]; + }else{ + return s>8 ? s : r[3]; + } + } + function _drag(amount,dur,easing,dir,overwrite,drag){ + if(!amount){return;} + _scrollTo($this,amount.toString(),{dur:dur,scrollEasing:easing,dir:dir,overwrite:overwrite,drag:drag}); + } + }, + /* -------------------- */ + + + /* + SELECT TEXT EVENTS + scrolls content when text is selected + */ + _selectable=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, + namespace=pluginPfx+"_"+d.idx, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + action; + mCSB_container.bind("mousedown."+namespace,function(e){ + if(touchable){return;} + if(!action){action=1; touchActive=true;} + }).add(document).bind("mousemove."+namespace,function(e){ + if(!touchable && action && _sel()){ + var offset=mCSB_container.offset(), + y=_coordinates(e)[0]-offset.top+mCSB_container[0].offsetTop,x=_coordinates(e)[1]-offset.left+mCSB_container[0].offsetLeft; + if(y>0 && y0 && xwrapper.height()){ + _seq("on",40); + } + } + if(o.axis!=="y" && d.overflowed[1]){ + if(x<0){ + _seq("on",37); + }else if(x>wrapper.width()){ + _seq("on",39); + } + } + } + } + }).bind("mouseup."+namespace+" dragend."+namespace,function(e){ + if(touchable){return;} + if(action){action=0; _seq("off",null);} + touchActive=false; + }); + function _sel(){ + return window.getSelection ? window.getSelection().toString() : + document.selection && document.selection.type!="Control" ? document.selection.createRange().text : 0; + } + function _seq(a,c,s){ + seq.type=s && action ? "stepped" : "stepless"; + seq.scrollAmount=10; + _sequentialScroll($this,a,c,"mcsLinearOut",s ? 60 : null); + } + }, + /* -------------------- */ + + + /* + MOUSE WHEEL EVENT + scrolls content via mouse-wheel + via mouse-wheel plugin (https://github.com/brandonaaron/jquery-mousewheel) + */ + _mousewheel=function(){ + if(!$(this).data(pluginPfx)){return;} /* Check if the scrollbar is ready to use mousewheel events (issue: #185) */ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], + iframe=$("#mCSB_"+d.idx+"_container").find("iframe"); + if(iframe.length){ + iframe.each(function(){ + $(this).bind("load",function(){ + /* bind events on accessible iframes */ + if(_canAccessIFrame(this)){ + $(this.contentDocument || this.contentWindow.document).bind("mousewheel."+namespace,function(e,delta){ + _onMousewheel(e,delta); + }); + } + }); + }); + } + mCustomScrollBox.bind("mousewheel."+namespace,function(e,delta){ + _onMousewheel(e,delta); + }); + function _onMousewheel(e,delta){ + _stop($this); + if(_disableMousewheel($this,e.target)){return;} /* disables mouse-wheel when hovering specific elements */ + var deltaFactor=o.mouseWheel.deltaFactor!=="auto" ? parseInt(o.mouseWheel.deltaFactor) : (oldIE && e.deltaFactor<100) ? 100 : e.deltaFactor || 100, + dur=o.scrollInertia; + if(o.axis==="x" || o.mouseWheel.axis==="x"){ + var dir="x", + px=[Math.round(deltaFactor*d.scrollRatio.x),parseInt(o.mouseWheel.scrollAmount)], + amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.width() ? mCustomScrollBox.width()*0.9 : px[0], + contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetLeft), + draggerPos=mCSB_dragger[1][0].offsetLeft, + limit=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(), + dlt=o.mouseWheel.axis==="y" ? (e.deltaY || delta) : e.deltaX; + }else{ + var dir="y", + px=[Math.round(deltaFactor*d.scrollRatio.y),parseInt(o.mouseWheel.scrollAmount)], + amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.height() ? mCustomScrollBox.height()*0.9 : px[0], + contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetTop), + draggerPos=mCSB_dragger[0][0].offsetTop, + limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), + dlt=e.deltaY || delta; + } + if((dir==="y" && !d.overflowed[0]) || (dir==="x" && !d.overflowed[1])){return;} + if(o.mouseWheel.invert || e.webkitDirectionInvertedFromDevice){dlt=-dlt;} + if(o.mouseWheel.normalizeDelta){dlt=dlt<0 ? -1 : 1;} + if((dlt>0 && draggerPos!==0) || (dlt<0 && draggerPos!==limit) || o.mouseWheel.preventDefault){ + e.stopImmediatePropagation(); + e.preventDefault(); + } + if(e.deltaFactor<5 && !o.mouseWheel.normalizeDelta){ + //very low deltaFactor values mean some kind of delta acceleration (e.g. osx trackpad), so adjusting scrolling accordingly + amount=e.deltaFactor; dur=17; + } + _scrollTo($this,(contentPos-(dlt*amount)).toString(),{dir:dir,dur:dur}); + } + }, + /* -------------------- */ + + + /* checks if iframe can be accessed */ + _canAccessIFrameCache=new Object(), + _canAccessIFrame=function(iframe){ + var result=false,cacheKey=false,html=null; + if(iframe===undefined){ + cacheKey="#empty"; + }else if($(iframe).attr("id")!==undefined){ + cacheKey=$(iframe).attr("id"); + } + if(cacheKey!==false && _canAccessIFrameCache[cacheKey]!==undefined){ + return _canAccessIFrameCache[cacheKey]; + } + if(!iframe){ + try{ + var doc=top.document; + html=doc.body.innerHTML; + }catch(err){/* do nothing */} + result=(html!==null); + }else{ + try{ + var doc=iframe.contentDocument || iframe.contentWindow.document; + html=doc.body.innerHTML; + }catch(err){/* do nothing */} + result=(html!==null); + } + if(cacheKey!==false){_canAccessIFrameCache[cacheKey]=result;} + return result; + }, + /* -------------------- */ + + + /* switches iframe's pointer-events property (drag, mousewheel etc. over cross-domain iframes) */ + _iframe=function(evt){ + var el=this.find("iframe"); + if(!el.length){return;} /* check if content contains iframes */ + var val=!evt ? "none" : "auto"; + el.css("pointer-events",val); /* for IE11, iframe's display property should not be "block" */ + }, + /* -------------------- */ + + + /* disables mouse-wheel when hovering specific elements like select, datalist etc. */ + _disableMousewheel=function(el,target){ + var tag=target.nodeName.toLowerCase(), + tags=el.data(pluginPfx).opt.mouseWheel.disableOver, + /* elements that require focus */ + focusTags=["select","textarea"]; + return $.inArray(tag,tags) > -1 && !($.inArray(tag,focusTags) > -1 && !$(target).is(":focus")); + }, + /* -------------------- */ + + + /* + DRAGGER RAIL CLICK EVENT + scrolls content via dragger rail + */ + _draggerRail=function(){ + var $this=$(this),d=$this.data(pluginPfx), + namespace=pluginPfx+"_"+d.idx, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + mCSB_draggerContainer=$(".mCSB_"+d.idx+"_scrollbar ."+classes[12]), + clickable; + mCSB_draggerContainer.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ + touchActive=true; + if(!$(e.target).hasClass("mCSB_dragger")){clickable=1;} + }).bind("touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ + touchActive=false; + }).bind("click."+namespace,function(e){ + if(!clickable){return;} + clickable=0; + if($(e.target).hasClass(classes[12]) || $(e.target).hasClass("mCSB_draggerRail")){ + _stop($this); + var el=$(this),mCSB_dragger=el.find(".mCSB_dragger"); + if(el.parent(".mCSB_scrollTools_horizontal").length>0){ + if(!d.overflowed[1]){return;} + var dir="x", + clickDir=e.pageX>mCSB_dragger.offset().left ? -1 : 1, + to=Math.abs(mCSB_container[0].offsetLeft)-(clickDir*(wrapper.width()*0.9)); + }else{ + if(!d.overflowed[0]){return;} + var dir="y", + clickDir=e.pageY>mCSB_dragger.offset().top ? -1 : 1, + to=Math.abs(mCSB_container[0].offsetTop)-(clickDir*(wrapper.height()*0.9)); + } + _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); + } + }); + }, + /* -------------------- */ + + + /* + FOCUS EVENT + scrolls content via element focus (e.g. clicking an input, pressing TAB key etc.) + */ + _focus=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(); + mCSB_container.bind("focusin."+namespace,function(e){ + var el=$(document.activeElement), + nested=mCSB_container.find(".mCustomScrollBox").length, + dur=0; + if(!el.is(o.advanced.autoScrollOnFocus)){return;} + _stop($this); + clearTimeout($this[0]._focusTimeout); + $this[0]._focusTimer=nested ? (dur+17)*nested : 0; + $this[0]._focusTimeout=setTimeout(function(){ + var to=[_childPos(el)[0],_childPos(el)[1]], + contentPos=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], + isVisible=[ + (contentPos[0]+to[0]>=0 && contentPos[0]+to[0]=0 && contentPos[0]+to[1]a"); + btn.bind("contextmenu."+namespace,function(e){ + e.preventDefault(); //prevent right click + }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace+" mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace+" mouseout."+namespace+" pointerout."+namespace+" MSPointerOut."+namespace+" click."+namespace,function(e){ + e.preventDefault(); + if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ + var btnClass=$(this).attr("class"); + seq.type=o.scrollButtons.scrollType; + switch(e.type){ + case "mousedown": case "touchstart": case "pointerdown": case "MSPointerDown": + if(seq.type==="stepped"){return;} + touchActive=true; + d.tweenRunning=false; + _seq("on",btnClass); + break; + case "mouseup": case "touchend": case "pointerup": case "MSPointerUp": + case "mouseout": case "pointerout": case "MSPointerOut": + if(seq.type==="stepped"){return;} + touchActive=false; + if(seq.dir){_seq("off",btnClass);} + break; + case "click": + if(seq.type!=="stepped" || d.tweenRunning){return;} + _seq("on",btnClass); + break; + } + function _seq(a,c){ + seq.scrollAmount=o.scrollButtons.scrollAmount; + _sequentialScroll($this,a,c); + } + }); + }, + /* -------------------- */ + + + /* + KEYBOARD EVENTS + scrolls content via keyboard + Keys: up arrow, down arrow, left arrow, right arrow, PgUp, PgDn, Home, End + */ + _keyboard=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, + namespace=pluginPfx+"_"+d.idx, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + editables="input,textarea,select,datalist,keygen,[contenteditable='true']", + iframe=mCSB_container.find("iframe"), + events=["blur."+namespace+" keydown."+namespace+" keyup."+namespace]; + if(iframe.length){ + iframe.each(function(){ + $(this).bind("load",function(){ + /* bind events on accessible iframes */ + if(_canAccessIFrame(this)){ + $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ + _onKeyboard(e); + }); + } + }); + }); + } + mCustomScrollBox.attr("tabindex","0").bind(events[0],function(e){ + _onKeyboard(e); + }); + function _onKeyboard(e){ + switch(e.type){ + case "blur": + if(d.tweenRunning && seq.dir){_seq("off",null);} + break; + case "keydown": case "keyup": + var code=e.keyCode ? e.keyCode : e.which,action="on"; + if((o.axis!=="x" && (code===38 || code===40)) || (o.axis!=="y" && (code===37 || code===39))){ + /* up (38), down (40), left (37), right (39) arrows */ + if(((code===38 || code===40) && !d.overflowed[0]) || ((code===37 || code===39) && !d.overflowed[1])){return;} + if(e.type==="keyup"){action="off";} + if(!$(document.activeElement).is(editables)){ + e.preventDefault(); + e.stopImmediatePropagation(); + _seq(action,code); + } + }else if(code===33 || code===34){ + /* PgUp (33), PgDn (34) */ + if(d.overflowed[0] || d.overflowed[1]){ + e.preventDefault(); + e.stopImmediatePropagation(); + } + if(e.type==="keyup"){ + _stop($this); + var keyboardDir=code===34 ? -1 : 1; + if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ + var dir="x",to=Math.abs(mCSB_container[0].offsetLeft)-(keyboardDir*(wrapper.width()*0.9)); + }else{ + var dir="y",to=Math.abs(mCSB_container[0].offsetTop)-(keyboardDir*(wrapper.height()*0.9)); + } + _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); + } + }else if(code===35 || code===36){ + /* End (35), Home (36) */ + if(!$(document.activeElement).is(editables)){ + if(d.overflowed[0] || d.overflowed[1]){ + e.preventDefault(); + e.stopImmediatePropagation(); + } + if(e.type==="keyup"){ + if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ + var dir="x",to=code===35 ? Math.abs(wrapper.width()-mCSB_container.outerWidth(false)) : 0; + }else{ + var dir="y",to=code===35 ? Math.abs(wrapper.height()-mCSB_container.outerHeight(false)) : 0; + } + _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); + } + } + } + break; + } + function _seq(a,c){ + seq.type=o.keyboard.scrollType; + seq.scrollAmount=o.keyboard.scrollAmount; + if(seq.type==="stepped" && d.tweenRunning){return;} + _sequentialScroll($this,a,c); + } + } + }, + /* -------------------- */ + + + /* scrolls content sequentially (used when scrolling via buttons, keyboard arrows etc.) */ + _sequentialScroll=function(el,action,trigger,e,s){ + var d=el.data(pluginPfx),o=d.opt,seq=d.sequential, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + once=seq.type==="stepped" ? true : false, + steplessSpeed=o.scrollInertia < 26 ? 26 : o.scrollInertia, /* 26/1.5=17 */ + steppedSpeed=o.scrollInertia < 1 ? 17 : o.scrollInertia; + switch(action){ + case "on": + seq.dir=[ + (trigger===classes[16] || trigger===classes[15] || trigger===39 || trigger===37 ? "x" : "y"), + (trigger===classes[13] || trigger===classes[15] || trigger===38 || trigger===37 ? -1 : 1) + ]; + _stop(el); + if(_isNumeric(trigger) && seq.type==="stepped"){return;} + _on(once); + break; + case "off": + _off(); + if(once || (d.tweenRunning && seq.dir)){ + _on(true); + } + break; + } + + /* starts sequence */ + function _on(once){ + if(o.snapAmount){seq.scrollAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : seq.dir[0]==="x" ? o.snapAmount[1] : o.snapAmount[0];} /* scrolling snapping */ + var c=seq.type!=="stepped", /* continuous scrolling */ + t=s ? s : !once ? 1000/60 : c ? steplessSpeed/1.5 : steppedSpeed, /* timer */ + m=!once ? 2.5 : c ? 7.5 : 40, /* multiplier */ + contentPos=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)], + ratio=[d.scrollRatio.y>10 ? 10 : d.scrollRatio.y,d.scrollRatio.x>10 ? 10 : d.scrollRatio.x], + amount=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*(ratio[1]*m)) : contentPos[0]+(seq.dir[1]*(ratio[0]*m)), + px=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*parseInt(seq.scrollAmount)) : contentPos[0]+(seq.dir[1]*parseInt(seq.scrollAmount)), + to=seq.scrollAmount!=="auto" ? px : amount, + easing=e ? e : !once ? "mcsLinear" : c ? "mcsLinearOut" : "mcsEaseInOut", + onComplete=!once ? false : true; + if(once && t<17){ + to=seq.dir[0]==="x" ? contentPos[1] : contentPos[0]; + } + _scrollTo(el,to.toString(),{dir:seq.dir[0],scrollEasing:easing,dur:t,onComplete:onComplete}); + if(once){ + seq.dir=false; + return; + } + clearTimeout(seq.step); + seq.step=setTimeout(function(){ + _on(); + },t); + } + /* stops sequence */ + function _off(){ + clearTimeout(seq.step); + _delete(seq,"step"); + _stop(el); + } + }, + /* -------------------- */ + + + /* returns a yx array from value */ + _arr=function(val){ + var o=$(this).data(pluginPfx).opt,vals=[]; + if(typeof val==="function"){val=val();} /* check if the value is a single anonymous function */ + /* check if value is object or array, its length and create an array with yx values */ + if(!(val instanceof Array)){ /* object value (e.g. {y:"100",x:"100"}, 100 etc.) */ + vals[0]=val.y ? val.y : val.x || o.axis==="x" ? null : val; + vals[1]=val.x ? val.x : val.y || o.axis==="y" ? null : val; + }else{ /* array value (e.g. [100,100]) */ + vals=val.length>1 ? [val[0],val[1]] : o.axis==="x" ? [null,val[0]] : [val[0],null]; + } + /* check if array values are anonymous functions */ + if(typeof vals[0]==="function"){vals[0]=vals[0]();} + if(typeof vals[1]==="function"){vals[1]=vals[1]();} + return vals; + }, + /* -------------------- */ + + + /* translates values (e.g. "top", 100, "100px", "#id") to actual scroll-to positions */ + _to=function(val,dir){ + if(val==null || typeof val=="undefined"){return;} + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + t=typeof val; + if(!dir){dir=o.axis==="x" ? "x" : "y";} + var contentLength=dir==="x" ? mCSB_container.outerWidth(false)-wrapper.width() : mCSB_container.outerHeight(false)-wrapper.height(), + contentPos=dir==="x" ? mCSB_container[0].offsetLeft : mCSB_container[0].offsetTop, + cssProp=dir==="x" ? "left" : "top"; + switch(t){ + case "function": /* this currently is not used. Consider removing it */ + return val(); + break; + case "object": /* js/jquery object */ + var obj=val.jquery ? val : $(val); + if(!obj.length){return;} + return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; + break; + case "string": case "number": + if(_isNumeric(val)){ /* numeric value */ + return Math.abs(val); + }else if(val.indexOf("%")!==-1){ /* percentage value */ + return Math.abs(contentLength*parseInt(val)/100); + }else if(val.indexOf("-=")!==-1){ /* decrease value */ + return Math.abs(contentPos-parseInt(val.split("-=")[1])); + }else if(val.indexOf("+=")!==-1){ /* inrease value */ + var p=(contentPos+parseInt(val.split("+=")[1])); + return p>=0 ? 0 : Math.abs(p); + }else if(val.indexOf("px")!==-1 && _isNumeric(val.split("px")[0])){ /* pixels string value (e.g. "100px") */ + return Math.abs(val.split("px")[0]); + }else{ + if(val==="top" || val==="left"){ /* special strings */ + return 0; + }else if(val==="bottom"){ + return Math.abs(wrapper.height()-mCSB_container.outerHeight(false)); + }else if(val==="right"){ + return Math.abs(wrapper.width()-mCSB_container.outerWidth(false)); + }else if(val==="first" || val==="last"){ + var obj=mCSB_container.find(":"+val); + return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; + }else{ + if($(val).length){ /* jquery selector */ + return dir==="x" ? _childPos($(val))[1] : _childPos($(val))[0]; + }else{ /* other values (e.g. "100em") */ + mCSB_container.css(cssProp,val); + methods.update.call(null,$this[0]); + return; + } + } + } + break; + } + }, + /* -------------------- */ + + + /* calls the update method automatically */ + _autoUpdate=function(rem){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(rem){ + /* + removes autoUpdate timer + usage: _autoUpdate.call(this,"remove"); + */ + clearTimeout(mCSB_container[0].autoUpdate); + _delete(mCSB_container[0],"autoUpdate"); + return; + } + upd(); + function upd(){ + clearTimeout(mCSB_container[0].autoUpdate); + if($this.parents("html").length===0){ + /* check element in dom tree */ + $this=null; + return; + } + mCSB_container[0].autoUpdate=setTimeout(function(){ + /* update on specific selector(s) length and size change */ + if(o.advanced.updateOnSelectorChange){ + d.poll.change.n=sizesSum(); + if(d.poll.change.n!==d.poll.change.o){ + d.poll.change.o=d.poll.change.n; + doUpd(3); + return; + } + } + /* update on main element and scrollbar size changes */ + if(o.advanced.updateOnContentResize){ + d.poll.size.n=$this[0].scrollHeight+$this[0].scrollWidth+mCSB_container[0].offsetHeight+$this[0].offsetHeight+$this[0].offsetWidth; + if(d.poll.size.n!==d.poll.size.o){ + d.poll.size.o=d.poll.size.n; + doUpd(1); + return; + } + } + /* update on image load */ + if(o.advanced.updateOnImageLoad){ + if(!(o.advanced.updateOnImageLoad==="auto" && o.axis==="y")){ //by default, it doesn't run on vertical content + d.poll.img.n=mCSB_container.find("img").length; + if(d.poll.img.n!==d.poll.img.o){ + d.poll.img.o=d.poll.img.n; + mCSB_container.find("img").each(function(){ + imgLoader(this); + }); + return; + } + } + } + if(o.advanced.updateOnSelectorChange || o.advanced.updateOnContentResize || o.advanced.updateOnImageLoad){upd();} + },o.advanced.autoUpdateTimeout); + } + /* a tiny image loader */ + function imgLoader(el){ + if($(el).hasClass(classes[2])){doUpd(); return;} + var img=new Image(); + function createDelegate(contextObject,delegateMethod){ + return function(){return delegateMethod.apply(contextObject,arguments);} + } + function imgOnLoad(){ + this.onload=null; + $(el).addClass(classes[2]); + doUpd(2); + } + img.onload=createDelegate(img,imgOnLoad); + img.src=el.src; + } + /* returns the total height and width sum of all elements matching the selector */ + function sizesSum(){ + if(o.advanced.updateOnSelectorChange===true){o.advanced.updateOnSelectorChange="*";} + var total=0,sel=mCSB_container.find(o.advanced.updateOnSelectorChange); + if(o.advanced.updateOnSelectorChange && sel.length>0){sel.each(function(){total+=this.offsetHeight+this.offsetWidth;});} + return total; + } + /* calls the update method */ + function doUpd(cb){ + clearTimeout(mCSB_container[0].autoUpdate); + methods.update.call(null,$this[0],cb); + } + }, + /* -------------------- */ + + + /* snaps scrolling to a multiple of a pixels number */ + _snapAmount=function(to,amount,offset){ + return (Math.round(to/amount)*amount-offset); + }, + /* -------------------- */ + + + /* stops content and scrollbar animations */ + _stop=function(el){ + var d=el.data(pluginPfx), + sel=$("#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal"); + sel.each(function(){ + _stopTween.call(this); + }); + }, + /* -------------------- */ + + + /* + ANIMATES CONTENT + This is where the actual scrolling happens + */ + _scrollTo=function(el,to,options){ + var d=el.data(pluginPfx),o=d.opt, + defaults={ + trigger:"internal", + dir:"y", + scrollEasing:"mcsEaseOut", + drag:false, + dur:o.scrollInertia, + overwrite:"all", + callbacks:true, + onStart:true, + onUpdate:true, + onComplete:true + }, + options=$.extend(defaults,options), + dur=[options.dur,(options.drag ? 0 : options.dur)], + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + totalScrollOffsets=o.callbacks.onTotalScrollOffset ? _arr.call(el,o.callbacks.onTotalScrollOffset) : [0,0], + totalScrollBackOffsets=o.callbacks.onTotalScrollBackOffset ? _arr.call(el,o.callbacks.onTotalScrollBackOffset) : [0,0]; + d.trigger=options.trigger; + if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){ /* always reset scrollTop/Left */ + $(".mCSB_"+d.idx+"_scrollbar").css("visibility","visible"); + wrapper.scrollTop(0).scrollLeft(0); + } + if(to==="_resetY" && !d.contentReset.y){ + /* callbacks: onOverflowYNone */ + if(_cb("onOverflowYNone")){o.callbacks.onOverflowYNone.call(el[0]);} + d.contentReset.y=1; + } + if(to==="_resetX" && !d.contentReset.x){ + /* callbacks: onOverflowXNone */ + if(_cb("onOverflowXNone")){o.callbacks.onOverflowXNone.call(el[0]);} + d.contentReset.x=1; + } + if(to==="_resetY" || to==="_resetX"){return;} + if((d.contentReset.y || !el[0].mcs) && d.overflowed[0]){ + /* callbacks: onOverflowY */ + if(_cb("onOverflowY")){o.callbacks.onOverflowY.call(el[0]);} + d.contentReset.x=null; + } + if((d.contentReset.x || !el[0].mcs) && d.overflowed[1]){ + /* callbacks: onOverflowX */ + if(_cb("onOverflowX")){o.callbacks.onOverflowX.call(el[0]);} + d.contentReset.x=null; + } + if(o.snapAmount){ /* scrolling snapping */ + var snapAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : options.dir==="x" ? o.snapAmount[1] : o.snapAmount[0]; + to=_snapAmount(to,snapAmount,o.snapOffset); + } + switch(options.dir){ + case "x": + var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_horizontal"), + property="left", + contentPos=mCSB_container[0].offsetLeft, + limit=[ + mCustomScrollBox.width()-mCSB_container.outerWidth(false), + mCSB_dragger.parent().width()-mCSB_dragger.width() + ], + scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.x)], + tso=totalScrollOffsets[1], + tsbo=totalScrollBackOffsets[1], + totalScrollOffset=tso>0 ? tso/d.scrollRatio.x : 0, + totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.x : 0; + break; + case "y": + var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_vertical"), + property="top", + contentPos=mCSB_container[0].offsetTop, + limit=[ + mCustomScrollBox.height()-mCSB_container.outerHeight(false), + mCSB_dragger.parent().height()-mCSB_dragger.height() + ], + scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.y)], + tso=totalScrollOffsets[0], + tsbo=totalScrollBackOffsets[0], + totalScrollOffset=tso>0 ? tso/d.scrollRatio.y : 0, + totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.y : 0; + break; + } + if(scrollTo[1]<0 || (scrollTo[0]===0 && scrollTo[1]===0)){ + scrollTo=[0,0]; + }else if(scrollTo[1]>=limit[1]){ + scrollTo=[limit[0],limit[1]]; + }else{ + scrollTo[0]=-scrollTo[0]; + } + if(!el[0].mcs){ + _mcs(); /* init mcs object (once) to make it available before callbacks */ + if(_cb("onInit")){o.callbacks.onInit.call(el[0]);} /* callbacks: onInit */ + } + clearTimeout(mCSB_container[0].onCompleteTimeout); + _tweenTo(mCSB_dragger[0],property,Math.round(scrollTo[1]),dur[1],options.scrollEasing); + if(!d.tweenRunning && ((contentPos===0 && scrollTo[0]>=0) || (contentPos===limit[0] && scrollTo[0]<=limit[0]))){return;} + _tweenTo(mCSB_container[0],property,Math.round(scrollTo[0]),dur[0],options.scrollEasing,options.overwrite,{ + onStart:function(){ + if(options.callbacks && options.onStart && !d.tweenRunning){ + /* callbacks: onScrollStart */ + if(_cb("onScrollStart")){_mcs(); o.callbacks.onScrollStart.call(el[0]);} + d.tweenRunning=true; + _onDragClasses(mCSB_dragger); + d.cbOffsets=_cbOffsets(); + } + },onUpdate:function(){ + if(options.callbacks && options.onUpdate){ + /* callbacks: whileScrolling */ + if(_cb("whileScrolling")){_mcs(); o.callbacks.whileScrolling.call(el[0]);} + } + },onComplete:function(){ + if(options.callbacks && options.onComplete){ + if(o.axis==="yx"){clearTimeout(mCSB_container[0].onCompleteTimeout);} + var t=mCSB_container[0].idleTimer || 0; + mCSB_container[0].onCompleteTimeout=setTimeout(function(){ + /* callbacks: onScroll, onTotalScroll, onTotalScrollBack */ + if(_cb("onScroll")){_mcs(); o.callbacks.onScroll.call(el[0]);} + if(_cb("onTotalScroll") && scrollTo[1]>=limit[1]-totalScrollOffset && d.cbOffsets[0]){_mcs(); o.callbacks.onTotalScroll.call(el[0]);} + if(_cb("onTotalScrollBack") && scrollTo[1]<=totalScrollBackOffset && d.cbOffsets[1]){_mcs(); o.callbacks.onTotalScrollBack.call(el[0]);} + d.tweenRunning=false; + mCSB_container[0].idleTimer=0; + _onDragClasses(mCSB_dragger,"hide"); + },t); + } + } + }); + /* checks if callback function exists */ + function _cb(cb){ + return d && o.callbacks[cb] && typeof o.callbacks[cb]==="function"; + } + /* checks whether callback offsets always trigger */ + function _cbOffsets(){ + return [o.callbacks.alwaysTriggerOffsets || contentPos>=limit[0]+tso,o.callbacks.alwaysTriggerOffsets || contentPos<=-tsbo]; + } + /* + populates object with useful values for the user + values: + content: this.mcs.content + content top position: this.mcs.top + content left position: this.mcs.left + dragger top position: this.mcs.draggerTop + dragger left position: this.mcs.draggerLeft + scrolling y percentage: this.mcs.topPct + scrolling x percentage: this.mcs.leftPct + scrolling direction: this.mcs.direction + */ + function _mcs(){ + var cp=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], /* content position */ + dp=[mCSB_dragger[0].offsetTop,mCSB_dragger[0].offsetLeft], /* dragger position */ + cl=[mCSB_container.outerHeight(false),mCSB_container.outerWidth(false)], /* content length */ + pl=[mCustomScrollBox.height(),mCustomScrollBox.width()]; /* content parent length */ + el[0].mcs={ + content:mCSB_container, /* original content wrapper as jquery object */ + top:cp[0],left:cp[1],draggerTop:dp[0],draggerLeft:dp[1], + topPct:Math.round((100*Math.abs(cp[0]))/(Math.abs(cl[0])-pl[0])),leftPct:Math.round((100*Math.abs(cp[1]))/(Math.abs(cl[1])-pl[1])), + direction:options.dir + }; + /* + this refers to the original element containing the scrollbar(s) + usage: this.mcs.top, this.mcs.leftPct etc. + */ + } + }, + /* -------------------- */ + + + /* + CUSTOM JAVASCRIPT ANIMATION TWEEN + Lighter and faster than jquery animate() and css transitions + Animates top/left properties and includes easings + */ + _tweenTo=function(el,prop,to,duration,easing,overwrite,callbacks){ + if(!el._mTween){el._mTween={top:{},left:{}};} + var callbacks=callbacks || {}, + onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){}, + startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop]; + if(prop==="left"){from=el.offsetLeft;} + var diff=to-from; + tobj.stop=0; + if(overwrite!=="none"){_cancelTween();} + _startTween(); + function _step(){ + if(tobj.stop){return;} + if(!progress){onStart.call();} + progress=_getTime()-startTime; + _tween(); + if(progress>=tobj.time){ + tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1; + if(tobj.time0){ + tobj.currVal=_ease(tobj.time,from,diff,duration,easing); + elStyle[prop]=Math.round(tobj.currVal)+"px"; + }else{ + elStyle[prop]=to+"px"; + } + onUpdate.call(); + } + function _startTween(){ + _delay=1000/60; + tobj.time=progress+_delay; + _request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame; + tobj.id=_request(_step); + } + function _cancelTween(){ + if(tobj.id==null){return;} + if(!window.requestAnimationFrame){clearTimeout(tobj.id); + }else{window.cancelAnimationFrame(tobj.id);} + tobj.id=null; + } + function _ease(t,b,c,d,type){ + switch(type){ + case "linear": case "mcsLinear": + return c*t/d + b; + break; + case "mcsLinearOut": + t/=d; t--; return c * Math.sqrt(1 - t*t) + b; + break; + case "easeInOutSmooth": + t/=d/2; + if(t<1) return c/2*t*t + b; + t--; + return -c/2 * (t*(t-2) - 1) + b; + break; + case "easeInOutStrong": + t/=d/2; + if(t<1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b; + t--; + return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b; + break; + case "easeInOut": case "mcsEaseInOut": + t/=d/2; + if(t<1) return c/2*t*t*t + b; + t-=2; + return c/2*(t*t*t + 2) + b; + break; + case "easeOutSmooth": + t/=d; t--; + return -c * (t*t*t*t - 1) + b; + break; + case "easeOutStrong": + return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b; + break; + case "easeOut": case "mcsEaseOut": default: + var ts=(t/=d)*t,tc=ts*t; + return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t); + } + } + }, + /* -------------------- */ + + + /* returns current time */ + _getTime=function(){ + if(window.performance && window.performance.now){ + return window.performance.now(); + }else{ + if(window.performance && window.performance.webkitNow){ + return window.performance.webkitNow(); + }else{ + if(Date.now){return Date.now();}else{return new Date().getTime();} + } + } + }, + /* -------------------- */ + + + /* stops a tween */ + _stopTween=function(){ + var el=this; + if(!el._mTween){el._mTween={top:{},left:{}};} + var props=["top","left"]; + for(var i=0; i
` [[`8c310bc`](https://github.com/PrismJS/prism/commit/8c310bc)]
+* Fixing to initial copyright year [[`69cbf7a`](https://github.com/PrismJS/prism/commit/69cbf7a)]
+* Simplify the “lang” regex [[`417f54a`](https://github.com/PrismJS/prism/commit/417f54a)]
+* Fix broken heading links [[`a7f9e62`](https://github.com/PrismJS/prism/commit/a7f9e62)]
+* Prevent infinite recursion in DFS [[`02894e1`](https://github.com/PrismJS/prism/commit/02894e1)]
+* Fix incorrect page title [[`544b56f`](https://github.com/PrismJS/prism/commit/544b56f)]
+* Link scss to webplatform wiki [[`08d979a`](https://github.com/PrismJS/prism/commit/08d979a)]
+* Revert white-space to normal when code is inline instead of in a pre [[`1a971b5`](https://github.com/PrismJS/prism/commit/1a971b5)]
+
+## 1.3.0 (2015-10-26)
+
+### New components
+
+* __AsciiDoc__ ([#800](https://github.com/PrismJS/prism/issues/800)) [[`6803ca0`](https://github.com/PrismJS/prism/commit/6803ca0)]
+* __Haxe__ ([#811](https://github.com/PrismJS/prism/issues/811)) [[`bd44341`](https://github.com/PrismJS/prism/commit/bd44341)]
+* __Icon__ ([#803](https://github.com/PrismJS/prism/issues/803)) [[`b43c5f3`](https://github.com/PrismJS/prism/commit/b43c5f3)]
+* __Kotlin ([#814](https://github.com/PrismJS/prism/issues/814)) [[`e8a31a5`](https://github.com/PrismJS/prism/commit/e8a31a5)]
+* __Lua__ ([#804](https://github.com/PrismJS/prism/issues/804)) [[`a36bc4a`](https://github.com/PrismJS/prism/commit/a36bc4a)]
+* __Nix__ ([#795](https://github.com/PrismJS/prism/issues/795)) [[`9b275c8`](https://github.com/PrismJS/prism/commit/9b275c8)]
+* __Oz__ ([#805](https://github.com/PrismJS/prism/issues/805)) [[`388c53f`](https://github.com/PrismJS/prism/commit/388c53f)]
+* __PARI/GP__ ([#802](https://github.com/PrismJS/prism/issues/802)) [[`253c035`](https://github.com/PrismJS/prism/commit/253c035)]
+* __Parser__ ([#808](https://github.com/PrismJS/prism/issues/808)) [[`a953b3a`](https://github.com/PrismJS/prism/commit/a953b3a)]
+* __Puppet__ ([#813](https://github.com/PrismJS/prism/issues/813)) [[`81933ee`](https://github.com/PrismJS/prism/commit/81933ee)]
+* __Roboconf__ ([#812](https://github.com/PrismJS/prism/issues/812)) [[`f5db346`](https://github.com/PrismJS/prism/commit/f5db346)]
+
+### Updated components
+
+* __C__:
+	* Highlight directives in preprocessor lines ([#801](https://github.com/PrismJS/prism/issues/801)) [[`ad316a3`](https://github.com/PrismJS/prism/commit/ad316a3)]
+* __C#__:
+	* Highlight directives in preprocessor lines ([#801](https://github.com/PrismJS/prism/issues/801)) [[`ad316a3`](https://github.com/PrismJS/prism/commit/ad316a3)]
+	* Fix detection of float numbers ([#806](https://github.com/PrismJS/prism/issues/806)) [[`1dae72b`](https://github.com/PrismJS/prism/commit/1dae72b)]
+* __F#__:
+	* Highlight directives in preprocessor lines ([#801](https://github.com/PrismJS/prism/issues/801)) [[`ad316a3`](https://github.com/PrismJS/prism/commit/ad316a3)]
+* __JavaScript__:
+	* Highlight true and false as booleans ([#801](https://github.com/PrismJS/prism/issues/801)) [[`ad316a3`](https://github.com/PrismJS/prism/commit/ad316a3)]
+* __Python__:
+	* Highlight triple-quoted strings before comments. Fix [#815](https://github.com/PrismJS/prism/issues/815) [[`90fbf0b`](https://github.com/PrismJS/prism/commit/90fbf0b)]
+
+### New plugins
+
+* __Previewer: Time__ ([#790](https://github.com/PrismJS/prism/issues/790)) [[`88173de`](https://github.com/PrismJS/prism/commit/88173de)]
+* __Previewer: Angle__ ([#791](https://github.com/PrismJS/prism/issues/791)) [[`a434c86`](https://github.com/PrismJS/prism/commit/a434c86)]
+
+### Other changes
+
+* Increase mocha's timeout [[`f1c41db`](https://github.com/PrismJS/prism/commit/f1c41db)]
+* Prevent most errors in IE8. Fix [#9](https://github.com/PrismJS/prism/issues/9) [[`9652d75`](https://github.com/PrismJS/prism/commit/9652d75)]
+* Add U.S. Web Design Standards on homepage. Fix [#785](https://github.com/PrismJS/prism/issues/785) [[`e10d48b`](https://github.com/PrismJS/prism/commit/e10d48b), [`79ebbf8`](https://github.com/PrismJS/prism/commit/79ebbf8), [`2f7088d`](https://github.com/PrismJS/prism/commit/2f7088d)]
+* Added gulp task to autolink PRs and commits in changelog [[`5ec4e4d`](https://github.com/PrismJS/prism/commit/5ec4e4d)]
+* Use child processes to run each set of tests, in order to deal with the memory leak in vm.runInNewContext() [[`9a4b6fa`](https://github.com/PrismJS/prism/commit/9a4b6fa)]
+
+## 1.2.0 (2015-10-07)
+
+### New components
+
+* __Batch__ ([#781](https://github.com/PrismJS/prism/issues/781)) [[`eab5b06`](https://github.com/PrismJS/prism/commit/eab5b06)]
+
+### Updated components
+
+* __ASP.NET__:
+	* Simplified pattern for `"),t.textContent=e.code,n.appendChild(t),e.element.parentNode.replaceChild(n,e.element),e.element=t,void 0}var n=e.element.parentNode;!e.code&&n&&"pre"==n.nodeName.toLowerCase()&&e.element.childNodes.length&&"#comment"==e.element.childNodes[0].nodeName&&(e.element.textContent=e.code=e.element.childNodes[0].textContent)}))}();
\ No newline at end of file
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.css
new file mode 100644
index 0000000000..43b7165a86
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.css
@@ -0,0 +1,11 @@
+code[class*="language-"] a[href],
+pre[class*="language-"] a[href] {
+	cursor: help;
+	text-decoration: none;
+}
+
+code[class*="language-"] a[href]:hover,
+pre[class*="language-"] a[href]:hover {
+	cursor: help;
+	text-decoration: underline;
+}
\ No newline at end of file
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.js b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.js
new file mode 100644
index 0000000000..dc147d4f65
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.js
@@ -0,0 +1,169 @@
+(function(){
+
+if (
+	typeof self !== 'undefined' && !self.Prism ||
+	typeof global !== 'undefined' && !global.Prism
+) {
+	return;
+}
+
+if (Prism.languages.css) {
+	// check whether the selector is an advanced pattern before extending it
+	if (Prism.languages.css.selector.pattern)
+	{
+		Prism.languages.css.selector.inside['pseudo-class'] = /:[\w-]+/;
+		Prism.languages.css.selector.inside['pseudo-element'] = /::[\w-]+/;
+	}
+	else
+	{
+		Prism.languages.css.selector = {
+			pattern: Prism.languages.css.selector,
+			inside: {
+				'pseudo-class': /:[\w-]+/,
+				'pseudo-element': /::[\w-]+/
+			}
+		};
+	}
+}
+
+if (Prism.languages.markup) {
+	Prism.languages.markup.tag.inside.tag.inside['tag-id'] = /[\w-]+/;
+	
+	var Tags = {
+		HTML: {
+			'a': 1, 'abbr': 1, 'acronym': 1, 'b': 1, 'basefont': 1, 'bdo': 1, 'big': 1, 'blink': 1, 'cite': 1, 'code': 1, 'dfn': 1, 'em': 1, 'kbd': 1,  'i': 1, 
+			'rp': 1, 'rt': 1, 'ruby': 1, 's': 1, 'samp': 1, 'small': 1, 'spacer': 1, 'strike': 1, 'strong': 1, 'sub': 1, 'sup': 1, 'time': 1, 'tt': 1,  'u': 1, 
+			'var': 1, 'wbr': 1, 'noframes': 1, 'summary': 1, 'command': 1, 'dt': 1, 'dd': 1, 'figure': 1, 'figcaption': 1, 'center': 1, 'section': 1, 'nav': 1,
+			'article': 1, 'aside': 1, 'hgroup': 1, 'header': 1, 'footer': 1, 'address': 1, 'noscript': 1, 'isIndex': 1, 'main': 1, 'mark': 1, 'marquee': 1,
+			'meter': 1, 'menu': 1
+		},
+		SVG: {
+			'animateColor': 1, 'animateMotion': 1, 'animateTransform': 1, 'glyph': 1, 'feBlend': 1, 'feColorMatrix': 1, 'feComponentTransfer': 1, 
+			'feFuncR': 1, 'feFuncG': 1, 'feFuncB': 1, 'feFuncA': 1, 'feComposite': 1, 'feConvolveMatrix': 1, 'feDiffuseLighting': 1, 'feDisplacementMap': 1, 
+			'feFlood': 1, 'feGaussianBlur': 1, 'feImage': 1, 'feMerge': 1, 'feMergeNode': 1, 'feMorphology': 1, 'feOffset': 1, 'feSpecularLighting': 1, 
+			'feTile': 1, 'feTurbulence': 1, 'feDistantLight': 1, 'fePointLight': 1, 'feSpotLight': 1, 'linearGradient': 1, 'radialGradient': 1, 'altGlyph': 1, 
+			'textPath': 1, 'tref': 1, 'altglyph': 1, 'textpath': 1, 'altglyphdef': 1, 'altglyphitem': 1, 'clipPath': 1, 'color-profile': 1, 'cursor': 1,
+			'font-face': 1, 'font-face-format': 1, 'font-face-name': 1, 'font-face-src': 1, 'font-face-uri': 1, 'foreignObject': 1, 'glyphRef': 1,
+			'hkern': 1, 'vkern': 1
+		},
+		MathML: {}
+	}
+}
+
+var language;
+
+Prism.hooks.add('wrap', function(env) {
+	if ((env.type == 'tag-id'
+		|| (env.type == 'property' && env.content.indexOf('-') != 0)
+		|| (env.type == 'rule'&& env.content.indexOf('@-') != 0)
+		|| (env.type == 'pseudo-class'&& env.content.indexOf(':-') != 0) 
+		|| (env.type == 'pseudo-element'&& env.content.indexOf('::-') != 0) 
+        || (env.type == 'attr-name' && env.content.indexOf('data-') != 0)
+		) && env.content.indexOf('<') === -1
+	) {
+		if (env.language == 'css'
+			|| env.language == 'scss'
+			|| env.language == 'markup'
+		) {
+			var href = 'https://webplatform.github.io/docs/';
+			var content = env.content;
+
+			if (env.language == 'css' || env.language == 'scss') {
+				href += 'css/';
+
+				if (env.type == 'property') {
+					href += 'properties/';
+				}
+				else if (env.type == 'rule') {
+					href += 'atrules/';
+					content = content.substring(1);
+				}
+				else if (env.type == 'pseudo-class') {
+					href += 'selectors/pseudo-classes/';
+					content = content.substring(1);
+				}
+				else if (env.type == 'pseudo-element') {
+					href += 'selectors/pseudo-elements/';
+					content = content.substring(2);
+				}
+			}
+			else if (env.language == 'markup') {
+				if (env.type == 'tag-id') {
+					// Check language
+					language = getLanguage(env.content) || language;
+
+					if (language) {
+						href += language + '/elements/';
+					}
+					else {
+						return; // Abort
+					}
+				}
+				else if (env.type == 'attr-name') {
+					if (language) {
+						href += language + '/attributes/';
+					}
+					else {
+						return; // Abort
+					}
+				}
+			}
+
+			href += content;
+			env.tag = 'a';
+			env.attributes.href = href;
+			env.attributes.target = '_blank';
+		}
+	}
+});
+
+function getLanguage(tag) {
+	var tagL = tag.toLowerCase();
+	
+	if (Tags.HTML[tagL]) {
+		return 'html';
+	}
+	else if (Tags.SVG[tag]) {
+		return 'svg';
+	}
+	else if (Tags.MathML[tag]) {
+		return 'mathml';
+	}
+	
+	// Not in dictionary, perform check
+	if (Tags.HTML[tagL] !== 0 && typeof document !== 'undefined') {
+		var htmlInterface = (document.createElement(tag).toString().match(/\[object HTML(.+)Element\]/) || [])[1];
+		
+		if (htmlInterface && htmlInterface != 'Unknown') {
+			Tags.HTML[tagL] = 1;
+			return 'html';
+		}
+	}
+	
+	Tags.HTML[tagL] = 0;
+	
+	if (Tags.SVG[tag] !== 0 && typeof document !== 'undefined') {
+		var svgInterface = (document.createElementNS('http://www.w3.org/2000/svg', tag).toString().match(/\[object SVG(.+)Element\]/) || [])[1];
+		
+		if (svgInterface && svgInterface != 'Unknown') {
+			Tags.SVG[tag] = 1;
+			return 'svg';
+		}
+	}
+	
+	Tags.SVG[tag] = 0;
+	
+	// Lame way to detect MathML, but browsers don’t expose interface names there :(
+	if (Tags.MathML[tag] !== 0) {
+		if (tag.indexOf('m') === 0) {
+			Tags.MathML[tag] = 1;
+			return 'mathml';
+		}
+	}
+	
+	Tags.MathML[tag] = 0;
+	
+	return null;
+}
+
+})();
\ No newline at end of file
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.min.js b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.min.js
new file mode 100644
index 0000000000..86bad36272
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/plugins/wpd/prism-wpd.min.js
@@ -0,0 +1 @@
+!function(){function e(e){var n=e.toLowerCase();if(t.HTML[n])return"html";if(t.SVG[e])return"svg";if(t.MathML[e])return"mathml";if(0!==t.HTML[n]&&"undefined"!=typeof document){var a=(document.createElement(e).toString().match(/\[object HTML(.+)Element\]/)||[])[1];if(a&&"Unknown"!=a)return t.HTML[n]=1,"html"}if(t.HTML[n]=0,0!==t.SVG[e]&&"undefined"!=typeof document){var s=(document.createElementNS("http://www.w3.org/2000/svg",e).toString().match(/\[object SVG(.+)Element\]/)||[])[1];if(s&&"Unknown"!=s)return t.SVG[e]=1,"svg"}return t.SVG[e]=0,0!==t.MathML[e]&&0===e.indexOf("m")?(t.MathML[e]=1,"mathml"):(t.MathML[e]=0,null)}if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){if(Prism.languages.css&&(Prism.languages.css.selector.pattern?(Prism.languages.css.selector.inside["pseudo-class"]=/:[\w-]+/,Prism.languages.css.selector.inside["pseudo-element"]=/::[\w-]+/):Prism.languages.css.selector={pattern:Prism.languages.css.selector,inside:{"pseudo-class":/:[\w-]+/,"pseudo-element":/::[\w-]+/}}),Prism.languages.markup){Prism.languages.markup.tag.inside.tag.inside["tag-id"]=/[\w-]+/;var t={HTML:{a:1,abbr:1,acronym:1,b:1,basefont:1,bdo:1,big:1,blink:1,cite:1,code:1,dfn:1,em:1,kbd:1,i:1,rp:1,rt:1,ruby:1,s:1,samp:1,small:1,spacer:1,strike:1,strong:1,sub:1,sup:1,time:1,tt:1,u:1,"var":1,wbr:1,noframes:1,summary:1,command:1,dt:1,dd:1,figure:1,figcaption:1,center:1,section:1,nav:1,article:1,aside:1,hgroup:1,header:1,footer:1,address:1,noscript:1,isIndex:1,main:1,mark:1,marquee:1,meter:1,menu:1},SVG:{animateColor:1,animateMotion:1,animateTransform:1,glyph:1,feBlend:1,feColorMatrix:1,feComponentTransfer:1,feFuncR:1,feFuncG:1,feFuncB:1,feFuncA:1,feComposite:1,feConvolveMatrix:1,feDiffuseLighting:1,feDisplacementMap:1,feFlood:1,feGaussianBlur:1,feImage:1,feMerge:1,feMergeNode:1,feMorphology:1,feOffset:1,feSpecularLighting:1,feTile:1,feTurbulence:1,feDistantLight:1,fePointLight:1,feSpotLight:1,linearGradient:1,radialGradient:1,altGlyph:1,textPath:1,tref:1,altglyph:1,textpath:1,altglyphdef:1,altglyphitem:1,clipPath:1,"color-profile":1,cursor:1,"font-face":1,"font-face-format":1,"font-face-name":1,"font-face-src":1,"font-face-uri":1,foreignObject:1,glyphRef:1,hkern:1,vkern:1},MathML:{}}}var n;Prism.hooks.add("wrap",function(t){if(("tag-id"==t.type||"property"==t.type&&0!=t.content.indexOf("-")||"rule"==t.type&&0!=t.content.indexOf("@-")||"pseudo-class"==t.type&&0!=t.content.indexOf(":-")||"pseudo-element"==t.type&&0!=t.content.indexOf("::-")||"attr-name"==t.type&&0!=t.content.indexOf("data-"))&&-1===t.content.indexOf("<")&&("css"==t.language||"scss"==t.language||"markup"==t.language)){var a="https://webplatform.github.io/docs/",s=t.content;if("css"==t.language||"scss"==t.language)a+="css/","property"==t.type?a+="properties/":"rule"==t.type?(a+="atrules/",s=s.substring(1)):"pseudo-class"==t.type?(a+="selectors/pseudo-classes/",s=s.substring(1)):"pseudo-element"==t.type&&(a+="selectors/pseudo-elements/",s=s.substring(2));else if("markup"==t.language)if("tag-id"==t.type){if(n=e(t.content)||n,!n)return;a+=n+"/elements/"}else if("attr-name"==t.type){if(!n)return;a+=n+"/attributes/"}a+=s,t.tag="a",t.attributes.href=a,t.attributes.target="_blank"}})}}();
\ No newline at end of file
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/prism.js b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/prism.js
new file mode 100644
index 0000000000..2baadce878
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/prism.js
@@ -0,0 +1,875 @@
+
+/* **********************************************
+     Begin prism-core.js
+********************************************** */
+
+var _self = (typeof window !== 'undefined')
+	? window   // if in browser
+	: (
+		(typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
+		? self // if in worker
+		: {}   // if in node js
+	);
+
+/**
+ * Prism: Lightweight, robust, elegant syntax highlighting
+ * MIT license http://www.opensource.org/licenses/mit-license.php/
+ * @author Lea Verou http://lea.verou.me
+ */
+
+var Prism = (function(){
+
+// Private helper vars
+var lang = /\blang(?:uage)?-([\w-]+)\b/i;
+var uniqueId = 0;
+
+var _ = _self.Prism = {
+	manual: _self.Prism && _self.Prism.manual,
+	disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
+	util: {
+		encode: function (tokens) {
+			if (tokens instanceof Token) {
+				return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
+			} else if (_.util.type(tokens) === 'Array') {
+				return tokens.map(_.util.encode);
+			} else {
+				return tokens.replace(/&/g, '&').replace(/ text.length) {
+						// Something went terribly wrong, ABORT, ABORT!
+						return;
+					}
+
+					if (str instanceof Token) {
+						continue;
+					}
+
+					if (greedy && i != strarr.length - 1) {
+						pattern.lastIndex = pos;
+						var match = pattern.exec(text);
+						if (!match) {
+							break;
+						}
+
+						var from = match.index + (lookbehind ? match[1].length : 0),
+						    to = match.index + match[0].length,
+						    k = i,
+						    p = pos;
+
+						for (var len = strarr.length; k < len && (p < to || (!strarr[k].type && !strarr[k - 1].greedy)); ++k) {
+							p += strarr[k].length;
+							// Move the index i to the element in strarr that is closest to from
+							if (from >= p) {
+								++i;
+								pos = p;
+							}
+						}
+
+						// If strarr[i] is a Token, then the match starts inside another Token, which is invalid
+						if (strarr[i] instanceof Token) {
+							continue;
+						}
+
+						// Number of tokens to delete and replace with the new match
+						delNum = k - i;
+						str = text.slice(pos, p);
+						match.index -= pos;
+					} else {
+						pattern.lastIndex = 0;
+
+						var match = pattern.exec(str),
+							delNum = 1;
+					}
+
+					if (!match) {
+						if (oneshot) {
+							break;
+						}
+
+						continue;
+					}
+
+					if(lookbehind) {
+						lookbehindLength = match[1] ? match[1].length : 0;
+					}
+
+					var from = match.index + lookbehindLength,
+					    match = match[0].slice(lookbehindLength),
+					    to = from + match.length,
+					    before = str.slice(0, from),
+					    after = str.slice(to);
+
+					var args = [i, delNum];
+
+					if (before) {
+						++i;
+						pos += before.length;
+						args.push(before);
+					}
+
+					var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias, match, greedy);
+
+					args.push(wrapped);
+
+					if (after) {
+						args.push(after);
+					}
+
+					Array.prototype.splice.apply(strarr, args);
+
+					if (delNum != 1)
+						_.matchGrammar(text, strarr, grammar, i, pos, true, token);
+
+					if (oneshot)
+						break;
+				}
+			}
+		}
+	},
+
+	tokenize: function(text, grammar, language) {
+		var strarr = [text];
+
+		var rest = grammar.rest;
+
+		if (rest) {
+			for (var token in rest) {
+				grammar[token] = rest[token];
+			}
+
+			delete grammar.rest;
+		}
+
+		_.matchGrammar(text, strarr, grammar, 0, 0, false);
+
+		return strarr;
+	},
+
+	hooks: {
+		all: {},
+
+		add: function (name, callback) {
+			var hooks = _.hooks.all;
+
+			hooks[name] = hooks[name] || [];
+
+			hooks[name].push(callback);
+		},
+
+		run: function (name, env) {
+			var callbacks = _.hooks.all[name];
+
+			if (!callbacks || !callbacks.length) {
+				return;
+			}
+
+			for (var i=0, callback; callback = callbacks[i++];) {
+				callback(env);
+			}
+		}
+	}
+};
+
+var Token = _.Token = function(type, content, alias, matchedStr, greedy) {
+	this.type = type;
+	this.content = content;
+	this.alias = alias;
+	// Copy of the full string this token was created from
+	this.length = (matchedStr || "").length|0;
+	this.greedy = !!greedy;
+};
+
+Token.stringify = function(o, language, parent) {
+	if (typeof o == 'string') {
+		return o;
+	}
+
+	if (_.util.type(o) === 'Array') {
+		return o.map(function(element) {
+			return Token.stringify(element, language, o);
+		}).join('');
+	}
+
+	var env = {
+		type: o.type,
+		content: Token.stringify(o.content, language, parent),
+		tag: 'span',
+		classes: ['token', o.type],
+		attributes: {},
+		language: language,
+		parent: parent
+	};
+
+	if (o.alias) {
+		var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias];
+		Array.prototype.push.apply(env.classes, aliases);
+	}
+
+	_.hooks.run('wrap', env);
+
+	var attributes = Object.keys(env.attributes).map(function(name) {
+		return name + '="' + (env.attributes[name] || '').replace(/"/g, '"') + '"';
+	}).join(' ');
+
+	return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '';
+
+};
+
+if (!_self.document) {
+	if (!_self.addEventListener) {
+		// in Node.js
+		return _self.Prism;
+	}
+
+	if (!_.disableWorkerMessageHandler) {
+		// In worker
+		_self.addEventListener('message', function (evt) {
+			var message = JSON.parse(evt.data),
+				lang = message.language,
+				code = message.code,
+				immediateClose = message.immediateClose;
+
+			_self.postMessage(_.highlight(code, _.languages[lang], lang));
+			if (immediateClose) {
+				_self.close();
+			}
+		}, false);
+	}
+
+	return _self.Prism;
+}
+
+//Get current script and highlight
+var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop();
+
+if (script) {
+	_.filename = script.src;
+
+	if (!_.manual && !script.hasAttribute('data-manual')) {
+		if(document.readyState !== "loading") {
+			if (window.requestAnimationFrame) {
+				window.requestAnimationFrame(_.highlightAll);
+			} else {
+				window.setTimeout(_.highlightAll, 16);
+			}
+		}
+		else {
+			document.addEventListener('DOMContentLoaded', _.highlightAll);
+		}
+	}
+}
+
+return _self.Prism;
+
+})();
+
+if (typeof module !== 'undefined' && module.exports) {
+	module.exports = Prism;
+}
+
+// hack for components to work correctly in node.js
+if (typeof global !== 'undefined') {
+	global.Prism = Prism;
+}
+
+
+/* **********************************************
+     Begin prism-markup.js
+********************************************** */
+
+Prism.languages.markup = {
+	'comment': //,
+	'prolog': /<\?[\s\S]+?\?>/,
+	'doctype': //i,
+	'cdata': //i,
+	'tag': {
+		pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,
+		greedy: true,
+		inside: {
+			'tag': {
+				pattern: /^<\/?[^\s>\/]+/i,
+				inside: {
+					'punctuation': /^<\/?/,
+					'namespace': /^[^\s>\/:]+:/
+				}
+			},
+			'attr-value': {
+				pattern: /=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,
+				inside: {
+					'punctuation': [
+						/^=/,
+						{
+							pattern: /(^|[^\\])["']/,
+							lookbehind: true
+						}
+					]
+				}
+			},
+			'punctuation': /\/?>/,
+			'attr-name': {
+				pattern: /[^\s>\/]+/,
+				inside: {
+					'namespace': /^[^\s>\/:]+:/
+				}
+			}
+
+		}
+	},
+	'entity': /&#?[\da-z]{1,8};/i
+};
+
+Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] =
+	Prism.languages.markup['entity'];
+
+// Plugin to make entity title show the real entity, idea by Roman Komarov
+Prism.hooks.add('wrap', function(env) {
+
+	if (env.type === 'entity') {
+		env.attributes['title'] = env.content.replace(/&/, '&');
+	}
+});
+
+Prism.languages.xml = Prism.languages.markup;
+Prism.languages.html = Prism.languages.markup;
+Prism.languages.mathml = Prism.languages.markup;
+Prism.languages.svg = Prism.languages.markup;
+
+
+/* **********************************************
+     Begin prism-css.js
+********************************************** */
+
+Prism.languages.css = {
+	'comment': /\/\*[\s\S]*?\*\//,
+	'atrule': {
+		pattern: /@[\w-]+?.*?(?:;|(?=\s*\{))/i,
+		inside: {
+			'rule': /@[\w-]+/
+			// See rest below
+		}
+	},
+	'url': /url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
+	'selector': /[^{}\s][^{};]*?(?=\s*\{)/,
+	'string': {
+		pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
+		greedy: true
+	},
+	'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,
+	'important': /\B!important\b/i,
+	'function': /[-a-z0-9]+(?=\()/i,
+	'punctuation': /[(){};:]/
+};
+
+Prism.languages.css['atrule'].inside.rest = Prism.languages.css;
+
+if (Prism.languages.markup) {
+	Prism.languages.insertBefore('markup', 'tag', {
+		'style': {
+			pattern: /()[\s\S]*?(?=<\/style>)/i,
+			lookbehind: true,
+			inside: Prism.languages.css,
+			alias: 'language-css',
+			greedy: true
+		}
+	});
+
+	Prism.languages.insertBefore('inside', 'attr-value', {
+		'style-attr': {
+			pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
+			inside: {
+				'attr-name': {
+					pattern: /^\s*style/i,
+					inside: Prism.languages.markup.tag.inside
+				},
+				'punctuation': /^\s*=\s*['"]|['"]\s*$/,
+				'attr-value': {
+					pattern: /.+/i,
+					inside: Prism.languages.css
+				}
+			},
+			alias: 'language-css'
+		}
+	}, Prism.languages.markup.tag);
+}
+
+/* **********************************************
+     Begin prism-clike.js
+********************************************** */
+
+Prism.languages.clike = {
+	'comment': [
+		{
+			pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
+			lookbehind: true
+		},
+		{
+			pattern: /(^|[^\\:])\/\/.*/,
+			lookbehind: true,
+			greedy: true
+		}
+	],
+	'string': {
+		pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
+		greedy: true
+	},
+	'class-name': {
+		pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,
+		lookbehind: true,
+		inside: {
+			punctuation: /[.\\]/
+		}
+	},
+	'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
+	'boolean': /\b(?:true|false)\b/,
+	'function': /[a-z0-9_]+(?=\()/i,
+	'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
+	'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,
+	'punctuation': /[{}[\];(),.:]/
+};
+
+
+/* **********************************************
+     Begin prism-javascript.js
+********************************************** */
+
+Prism.languages.javascript = Prism.languages.extend('clike', {
+	'keyword': /\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,
+	'number': /\b(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,
+	// Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
+	'function': /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\()/i,
+	'operator': /-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/
+});
+
+Prism.languages.insertBefore('javascript', 'keyword', {
+	'regex': {
+		pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[[^\]\r\n]+]|\\.|[^/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,
+		lookbehind: true,
+		greedy: true
+	},
+	// This must be declared before keyword because we use "function" inside the look-forward
+	'function-variable': {
+		pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,
+		alias: 'function'
+	},
+	'constant': /\b[A-Z][A-Z\d_]*\b/
+});
+
+Prism.languages.insertBefore('javascript', 'string', {
+	'template-string': {
+		pattern: /`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,
+		greedy: true,
+		inside: {
+			'interpolation': {
+				pattern: /\${[^}]+}/,
+				inside: {
+					'interpolation-punctuation': {
+						pattern: /^\${|}$/,
+						alias: 'punctuation'
+					},
+					rest: null // See below
+				}
+			},
+			'string': /[\s\S]+/
+		}
+	}
+});
+Prism.languages.javascript['template-string'].inside['interpolation'].inside.rest = Prism.languages.javascript;
+
+if (Prism.languages.markup) {
+	Prism.languages.insertBefore('markup', 'tag', {
+		'script': {
+			pattern: /()[\s\S]*?(?=<\/script>)/i,
+			lookbehind: true,
+			inside: Prism.languages.javascript,
+			alias: 'language-javascript',
+			greedy: true
+		}
+	});
+}
+
+Prism.languages.js = Prism.languages.javascript;
+
+
+/* **********************************************
+     Begin prism-file-highlight.js
+********************************************** */
+
+(function () {
+	if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) {
+		return;
+	}
+
+	self.Prism.fileHighlight = function() {
+
+		var Extensions = {
+			'js': 'javascript',
+			'py': 'python',
+			'rb': 'ruby',
+			'ps1': 'powershell',
+			'psm1': 'powershell',
+			'sh': 'bash',
+			'bat': 'batch',
+			'h': 'c',
+			'tex': 'latex'
+		};
+
+		Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function (pre) {
+			var src = pre.getAttribute('data-src');
+
+			var language, parent = pre;
+			var lang = /\blang(?:uage)?-([\w-]+)\b/i;
+			while (parent && !lang.test(parent.className)) {
+				parent = parent.parentNode;
+			}
+
+			if (parent) {
+				language = (pre.className.match(lang) || [, ''])[1];
+			}
+
+			if (!language) {
+				var extension = (src.match(/\.(\w+)$/) || [, ''])[1];
+				language = Extensions[extension] || extension;
+			}
+
+			var code = document.createElement('code');
+			code.className = 'language-' + language;
+
+			pre.textContent = '';
+
+			code.textContent = 'Loading…';
+
+			pre.appendChild(code);
+
+			var xhr = new XMLHttpRequest();
+
+			xhr.open('GET', src, true);
+
+			xhr.onreadystatechange = function () {
+				if (xhr.readyState == 4) {
+
+					if (xhr.status < 400 && xhr.responseText) {
+						code.textContent = xhr.responseText;
+
+						Prism.highlightElement(code);
+					}
+					else if (xhr.status >= 400) {
+						code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
+					}
+					else {
+						code.textContent = '✖ Error: File does not exist or is empty';
+					}
+				}
+			};
+
+			xhr.send(null);
+		});
+
+		if (Prism.plugins.toolbar) {
+			Prism.plugins.toolbar.registerButton('download-file', function (env) {
+				var pre = env.element.parentNode;
+				if (!pre || !/pre/i.test(pre.nodeName) || !pre.hasAttribute('data-src') || !pre.hasAttribute('data-download-link')) {
+					return;
+				}
+				var src = pre.getAttribute('data-src');
+				var a = document.createElement('a');
+				a.textContent = pre.getAttribute('data-download-link-label') || 'Download';
+				a.setAttribute('download', '');
+				a.href = src;
+				return a;
+			});
+		}
+
+	};
+
+	document.addEventListener('DOMContentLoaded', self.Prism.fileHighlight);
+
+})();
\ No newline at end of file
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-coy.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-coy.css
new file mode 100644
index 0000000000..1127bbe37d
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-coy.css
@@ -0,0 +1,225 @@
+/**
+ * prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML
+ * Based on https://github.com/tshedor/workshop-wp-theme (Example: http://workshop.kansan.com/category/sessions/basics or http://workshop.timshedor.com/category/sessions/basics);
+ * @author Tim  Shedor
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	color: black;
+	background: none;
+	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	word-break: normal;
+	word-wrap: normal;
+	line-height: 1.5;
+
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	position: relative;
+	margin: .5em 0;
+	overflow: visible;
+	padding: 0;
+}
+pre[class*="language-"]>code {
+	position: relative;
+	border-left: 10px solid #358ccb;
+	box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf;
+	background-color: #fdfdfd;
+	background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);
+	background-size: 3em 3em;
+	background-origin: content-box;
+	background-attachment: local;
+}
+
+code[class*="language"] {
+	max-height: inherit;
+	height: inherit;
+	padding: 0 1em;
+	display: block;
+	overflow: auto;
+}
+
+/* Margin bottom to accomodate shadow */
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+	background-color: #fdfdfd;
+	-webkit-box-sizing: border-box;
+	-moz-box-sizing: border-box;
+	box-sizing: border-box;
+	margin-bottom: 1em;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	position: relative;
+	padding: .2em;
+	border-radius: 0.3em;
+	color: #c92c2c;
+	border: 1px solid rgba(0, 0, 0, 0.1);
+	display: inline;
+	white-space: normal;
+}
+
+pre[class*="language-"]:before,
+pre[class*="language-"]:after {
+	content: '';
+	z-index: -2;
+	display: block;
+	position: absolute;
+	bottom: 0.75em;
+	left: 0.18em;
+	width: 40%;
+	height: 20%;
+	max-height: 13em;
+	box-shadow: 0px 13px 8px #979797;
+	-webkit-transform: rotate(-2deg);
+	-moz-transform: rotate(-2deg);
+	-ms-transform: rotate(-2deg);
+	-o-transform: rotate(-2deg);
+	transform: rotate(-2deg);
+}
+
+:not(pre) > code[class*="language-"]:after,
+pre[class*="language-"]:after {
+	right: 0.75em;
+	left: auto;
+	-webkit-transform: rotate(2deg);
+	-moz-transform: rotate(2deg);
+	-ms-transform: rotate(2deg);
+	-o-transform: rotate(2deg);
+	transform: rotate(2deg);
+}
+
+.token.comment,
+.token.block-comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: #7D8B99;
+}
+
+.token.punctuation {
+	color: #5F6364;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.function-name,
+.token.constant,
+.token.symbol,
+.token.deleted {
+	color: #c92c2c;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.function,
+.token.builtin,
+.token.inserted {
+	color: #2f9c0a;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.token.variable {
+	color: #a67f59;
+	background: rgba(255, 255, 255, 0.5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword,
+.token.class-name {
+	color: #1990b8;
+}
+
+.token.regex,
+.token.important {
+	color: #e90;
+}
+
+.language-css .token.string,
+.style .token.string {
+	color: #a67f59;
+	background: rgba(255, 255, 255, 0.5);
+}
+
+.token.important {
+	font-weight: normal;
+}
+
+.token.bold {
+	font-weight: bold;
+}
+.token.italic {
+	font-style: italic;
+}
+
+.token.entity {
+	cursor: help;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+@media screen and (max-width: 767px) {
+	pre[class*="language-"]:before,
+	pre[class*="language-"]:after {
+		bottom: 14px;
+		box-shadow: none;
+	}
+
+}
+
+/* Plugin styles */
+.token.tab:not(:empty):before,
+.token.cr:before,
+.token.lf:before {
+	color: #e0d7d1;
+}
+
+/* Plugin styles: Line Numbers */
+pre[class*="language-"].line-numbers.line-numbers {
+	padding-left: 0;
+}
+
+pre[class*="language-"].line-numbers.line-numbers code {
+	padding-left: 3.8em;
+}
+
+pre[class*="language-"].line-numbers.line-numbers .line-numbers-rows {
+	left: 0;
+}
+
+/* Plugin styles: Line Highlight */
+pre[class*="language-"][data-line] {
+	padding-top: 0;
+	padding-bottom: 0;
+	padding-left: 0;
+}
+pre[data-line] code {
+	position: relative;
+	padding-left: 4em;
+}
+pre .line-highlight {
+	margin-top: 0;
+}
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-dark.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-dark.css
new file mode 100644
index 0000000000..7f4572877b
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-dark.css
@@ -0,0 +1,128 @@
+/**
+ * prism.js Dark theme for JavaScript, CSS and HTML
+ * Based on the slides of the talk “/Reg(exp){2}lained/”
+ * @author Lea Verou
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	color: white;
+	background: none;
+	text-shadow: 0 -.1em .2em black;
+	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	word-break: normal;
+	word-wrap: normal;
+	line-height: 1.5;
+
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+@media print {
+	code[class*="language-"],
+	pre[class*="language-"] {
+		text-shadow: none;
+	}
+}
+
+pre[class*="language-"],
+:not(pre) > code[class*="language-"] {
+	background: hsl(30, 20%, 25%);
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: 1em;
+	margin: .5em 0;
+	overflow: auto;
+	border: .3em solid hsl(30, 20%, 40%);
+	border-radius: .5em;
+	box-shadow: 1px 1px .5em black inset;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .15em .2em .05em;
+	border-radius: .3em;
+	border: .13em solid hsl(30, 20%, 40%);
+	box-shadow: 1px 1px .3em -.1em black inset;
+	white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: hsl(30, 20%, 50%);
+}
+
+.token.punctuation {
+	opacity: .7;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol {
+	color: hsl(350, 40%, 70%);
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+	color: hsl(75, 70%, 60%);
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string,
+.token.variable {
+	color: hsl(40, 90%, 60%);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+	color: hsl(350, 40%, 70%);
+}
+
+.token.regex,
+.token.important {
+	color: #e90;
+}
+
+.token.important,
+.token.bold {
+	font-weight: bold;
+}
+.token.italic {
+	font-style: italic;
+}
+
+.token.entity {
+	cursor: help;
+}
+
+.token.deleted {
+	color: red;
+}
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-funky.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-funky.css
new file mode 100644
index 0000000000..dd3be06188
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-funky.css
@@ -0,0 +1,116 @@
+/**
+ * prism.js Funky theme
+ * Based on “Polyfilling the gaps” talk slides http://lea.verou.me/polyfilling-the-gaps/
+ * @author Lea Verou
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	word-break: normal;
+	word-wrap: normal;
+	line-height: 1.5;
+
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: .4em .8em;
+	margin: .5em 0;
+	overflow: auto;
+	background: url('data:image/svg+xml;charset=utf-8,%0D%0A%0D%0A%0D%0A<%2Fsvg>');
+	background-size: 1em 1em;
+}
+
+code[class*="language-"] {
+	background: black;
+	color: white;
+	box-shadow: -.3em 0 0 .3em black, .3em 0 0 .3em black;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .2em;
+	border-radius: .3em;
+	box-shadow: none;
+	white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: #aaa;
+}
+
+.token.punctuation {
+	color: #999;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol {
+	color: #0cf;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin {
+	color: yellow;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.toke.variable,
+.token.inserted {
+	color: yellowgreen;
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+	color: deeppink;
+}
+
+.token.regex,
+.token.important {
+	color: orange;
+}
+
+.token.important,
+.token.bold {
+	font-weight: bold;
+}
+.token.italic {
+	font-style: italic;
+}
+
+.token.entity {
+	cursor: help;
+}
+
+.token.deleted {
+	color: red;
+}
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-okaidia.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-okaidia.css
new file mode 100644
index 0000000000..8efbc074b5
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-okaidia.css
@@ -0,0 +1,122 @@
+/**
+ * okaidia theme for JavaScript, CSS and HTML
+ * Loosely based on Monokai textmate theme by http://www.monokai.nl/
+ * @author ocodia
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	color: #f8f8f2;
+	background: none;
+	text-shadow: 0 1px rgba(0, 0, 0, 0.3);
+	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	word-break: normal;
+	word-wrap: normal;
+	line-height: 1.5;
+
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: 1em;
+	margin: .5em 0;
+	overflow: auto;
+	border-radius: 0.3em;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+	background: #272822;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .1em;
+	border-radius: .3em;
+	white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: slategray;
+}
+
+.token.punctuation {
+	color: #f8f8f2;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.constant,
+.token.symbol,
+.token.deleted {
+	color: #f92672;
+}
+
+.token.boolean,
+.token.number {
+	color: #ae81ff;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+	color: #a6e22e;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string,
+.token.variable {
+	color: #f8f8f2;
+}
+
+.token.atrule,
+.token.attr-value,
+.token.function,
+.token.class-name {
+	color: #e6db74;
+}
+
+.token.keyword {
+	color: #66d9ef;
+}
+
+.token.regex,
+.token.important {
+	color: #fd971f;
+}
+
+.token.important,
+.token.bold {
+	font-weight: bold;
+}
+.token.italic {
+	font-style: italic;
+}
+
+.token.entity {
+	cursor: help;
+}
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-solarizedlight.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-solarizedlight.css
new file mode 100644
index 0000000000..07657dac4f
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-solarizedlight.css
@@ -0,0 +1,149 @@
+/*
+ Solarized Color Schemes originally by Ethan Schoonover
+ http://ethanschoonover.com/solarized
+
+ Ported for PrismJS by Hector Matos
+ Website: https://krakendev.io
+ Twitter Handle: https://twitter.com/allonsykraken)
+*/
+
+/*
+SOLARIZED HEX
+--------- -------
+base03    #002b36
+base02    #073642
+base01    #586e75
+base00    #657b83
+base0     #839496
+base1     #93a1a1
+base2     #eee8d5
+base3     #fdf6e3
+yellow    #b58900
+orange    #cb4b16
+red       #dc322f
+magenta   #d33682
+violet    #6c71c4
+blue      #268bd2
+cyan      #2aa198
+green     #859900
+*/
+
+code[class*="language-"],
+pre[class*="language-"] {
+	color: #657b83; /* base00 */
+	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	word-break: normal;
+	word-wrap: normal;
+
+	line-height: 1.5;
+
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
+code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
+	background: #073642; /* base02 */
+}
+
+pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
+code[class*="language-"]::selection, code[class*="language-"] ::selection {
+	background: #073642; /* base02 */
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: 1em;
+	margin: .5em 0;
+	overflow: auto;
+	border-radius: 0.3em;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+	background-color: #fdf6e3; /* base3 */
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .1em;
+	border-radius: .3em;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: #93a1a1; /* base1 */
+}
+
+.token.punctuation {
+	color: #586e75; /* base01 */
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol,
+.token.deleted {
+	color: #268bd2; /* blue */
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.url,
+.token.inserted {
+	color: #2aa198; /* cyan */
+}
+
+.token.entity {
+	color: #657b83; /* base00 */
+	background: #eee8d5; /* base2 */
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+	color: #859900; /* green */
+}
+
+.token.function,
+.token.class-name {
+	color: #b58900; /* yellow */
+}
+
+.token.regex,
+.token.important,
+.token.variable {
+	color: #cb4b16; /* orange */
+}
+
+.token.important,
+.token.bold {
+	font-weight: bold;
+}
+.token.italic {
+	font-style: italic;
+}
+
+.token.entity {
+	cursor: help;
+}
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-tomorrow.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-tomorrow.css
new file mode 100644
index 0000000000..6add2d2620
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-tomorrow.css
@@ -0,0 +1,121 @@
+/**
+ * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
+ * Based on https://github.com/chriskempson/tomorrow-theme
+ * @author Rose Pritchard
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	color: #ccc;
+	background: none;
+	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	word-break: normal;
+	word-wrap: normal;
+	line-height: 1.5;
+
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: 1em;
+	margin: .5em 0;
+	overflow: auto;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+	background: #2d2d2d;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .1em;
+	border-radius: .3em;
+	white-space: normal;
+}
+
+.token.comment,
+.token.block-comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: #999;
+}
+
+.token.punctuation {
+	color: #ccc;
+}
+
+.token.tag,
+.token.attr-name,
+.token.namespace,
+.token.deleted {
+	color: #e2777a;
+}
+
+.token.function-name {
+	color: #6196cc;
+}
+
+.token.boolean,
+.token.number,
+.token.function {
+	color: #f08d49;
+}
+
+.token.property,
+.token.class-name,
+.token.constant,
+.token.symbol {
+	color: #f8c555;
+}
+
+.token.selector,
+.token.important,
+.token.atrule,
+.token.keyword,
+.token.builtin {
+	color: #cc99cd;
+}
+
+.token.string,
+.token.char,
+.token.attr-value,
+.token.regex,
+.token.variable {
+	color: #7ec699;
+}
+
+.token.operator,
+.token.entity,
+.token.url {
+	color: #67cdcc;
+}
+
+.token.important,
+.token.bold {
+	font-weight: bold;
+}
+.token.italic {
+	font-style: italic;
+}
+
+.token.entity {
+	cursor: help;
+}
+
+.token.inserted {
+	color: green;
+}
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-twilight.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-twilight.css
new file mode 100644
index 0000000000..504ca7049c
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism-twilight.css
@@ -0,0 +1,198 @@
+/**
+ * prism.js Twilight theme
+ * Based (more or less) on the Twilight theme originally of Textmate fame.
+ * @author Remy Bach
+ */
+code[class*="language-"],
+pre[class*="language-"] {
+	color: white;
+	background: none;
+	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+	text-align: left;
+	text-shadow: 0 -.1em .2em black;
+	white-space: pre;
+	word-spacing: normal;
+	word-break: normal;
+	word-wrap: normal;
+	line-height: 1.5;
+
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+pre[class*="language-"],
+:not(pre) > code[class*="language-"] {
+	background: hsl(0, 0%, 8%); /* #141414 */
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	border-radius: .5em;
+	border: .3em solid hsl(0, 0%, 33%); /* #282A2B */
+	box-shadow: 1px 1px .5em black inset;
+	margin: .5em 0;
+	overflow: auto;
+	padding: 1em;
+}
+
+pre[class*="language-"]::-moz-selection {
+	/* Firefox */
+	background: hsl(200, 4%, 16%); /* #282A2B */
+}
+
+pre[class*="language-"]::selection {
+	/* Safari */
+	background: hsl(200, 4%, 16%); /* #282A2B */
+}
+
+/* Text Selection colour */
+pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
+code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
+	text-shadow: none;
+	background: hsla(0, 0%, 93%, 0.15); /* #EDEDED */
+}
+
+pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
+code[class*="language-"]::selection, code[class*="language-"] ::selection {
+	text-shadow: none;
+	background: hsla(0, 0%, 93%, 0.15); /* #EDEDED */
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	border-radius: .3em;
+	border: .13em solid hsl(0, 0%, 33%); /* #545454 */
+	box-shadow: 1px 1px .3em -.1em black inset;
+	padding: .15em .2em .05em;
+	white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: hsl(0, 0%, 47%); /* #777777 */
+}
+
+.token.punctuation {
+	opacity: .7;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.tag,
+.token.boolean,
+.token.number,
+.token.deleted {
+	color: hsl(14, 58%, 55%); /* #CF6A4C */
+}
+
+.token.keyword,
+.token.property,
+.token.selector,
+.token.constant,
+.token.symbol,
+.token.builtin {
+	color: hsl(53, 89%, 79%); /* #F9EE98 */
+}
+
+.token.attr-name,
+.token.attr-value,
+.token.string,
+.token.char,
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string,
+.token.variable,
+.token.inserted {
+	color: hsl(76, 21%, 52%); /* #8F9D6A */
+}
+
+.token.atrule {
+	color: hsl(218, 22%, 55%); /* #7587A6 */
+}
+
+.token.regex,
+.token.important {
+	color: hsl(42, 75%, 65%); /* #E9C062 */
+}
+
+.token.important,
+.token.bold {
+	font-weight: bold;
+}
+.token.italic {
+	font-style: italic;
+}
+
+.token.entity {
+	cursor: help;
+}
+
+pre[data-line] {
+	padding: 1em 0 1em 3em;
+	position: relative;
+}
+
+/* Markup */
+.language-markup .token.tag,
+.language-markup .token.attr-name,
+.language-markup .token.punctuation {
+	color: hsl(33, 33%, 52%); /* #AC885B */
+}
+
+/* Make the tokens sit above the line highlight so the colours don't look faded. */
+.token {
+	position: relative;
+	z-index: 1;
+}
+
+.line-highlight {
+	background: hsla(0, 0%, 33%, 0.25); /* #545454 */
+	background: linear-gradient(to right, hsla(0, 0%, 33%, .1) 70%, hsla(0, 0%, 33%, 0)); /* #545454 */
+	border-bottom: 1px dashed hsl(0, 0%, 33%); /* #545454 */
+	border-top: 1px dashed hsl(0, 0%, 33%); /* #545454 */
+	left: 0;
+	line-height: inherit;
+	margin-top: 0.75em; /* Same as .prism’s padding-top */
+	padding: inherit 0;
+	pointer-events: none;
+	position: absolute;
+	right: 0;
+	white-space: pre;
+	z-index: 0;
+}
+
+.line-highlight:before,
+.line-highlight[data-end]:after {
+	background-color: hsl(215, 15%, 59%); /* #8794A6 */
+	border-radius: 999px;
+	box-shadow: 0 1px white;
+	color: hsl(24, 20%, 95%); /* #F5F2F0 */
+	content: attr(data-start);
+	font: bold 65%/1.5 sans-serif;
+	left: .6em;
+	min-width: 1em;
+	padding: 0 .5em;
+	position: absolute;
+	text-align: center;
+	text-shadow: none;
+	top: .4em;
+	vertical-align: .3em;
+}
+
+.line-highlight[data-end]:after {
+	bottom: .4em;
+	content: attr(data-end);
+	top: auto;
+}
diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism.css
new file mode 100644
index 0000000000..9010cb637e
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/libs/prismjs/themes/prism.css
@@ -0,0 +1,138 @@
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	color: black;
+	background: none;
+	text-shadow: 0 1px white;
+	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	word-break: normal;
+	word-wrap: normal;
+	line-height: 1.5;
+
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
+code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
+	text-shadow: none;
+	background: #b3d4fc;
+}
+
+pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
+code[class*="language-"]::selection, code[class*="language-"] ::selection {
+	text-shadow: none;
+	background: #b3d4fc;
+}
+
+@media print {
+	code[class*="language-"],
+	pre[class*="language-"] {
+		text-shadow: none;
+	}
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: 1em;
+	margin: .5em 0;
+	overflow: auto;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+	background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .1em;
+	border-radius: .3em;
+	white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: slategray;
+}
+
+.token.punctuation {
+	color: #999;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol,
+.token.deleted {
+	color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+	color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+	color: #9a6e3a;
+	background: hsla(0, 0%, 100%, .5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+	color: #07a;
+}
+
+.token.function,
+.token.class-name {
+	color: #DD4A68;
+}
+
+.token.regex,
+.token.important,
+.token.variable {
+	color: #e90;
+}
+
+.token.important,
+.token.bold {
+	font-weight: bold;
+}
+.token.italic {
+	font-style: italic;
+}
+
+.token.entity {
+	cursor: help;
+}
diff --git a/abp_io/src/Volo.AbpWebSite.Web/yarn.lock b/abp_io/src/Volo.AbpWebSite.Web/yarn.lock
index fb7d8adf59..afb9143b99 100644
--- a/abp_io/src/Volo.AbpWebSite.Web/yarn.lock
+++ b/abp_io/src/Volo.AbpWebSite.Web/yarn.lock
@@ -2,6 +2,13 @@
 # yarn lockfile v1
 
 
+"@abp/anchor-js@^0.5.1":
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/@abp/anchor-js/-/anchor-js-0.5.1.tgz#5693bb317f08f9a05bb579f63d6ee011033d3632"
+  dependencies:
+    "@abp/core" "^0.4.9"
+    anchor-js "^4.1.1"
+
 "@abp/aspnetcore.mvc.ui.theme.basic@^0.4.9":
   version "0.4.9"
   resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-0.4.9.tgz#926a25c641225598c8666b658c1df3fa7fbed7cf"
@@ -50,6 +57,13 @@
     "@abp/core" "^0.4.9"
     bootstrap "^4.1.1"
 
+"@abp/clipboard@^0.5.1":
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-0.5.1.tgz#bd799e3ed5eb316b718125fbd1010967cf0b5ec5"
+  dependencies:
+    "@abp/core" "^0.4.9"
+    clipboard "^2.0.4"
+
 "@abp/codemirror@^0.4.9":
   version "0.4.9"
   resolved "https://registry.yarnpkg.com/@abp/codemirror/-/codemirror-0.4.9.tgz#59b6ece19efa9c10cf8c8a1164d0939515e13c9b"
@@ -75,6 +89,16 @@
     "@abp/core" "^0.4.9"
     datatables.net "^1.10.16"
 
+"@abp/docs@^0.5.1":
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/@abp/docs/-/docs-0.5.1.tgz#401a34eb13ad9b773a3d70319c50bb40f6f39c25"
+  dependencies:
+    "@abp/anchor-js" "^0.5.1"
+    "@abp/clipboard" "^0.5.1"
+    "@abp/malihu-custom-scrollbar-plugin" "^0.5.1"
+    "@abp/popper.js" "^0.5.1"
+    "@abp/prismjs" "^0.5.1"
+
 "@abp/font-awesome@^0.4.9":
   version "0.4.9"
   resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-0.4.9.tgz#eb1691ff33be53832b5063aa2a382dc7d65a3f43"
@@ -123,6 +147,13 @@
     "@abp/core" "^0.4.9"
     lodash "^4.17.10"
 
+"@abp/malihu-custom-scrollbar-plugin@^0.5.1":
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-0.5.1.tgz#0b293c6164292aa9cb016b042735d2640ccc63fe"
+  dependencies:
+    "@abp/core" "^0.4.9"
+    malihu-custom-scrollbar-plugin "^3.1.5"
+
 "@abp/markdown-it@^0.4.9":
   version "0.4.9"
   resolved "https://registry.yarnpkg.com/@abp/markdown-it/-/markdown-it-0.4.9.tgz#9b3ee9bffe0416d4ee9c5ea983de04a350f2b938"
@@ -137,6 +168,20 @@
     "@abp/core" "^0.4.9"
     owl.carousel "^2.3.4"
 
+"@abp/popper.js@^0.5.1":
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/@abp/popper.js/-/popper.js-0.5.1.tgz#9bb1d1c88d467963b5acbdcfe01b7e2dbe773b0f"
+  dependencies:
+    "@abp/core" "^0.4.9"
+    popper.js "^1.14.6"
+
+"@abp/prismjs@^0.5.1":
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-0.5.1.tgz#0df2d40fe0c2a0992df03d6f8fc14682873b7f44"
+  dependencies:
+    "@abp/core" "^0.4.9"
+    prismjs "^1.15.0"
+
 "@abp/select2@^0.4.9":
   version "0.4.9"
   resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-0.4.9.tgz#6bbb4d8ffd67876787a400647659f5bb7a1d642d"
@@ -179,6 +224,10 @@ almond@~0.3.1:
   version "0.3.3"
   resolved "https://registry.yarnpkg.com/almond/-/almond-0.3.3.tgz#a0e7c95ac7624d6417b4494b1e68bff693168a20"
 
+anchor-js@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/anchor-js/-/anchor-js-4.1.1.tgz#943b7605e47b3c663e91e82879b682f2e186a5b1"
+
 ansi-colors@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9"
@@ -332,6 +381,14 @@ class-utils@^0.3.5:
     isobject "^3.0.0"
     static-extend "^0.1.1"
 
+clipboard@^2.0.0, clipboard@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d"
+  dependencies:
+    good-listener "^1.2.2"
+    select "^1.1.2"
+    tiny-emitter "^2.0.0"
+
 clone-stats@^0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1"
@@ -427,6 +484,10 @@ define-property@^2.0.2:
     is-descriptor "^1.0.2"
     isobject "^3.0.1"
 
+delegate@^3.1.2:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
+
 deprecated@^0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19"
@@ -680,6 +741,12 @@ glogg@^1.0.0:
   dependencies:
     sparkles "^1.0.0"
 
+good-listener@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
+  dependencies:
+    delegate "^3.1.2"
+
 graceful-fs@^3.0.0:
   version "3.0.11"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818"
@@ -954,7 +1021,7 @@ jquery-form@^4.2.2:
   dependencies:
     jquery ">=1.7.2"
 
-jquery-mousewheel@~3.1.13:
+jquery-mousewheel@>=3.0.6, jquery-mousewheel@~3.1.13:
   version "3.1.13"
   resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5"
 
@@ -1115,6 +1182,12 @@ make-iterator@^1.0.0:
   dependencies:
     kind-of "^6.0.2"
 
+malihu-custom-scrollbar-plugin@^3.1.5:
+  version "3.1.5"
+  resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef"
+  dependencies:
+    jquery-mousewheel ">=3.0.6"
+
 map-cache@^0.2.0, map-cache@^0.2.2:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
@@ -1360,6 +1433,10 @@ plantuml-encoder@^1.2.5:
     pako "1.0.3"
     utf8-bytes "0.0.1"
 
+popper.js@^1.14.6:
+  version "1.14.6"
+  resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.6.tgz#ab20dd4edf9288b8b3b6531c47c361107b60b4b0"
+
 posix-character-classes@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
@@ -1368,6 +1445,12 @@ pretty-hrtime@^1.0.0:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
 
+prismjs@^1.15.0:
+  version "1.15.0"
+  resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.15.0.tgz#8801d332e472091ba8def94976c8877ad60398d9"
+  optionalDependencies:
+    clipboard "^2.0.0"
+
 process-nextick-args@~2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
@@ -1489,6 +1572,10 @@ select2@^4.0.5:
     almond "~0.3.1"
     jquery-mousewheel "~3.1.13"
 
+select@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
+
 semver@^4.1.0:
   version "4.3.6"
   resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
@@ -1657,6 +1744,10 @@ timeago@^1.6.3:
   dependencies:
     jquery ">=1.2.3"
 
+tiny-emitter@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
+
 to-mark@^1.1.2:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/to-mark/-/to-mark-1.1.3.tgz#d421a170a2dd582025e5090256c7821c6703f346"

From 39fc9706ea98e4c5eecb4c8a3acdd4767c4c19b8 Mon Sep 17 00:00:00 2001
From: Halil ibrahim Kalkan 
Date: Mon, 10 Dec 2018 10:13:17 +0300
Subject: [PATCH 06/36] Add migration to abp.io for docs module changes

---
 ...0181210071243_Docs_Upgrade_0_9.Designer.cs | 767 ++++++++++++++++++
 .../20181210071243_Docs_Upgrade_0_9.cs        |  22 +
 .../AbpWebSiteDbContextModelSnapshot.cs       |   2 -
 3 files changed, 789 insertions(+), 2 deletions(-)
 create mode 100644 abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181210071243_Docs_Upgrade_0_9.Designer.cs
 create mode 100644 abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181210071243_Docs_Upgrade_0_9.cs

diff --git a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181210071243_Docs_Upgrade_0_9.Designer.cs b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181210071243_Docs_Upgrade_0_9.Designer.cs
new file mode 100644
index 0000000000..9ee369b29f
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181210071243_Docs_Upgrade_0_9.Designer.cs
@@ -0,0 +1,767 @@
+// 
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Volo.AbpWebSite.EntityFrameworkCore;
+
+namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
+{
+    [DbContext(typeof(AbpWebSiteDbContext))]
+    [Migration("20181210071243_Docs_Upgrade_0_9")]
+    partial class Docs_Upgrade_0_9
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "2.1.1-rtm-30846")
+                .HasAnnotation("Relational:MaxIdentifierLength", 128)
+                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Description")
+                        .HasMaxLength(256);
+
+                    b.Property("IsStatic");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("Regex")
+                        .HasMaxLength(512);
+
+                    b.Property("RegexDescription")
+                        .HasMaxLength(128);
+
+                    b.Property("Required");
+
+                    b.Property("ValueType");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("AbpClaimTypes");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("IsDefault")
+                        .HasColumnName("IsDefault");
+
+                    b.Property("IsPublic")
+                        .HasColumnName("IsPublic");
+
+                    b.Property("IsStatic")
+                        .HasColumnName("IsStatic");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("NormalizedName")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("TenantId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("NormalizedName");
+
+                    b.ToTable("AbpRoles");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ClaimType")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("ClaimValue")
+                        .HasMaxLength(1024);
+
+                    b.Property("RoleId");
+
+                    b.Property("TenantId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("RoleId");
+
+                    b.ToTable("AbpRoleClaims");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("AccessFailedCount")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("AccessFailedCount")
+                        .HasDefaultValue(0);
+
+                    b.Property("ConcurrencyStamp")
+                        .IsRequired()
+                        .HasColumnName("ConcurrencyStamp")
+                        .HasMaxLength(256);
+
+                    b.Property("CreationTime");
+
+                    b.Property("CreatorId");
+
+                    b.Property("DeleterId");
+
+                    b.Property("DeletionTime");
+
+                    b.Property("Email")
+                        .HasColumnName("Email")
+                        .HasMaxLength(256);
+
+                    b.Property("EmailConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("EmailConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted");
+
+                    b.Property("LastModificationTime");
+
+                    b.Property("LastModifierId");
+
+                    b.Property("LockoutEnabled")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("LockoutEnabled")
+                        .HasDefaultValue(false);
+
+                    b.Property("LockoutEnd");
+
+                    b.Property("Name")
+                        .HasColumnName("Name")
+                        .HasMaxLength(64);
+
+                    b.Property("NormalizedEmail")
+                        .HasColumnName("NormalizedEmail")
+                        .HasMaxLength(256);
+
+                    b.Property("NormalizedUserName")
+                        .IsRequired()
+                        .HasColumnName("NormalizedUserName")
+                        .HasMaxLength(256);
+
+                    b.Property("PasswordHash")
+                        .HasColumnName("PasswordHash")
+                        .HasMaxLength(256);
+
+                    b.Property("PhoneNumber")
+                        .HasColumnName("PhoneNumber")
+                        .HasMaxLength(16);
+
+                    b.Property("PhoneNumberConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("PhoneNumberConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("SecurityStamp")
+                        .IsRequired()
+                        .HasColumnName("SecurityStamp")
+                        .HasMaxLength(256);
+
+                    b.Property("Surname")
+                        .HasColumnName("Surname")
+                        .HasMaxLength(64);
+
+                    b.Property("TenantId")
+                        .HasColumnName("TenantId");
+
+                    b.Property("TwoFactorEnabled")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("TwoFactorEnabled")
+                        .HasDefaultValue(false);
+
+                    b.Property("UserName")
+                        .IsRequired()
+                        .HasColumnName("UserName")
+                        .HasMaxLength(256);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Email");
+
+                    b.HasIndex("NormalizedEmail");
+
+                    b.HasIndex("NormalizedUserName");
+
+                    b.HasIndex("UserName");
+
+                    b.ToTable("AbpUsers");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ClaimType")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("ClaimValue")
+                        .HasMaxLength(1024);
+
+                    b.Property("TenantId");
+
+                    b.Property("UserId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("AbpUserClaims");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
+                {
+                    b.Property("UserId");
+
+                    b.Property("LoginProvider")
+                        .HasMaxLength(64);
+
+                    b.Property("ProviderDisplayName")
+                        .HasMaxLength(128);
+
+                    b.Property("ProviderKey")
+                        .IsRequired()
+                        .HasMaxLength(196);
+
+                    b.Property("TenantId");
+
+                    b.HasKey("UserId", "LoginProvider");
+
+                    b.HasIndex("LoginProvider", "ProviderKey");
+
+                    b.ToTable("AbpUserLogins");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
+                {
+                    b.Property("UserId");
+
+                    b.Property("RoleId");
+
+                    b.Property("TenantId");
+
+                    b.HasKey("UserId", "RoleId");
+
+                    b.HasIndex("RoleId", "UserId");
+
+                    b.ToTable("AbpUserRoles");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
+                {
+                    b.Property("UserId");
+
+                    b.Property("LoginProvider")
+                        .HasMaxLength(64);
+
+                    b.Property("Name")
+                        .HasMaxLength(128);
+
+                    b.Property("TenantId");
+
+                    b.Property("Value");
+
+                    b.HasKey("UserId", "LoginProvider", "Name");
+
+                    b.ToTable("AbpUserTokens");
+                });
+
+            modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("ProviderKey")
+                        .IsRequired()
+                        .HasMaxLength(64);
+
+                    b.Property("ProviderName")
+                        .IsRequired()
+                        .HasMaxLength(64);
+
+                    b.Property("TenantId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name", "ProviderName", "ProviderKey");
+
+                    b.ToTable("AbpPermissionGrants");
+                });
+
+            modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("ProviderKey")
+                        .HasMaxLength(64);
+
+                    b.Property("ProviderName")
+                        .HasMaxLength(64);
+
+                    b.Property("Value")
+                        .IsRequired()
+                        .HasMaxLength(2048);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name", "ProviderName", "ProviderKey");
+
+                    b.ToTable("AbpSettings");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("Description")
+                        .HasColumnName("Description")
+                        .HasMaxLength(1024);
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasColumnName("Name")
+                        .HasMaxLength(256);
+
+                    b.Property("ShortName")
+                        .IsRequired()
+                        .HasColumnName("ShortName")
+                        .HasMaxLength(32);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BlgBlogs");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("PostId")
+                        .HasColumnName("PostId");
+
+                    b.Property("RepliedCommentId")
+                        .HasColumnName("RepliedCommentId");
+
+                    b.Property("Text")
+                        .IsRequired()
+                        .HasColumnName("Text")
+                        .HasMaxLength(1024);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("PostId");
+
+                    b.HasIndex("RepliedCommentId");
+
+                    b.ToTable("BlgComments");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("BlogId")
+                        .HasColumnName("BlogId");
+
+                    b.Property("Content")
+                        .HasColumnName("Content")
+                        .HasMaxLength(1048576);
+
+                    b.Property("CoverImage")
+                        .IsRequired()
+                        .HasColumnName("CoverImage");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("ReadCount");
+
+                    b.Property("Title")
+                        .IsRequired()
+                        .HasColumnName("Title")
+                        .HasMaxLength(512);
+
+                    b.Property("Url")
+                        .IsRequired()
+                        .HasColumnName("Url")
+                        .HasMaxLength(64);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("BlogId");
+
+                    b.ToTable("BlgPosts");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
+                {
+                    b.Property("PostId")
+                        .HasColumnName("PostId");
+
+                    b.Property("TagId")
+                        .HasColumnName("TagId");
+
+                    b.Property("CreationTime");
+
+                    b.Property("CreatorId");
+
+                    b.HasKey("PostId", "TagId");
+
+                    b.HasIndex("TagId");
+
+                    b.ToTable("BlgPostTags");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("BlogId");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("Description")
+                        .HasColumnName("Description")
+                        .HasMaxLength(512);
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasColumnName("Name")
+                        .HasMaxLength(64);
+
+                    b.Property("UsageCount")
+                        .HasColumnName("UsageCount");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BlgTags");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Users.BlogUser", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Email")
+                        .HasColumnName("Email")
+                        .HasMaxLength(256);
+
+                    b.Property("EmailConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("EmailConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("Name")
+                        .HasColumnName("Name")
+                        .HasMaxLength(64);
+
+                    b.Property("PhoneNumber")
+                        .HasColumnName("PhoneNumber")
+                        .HasMaxLength(16);
+
+                    b.Property("PhoneNumberConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("PhoneNumberConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("Surname")
+                        .HasColumnName("Surname")
+                        .HasMaxLength(64);
+
+                    b.Property("TenantId")
+                        .HasColumnName("TenantId");
+
+                    b.Property("UserName")
+                        .IsRequired()
+                        .HasColumnName("UserName")
+                        .HasMaxLength(256);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BlgUsers");
+                });
+
+            modelBuilder.Entity("Volo.Docs.Projects.Project", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("DefaultDocumentName")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("DocumentStoreType");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("Format");
+
+                    b.Property("LatestVersionBranchName")
+                        .HasMaxLength(128);
+
+                    b.Property("MainWebsiteUrl");
+
+                    b.Property("MinimumVersion");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("NavigationDocumentName")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("ShortName")
+                        .IsRequired()
+                        .HasMaxLength(32);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("DocsProjects");
+                });
+
+            modelBuilder.Entity("Volo.Utils.SolutionTemplating.DownloadInfo", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+                    b.Property("CreationDuration");
+
+                    b.Property("CreationTime");
+
+                    b.Property("CreatorId");
+
+                    b.Property("DatabaseProvider");
+
+                    b.Property("ProjectName")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("TemplateName")
+                        .IsRequired()
+                        .HasMaxLength(42);
+
+                    b.Property("Version")
+                        .IsRequired()
+                        .HasMaxLength(20);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Downloads");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityRole")
+                        .WithMany("Claims")
+                        .HasForeignKey("RoleId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Claims")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Logins")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityRole")
+                        .WithMany()
+                        .HasForeignKey("RoleId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Roles")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Tokens")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
+                {
+                    b.HasOne("Volo.Blogging.Posts.Post")
+                        .WithMany()
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.HasOne("Volo.Blogging.Comments.Comment")
+                        .WithMany()
+                        .HasForeignKey("RepliedCommentId");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
+                {
+                    b.HasOne("Volo.Blogging.Blogs.Blog")
+                        .WithMany()
+                        .HasForeignKey("BlogId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
+                {
+                    b.HasOne("Volo.Blogging.Posts.Post")
+                        .WithMany("Tags")
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.HasOne("Volo.Blogging.Tagging.Tag")
+                        .WithMany()
+                        .HasForeignKey("TagId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181210071243_Docs_Upgrade_0_9.cs b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181210071243_Docs_Upgrade_0_9.cs
new file mode 100644
index 0000000000..2768914460
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181210071243_Docs_Upgrade_0_9.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
+{
+    public partial class Docs_Upgrade_0_9 : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "GoogleCustomSearchId",
+                table: "DocsProjects");
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn(
+                name: "GoogleCustomSearchId",
+                table: "DocsProjects",
+                nullable: true);
+        }
+    }
+}
diff --git a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/AbpWebSiteDbContextModelSnapshot.cs b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/AbpWebSiteDbContextModelSnapshot.cs
index 61d530915c..4ec11d491e 100644
--- a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/AbpWebSiteDbContextModelSnapshot.cs
+++ b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/AbpWebSiteDbContextModelSnapshot.cs
@@ -627,8 +627,6 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
 
                     b.Property("Format");
 
-                    b.Property("GoogleCustomSearchId");
-
                     b.Property("LatestVersionBranchName")
                         .HasMaxLength(128);
 

From 5f009eb96fc8746ea94ce5993695e95898bf2670 Mon Sep 17 00:00:00 2001
From: Halil ibrahim Kalkan 
Date: Mon, 10 Dec 2018 13:22:38 +0300
Subject: [PATCH 07/36] Clean csproj files from unnecessary items.

---
 .../Volo.Blogging.Application.Contracts.csproj        | 11 ++---------
 .../Volo.Abp.Identity.Application.Contracts.csproj    |  4 ----
 .../Volo.Abp.Identity.Domain.csproj                   |  4 ----
 ....Abp.TenantManagement.Application.Contracts.csproj |  4 ----
 ...anyName.MyProjectName.Application.Contracts.csproj |  4 ----
 .../MyCompanyName.MyProjectName.Domain.csproj         |  4 ----
 6 files changed, 2 insertions(+), 29 deletions(-)

diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo.Blogging.Application.Contracts.csproj b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo.Blogging.Application.Contracts.csproj
index 5daa33dfde..dccdef1e0d 100644
--- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo.Blogging.Application.Contracts.csproj
+++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo.Blogging.Application.Contracts.csproj
@@ -10,15 +10,8 @@
   
 
   
-    
-    
-    
-  
-
-  
-    
-    
-    
+    
+    
   
 
   
diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo.Abp.Identity.Application.Contracts.csproj b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo.Abp.Identity.Application.Contracts.csproj
index 1cc2db0ba0..8550b20c3e 100644
--- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo.Abp.Identity.Application.Contracts.csproj
+++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo.Abp.Identity.Application.Contracts.csproj
@@ -17,10 +17,6 @@
     
   
 
-  
-    
-  
-
   
     
 
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj
index 6cc72b3779..a151c385b9 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj
@@ -17,10 +17,6 @@
     
   
 
-  
-    
-  
-
   
     
 
diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo.Abp.TenantManagement.Application.Contracts.csproj b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo.Abp.TenantManagement.Application.Contracts.csproj
index 76b3a3d8cb..393c22258c 100644
--- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo.Abp.TenantManagement.Application.Contracts.csproj
+++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo.Abp.TenantManagement.Application.Contracts.csproj
@@ -23,8 +23,4 @@
     
   
 
-  
-    
-  
-
 
diff --git a/templates/module/src/MyCompanyName.MyProjectName.Application.Contracts/MyCompanyName.MyProjectName.Application.Contracts.csproj b/templates/module/src/MyCompanyName.MyProjectName.Application.Contracts/MyCompanyName.MyProjectName.Application.Contracts.csproj
index a43dd21542..317662c6ac 100644
--- a/templates/module/src/MyCompanyName.MyProjectName.Application.Contracts/MyCompanyName.MyProjectName.Application.Contracts.csproj
+++ b/templates/module/src/MyCompanyName.MyProjectName.Application.Contracts/MyCompanyName.MyProjectName.Application.Contracts.csproj
@@ -20,8 +20,4 @@
     
   
 
-  
-    
-  
-
 
diff --git a/templates/module/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj b/templates/module/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj
index 861d0ac377..59e1709df7 100644
--- a/templates/module/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj
+++ b/templates/module/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj
@@ -20,8 +20,4 @@
     
   
 
-  
-    
-  
-
 

From 0892dc87f72762265bcfebf2b35aba70086844ca Mon Sep 17 00:00:00 2001
From: Halil ibrahim Kalkan 
Date: Mon, 10 Dec 2018 16:05:07 +0300
Subject: [PATCH 08/36] Update AbpViewComponent.cs

---
 .../Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs            | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs
index f66a992df7..883fea8046 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs
@@ -1,8 +1,15 @@
 using Microsoft.AspNetCore.Mvc;
+using Volo.Abp.ObjectMapping;
 
 namespace Volo.Abp.AspNetCore.Mvc
 {
     public abstract class AbpViewComponent : ViewComponent
     {
+        public IObjectMapper ObjectMapper { get; set; }
+
+        protected AbpViewComponent()
+        {
+            
+        }
     }
 }

From f37b88528afd80ebc08b2ab03a724d7a8e2bb857 Mon Sep 17 00:00:00 2001
From: Yunus Emre Kalkan 
Date: Tue, 11 Dec 2018 09:17:33 +0300
Subject: [PATCH 09/36] Resolved https://github.com/abpframework/abp/issues/634

---
 .../BookStore/src/Acme.BookStore.Web/Pages/Books/index.js   | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/index.js b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/index.js
index 5b99327141..e1f8e44804 100644
--- a/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/index.js
+++ b/samples/BookStore/src/Acme.BookStore.Web/Pages/Books/index.js
@@ -6,6 +6,12 @@
     var editModal = new abp.ModalManager(abp.appPath + 'Books/EditModal');
 
     var dataTable = $('#BooksTable').DataTable(abp.libs.datatables.normalizeConfiguration({
+        processing: true,
+        serverSide: true,
+        paging: true,
+        searching: false,
+        autoWidth: false,
+        scrollCollapse: true,
         order: [[1, "asc"]],
         ajax: abp.libs.datatables.createAjax(acme.bookStore.book.getList),
         columnDefs: [

From 25cd5c04b8c98680259b7085a6b4f7a0cf31c5ae Mon Sep 17 00:00:00 2001
From: Yunus Emre Kalkan 
Date: Tue, 11 Dec 2018 09:19:45 +0300
Subject: [PATCH 10/36] Updated documentation:
 https://github.com/abpframework/abp/issues/634

---
 docs/en/Tutorials/AspNetCore-Mvc/Part-II.md      | 6 ++++++
 docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md b/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md
index e0ec830727..eeb14db8bb 100644
--- a/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md
+++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-II.md
@@ -279,6 +279,12 @@ $(function () {
     var editModal = new abp.ModalManager(abp.appPath + 'Books/EditModal');
 
     var dataTable = $('#BooksTable').DataTable(abp.libs.datatables.normalizeConfiguration({
+        processing: true,
+        serverSide: true,
+        paging: true,
+        searching: false,
+        autoWidth: false,
+        scrollCollapse: true,
         order: [[1, "asc"]],
         ajax: abp.libs.datatables.createAjax(acme.bookStore.book.getList),
         columnDefs: [
diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md
index 3e355b5c94..a7334030a6 100644
--- a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md
+++ b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md
@@ -279,6 +279,12 @@ $(function () {
     var editModal = new abp.ModalManager(abp.appPath + 'Books/EditModal');
 
     var dataTable = $('#BooksTable').DataTable(abp.libs.datatables.normalizeConfiguration({
+        processing: true,
+        serverSide: true,
+        paging: true,
+        searching: false,
+        autoWidth: false,
+        scrollCollapse: true,
         order: [[1, "asc"]],
         ajax: abp.libs.datatables.createAjax(acme.bookStore.book.getList),
         columnDefs: [

From 6b49c5f05cffd15ab494ddc6003fd983a58b020a Mon Sep 17 00:00:00 2001
From: Halil ibrahim Kalkan 
Date: Tue, 11 Dec 2018 14:51:12 +0300
Subject: [PATCH 11/36] Created background job documentation

---
 docs/en/Background-Jobs-Hangfire.md |   3 +
 docs/en/Background-Jobs-RabbitMq.md |   3 +
 docs/en/Background-Jobs.md          | 163 +++++++++++++++++++++++++++-
 docs/en/Emailing.md                 |   3 +
 docs/en/Index.md                    |   2 +
 docs/en/Modules/Background-Jobs.md  |   3 +
 6 files changed, 171 insertions(+), 6 deletions(-)
 create mode 100644 docs/en/Background-Jobs-Hangfire.md
 create mode 100644 docs/en/Background-Jobs-RabbitMq.md
 create mode 100644 docs/en/Emailing.md
 create mode 100644 docs/en/Modules/Background-Jobs.md

diff --git a/docs/en/Background-Jobs-Hangfire.md b/docs/en/Background-Jobs-Hangfire.md
new file mode 100644
index 0000000000..031ae28589
--- /dev/null
+++ b/docs/en/Background-Jobs-Hangfire.md
@@ -0,0 +1,3 @@
+# Hangfire Background Job Manager
+
+TODO
\ No newline at end of file
diff --git a/docs/en/Background-Jobs-RabbitMq.md b/docs/en/Background-Jobs-RabbitMq.md
new file mode 100644
index 0000000000..a984a2a3ab
--- /dev/null
+++ b/docs/en/Background-Jobs-RabbitMq.md
@@ -0,0 +1,3 @@
+# RabbitMQ Background Job Manager
+
+TODO
\ No newline at end of file
diff --git a/docs/en/Background-Jobs.md b/docs/en/Background-Jobs.md
index 12e0dbbeea..483df737a1 100644
--- a/docs/en/Background-Jobs.md
+++ b/docs/en/Background-Jobs.md
@@ -1,6 +1,6 @@
-## Background Jobs
+# Background Jobs
 
-### Introduction
+## Introduction
 
 Background jobs are used to queue some tasks to be executed in the background. You may need background jobs for several reasons. Here are some examples:
 
@@ -9,15 +9,166 @@ Background jobs are used to queue some tasks to be executed in the background. Y
 
 Background jobs are **persistent** that means they will be **re-tried** and **executed** later even if your application crashes.
 
+## Abstraction Package
+
 ABP provides an **abstraction** module and **several implementations** for background jobs. It has a built-in/default implementation as well as Hangfire and RabbitMQ integrations.
 
-### Abstraction Module
+`Volo.Abp.BackgroundJobs.Abstractions` nuget package provides needed services to create background jobs and queue background job items. If your module only depend on this package, it can be independent from the actual implementation/integration.
 
-TODO
+> `Volo.Abp.BackgroundJobs.Abstractions` package is installed to the startup templates by default.
 
-### Creating a Background Job
+### Create a Background Job
 
 A background job is a class that implements the `IBackgroundJob` interface or derives from the `BackgroundJob` class. `TArgs` is a simple plain C# class to store the job data.
 
-An example background job to send emails in background:
+This example is used to send emails in background. First, define a class to store arguments of the background job:
+
+````csharp
+public class EmailSendingArgs
+{
+    public string EmailAddress { get; set; }
+    public string Subject { get; set; }
+    public string Body { get; set; }
+}
+````
+
+Then create a background job class that uses an `EmailSendingArgs` object to send an email:
+
+````csharp
+using Volo.Abp.BackgroundJobs;
+using Volo.Abp.Emailing;
+
+namespace MyProject
+{
+    public class EmailSendingJob : BackgroundJob
+    {
+        private readonly IEmailSender _emailSender;
+
+        public EmailSendingJob(IEmailSender emailSender)
+        {
+            _emailSender = emailSender;
+        }
+
+        public override void Execute(EmailSendingArgs args)
+        {
+            _emailSender.Send(
+                args.EmailAddress,
+                args.Subject,
+                args.Body
+            );
+        }
+    }
+}
+````
+
+This job simply uses `IEmailSender` to send emails (see [email sending document](Emailing.md)).
+
+#### Exception Handling
+
+A background job should not hide exceptions. If it throws an exception, the background job is automatically re-tried after a calculated waiting time. Hide exceptions only if you don't want to re-run the background job for the current argument.
+
+### Queue a Job Item
+
+Now, you can queue an email sending job using the `IBackgroundJobManager` service:
+
+````csharp
+public class RegistrationService : ApplicationService
+{
+    private readonly IBackgroundJobManager _backgroundJobManager;
+
+    public RegistrationService(IBackgroundJobManager backgroundJobManager)
+    {
+        _backgroundJobManager = backgroundJobManager;
+    }
+
+    public async Task RegisterAsync(string userName, string emailAddress, string password)
+    {
+        //TODO: Create new user in the database...
+
+        await _backgroundJobManager.EnqueueAsync(
+            new EmailSendingArgs
+            {
+                EmailAddress = emailAddress,
+                Subject = "You've successfully registered!",
+                Body = "..."
+            }
+        );
+    }
+}
+````
+
+Just injected `IBackgroundJobManager` service and used its `EnqueueAsync` method to add a new job to the queue.
+
+Enqueue method gets some optional arguments to control the background job:
+
+* **priority** is used to control priority of the job item. It gets an `BackgroundJobPriority` enum which has `Low`, `BelowNormal`, `Normal` (default), `AboveNormal` and `Hight` fields.
+* **delay** is used to wait a while (`TimeSpan`) before first try.
+
+### Disable Job Execution
+
+You may want to disable background job execution for your application. This is generally needed if you want to execute background jobs in another process and disable it for the current process.
+
+Use `BackgroundJobOptions` to configure the job execution:
+
+````csharp
+[DependsOn(typeof(AbpBackgroundJobsModule))]
+public class MyModule : AbpModule
+{
+    public override void ConfigureServices(ServiceConfigurationContext context)
+    {
+        Configure(options =>
+        {
+            options.IsJobExecutionEnabled = false; //Disables job execution
+        });
+    }
+}
+````
+
+> Default background manager (see below) does not support multiple processes execute the same job queue. So, if you have multiple running instance of your application and you are using the default background job manager, you should only enable one application instance process the job queue.
+
+## Default Background Job Manager
+
+ABP framework includes a simple `IBackgroundJobManager` implementation that;
+
+- Works as **FIFO** in a **single thread**.
+- **Retries** job execution until the job **successfully runs** or **timeouts**. Default timeout is 2 days for a job. Logs all exceptions.
+- **Deletes** a job from the store (database) when it's successfully executed. If it's timed out, it sets it as **abandoned** and leaves it in the database.
+- **Increasingly waits between retries** for a job. It waits 1 minute for the first retry, 2 minutes for the second retry, 4 minutes for the third retry and so on.
+- **Polls** the store for jobs in fixed intervals. It queries jobs, ordering by priority (asc) and then by try count (asc).
+
+> `Volo.Abp.BackgroundJobs` nuget package contains the default background job manager and it is installed to the startup templates by default.
+
+### Configuration
+
+Use `BackgroundJobWorkerOptions` in your [module class](Module-Development-Basics.md) to configure the default background job manager. The example below changes the timeout duration for background jobs:
+
+````csharp
+[DependsOn(typeof(AbpBackgroundJobsModule))]
+public class MyModule : AbpModule
+{
+    public override void ConfigureServices(ServiceConfigurationContext context)
+    {
+        Configure(options =>
+        {
+            options.DefaultTimeout = 864000; //10 days (as seconds)
+        });
+    }
+}
+````
+
+### Data Store
+
+The default background job manager needs a data store to save and read jobs. It defines `IBackgroundJobStore` as an abstraction. So, you can replace the implementation if you want.
+
+Background Jobs module implements `IBackgroundJobStore` using various data access providers. See its own [documentation](Modules/Background-Jobs.md).
+
+> Background Jobs module is already installed to the startup templates by default and it works based on your ORM/data access choice.
+
+## Integrations
+
+Background job system is extensible and you can change the default background job manager with your own implementation or on of the pre-built integrations.
+
+See pre-built job manager alternatives:
 
+* [Hangfire Background Job Manager](Background-Jobs-Hangfire.md)
+* [RabbitMQ Background Job Manager](Background-Jobs-RabbitMq.md)
\ No newline at end of file
diff --git a/docs/en/Emailing.md b/docs/en/Emailing.md
new file mode 100644
index 0000000000..75069aacbe
--- /dev/null
+++ b/docs/en/Emailing.md
@@ -0,0 +1,3 @@
+# Emailing
+
+TODO!
\ No newline at end of file
diff --git a/docs/en/Index.md b/docs/en/Index.md
index 150ce18275..443579e40e 100644
--- a/docs/en/Index.md
+++ b/docs/en/Index.md
@@ -61,4 +61,6 @@
 * Data Access
   * [Entity Framework Core Integration](Entity-Framework-Core.md)
   * [MongoDB Integration](MongoDB.md)
+* Background
+  * [Background Jobs](Background-Jobs.md)
 * Testing
diff --git a/docs/en/Modules/Background-Jobs.md b/docs/en/Modules/Background-Jobs.md
new file mode 100644
index 0000000000..18d7f43486
--- /dev/null
+++ b/docs/en/Modules/Background-Jobs.md
@@ -0,0 +1,3 @@
+# Background Jobs Module
+
+TODO
\ No newline at end of file

From d3534efcb5b533ca54fcda57dc72fd700931c882 Mon Sep 17 00:00:00 2001
From: Halil ibrahim Kalkan 
Date: Tue, 11 Dec 2018 14:54:49 +0300
Subject: [PATCH 12/36] Add background jobs to the nav doc

---
 docs/en/docs-nav.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json
index d0733a5f6d..c0171cd15c 100644
--- a/docs/en/docs-nav.json
+++ b/docs/en/docs-nav.json
@@ -226,6 +226,24 @@
         }
       ]
     },
+    {
+      "text": "Background",
+      "items": [
+        {
+          "text": "Background Jobs",
+          "path": "Background-Jobs.md",
+          "items": [
+            {
+              "text": "Hangfire Integration",
+              "path": "Background-Jobs-Hangfire.md"
+            },
+            {
+              "text": "RabbitMQ Integration",
+              "path": "Background-Jobs-RabbitMq.md"
+            }
+        }
+      ]
+    },
     {
       "text": "Testing"
     },

From 75181aa1798152b21e699e6021d384b5273a7556 Mon Sep 17 00:00:00 2001
From: Yunus Emre Kalkan 
Date: Tue, 11 Dec 2018 15:45:11 +0300
Subject: [PATCH 13/36] small fixes

---
 .../Form/AbpDynamicformTagHelperService.cs      |  7 ++++---
 .../AbpListGroupItemTagHelperService.cs         | 17 ++++++++++++++---
 .../Volo/Blogging/Posts/PostAppService.cs       |  2 +-
 3 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs
index 9337fad1ba..3d7504f72d 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs
@@ -134,10 +134,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
                 if (IsSelectGroup(context, model))
                 {
                     ProcessSelectGroup(context, output, model);
-                    continue;
                 }
-
-                ProcessInputGroup(context, output, model);
+                else
+                {
+                    ProcessInputGroup(context, output, model);
+                }
             }
         }
 
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/ListGroup/AbpListGroupItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/ListGroup/AbpListGroupItemTagHelperService.cs
index f13f184622..c80f07dde3 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/ListGroup/AbpListGroupItemTagHelperService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/ListGroup/AbpListGroupItemTagHelperService.cs
@@ -37,9 +37,20 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.ListGroup
         {
             output.Attributes.AddClass("list-group-item");
 
-            if (TagHelper.Active ?? false) output.Attributes.AddClass("active");
-            if (TagHelper.Disabled ?? false) output.Attributes.AddClass("disabled");
-            if (TagHelper.Type != AbpListItemType.Default) { output.Attributes.AddClass("list-group-item-" + TagHelper.Type.ToString().ToLowerInvariant()); }
+            if (TagHelper.Active ?? false)
+            {
+                output.Attributes.AddClass("active");
+            }
+
+            if (TagHelper.Disabled ?? false)
+            {
+                output.Attributes.AddClass("disabled");
+            }
+
+            if (TagHelper.Type != AbpListItemType.Default)
+            {
+                output.Attributes.AddClass("list-group-item-" + TagHelper.Type.ToString().ToLowerInvariant());
+            }
         }
 
         protected virtual void MakeLinkIfHrefIsSet()
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 09671ca30b..5bf5c6decb 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
@@ -146,7 +146,7 @@ namespace Volo.Blogging.Posts
             var tags = await GetTagsOfPost(id);
             _tagRepository.DecreaseUsageCountOfTags(tags.Select(t => t.Id).ToList());
             _postTagRepository.DeleteOfPost(id);
-            _commentRepository.DeleteOfPost(id);
+            await _commentRepository.DeleteOfPost(id);
 
             await _postRepository.DeleteAsync(id);
         }

From bb2e740762e6f66fe7c2a5dae1b27e7882029f88 Mon Sep 17 00:00:00 2001
From: Halil ibrahim Kalkan 
Date: Tue, 11 Dec 2018 15:56:19 +0300
Subject: [PATCH 14/36] Fix nav file

---
 docs/en/docs-nav.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json
index c0171cd15c..fa8ec3552e 100644
--- a/docs/en/docs-nav.json
+++ b/docs/en/docs-nav.json
@@ -241,6 +241,7 @@
               "text": "RabbitMQ Integration",
               "path": "Background-Jobs-RabbitMq.md"
             }
+          ]
         }
       ]
     },

From 0d6a790569d63985e04b44b295f8a330b6cf6c36 Mon Sep 17 00:00:00 2001
From: Alper Ebicoglu 
Date: Tue, 11 Dec 2018 16:39:52 +0300
Subject: [PATCH 15/36] fixes #602

---
 .../Markdown/MarkdownDocumentToHtmlConverter.cs           | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs
index 7851d99a99..0b6e18e5a8 100644
--- a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs
+++ b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs
@@ -15,7 +15,7 @@ namespace Volo.Docs.Markdown
         public const string Type = "md";
 
         private const string MdLinkFormat = "[{0}](/documents/{1}/{2}{3}/{4})";
-        private const string MarkdownLinkRegExp = @"\[([^)]+)\]\(([^)]+." + Type + @")\)";
+        private const string MarkdownLinkRegExp = @"\[(.*)\]\((.*\.md)\)";
         private const string AnchorLinkRegExp = @"]+href=\""(.*?)\""[^>]*>(.*)?";
 
         public virtual string Convert(ProjectDto project, DocumentWithDetailsDto document, string version)
@@ -36,12 +36,12 @@ namespace Volo.Docs.Markdown
         }
 
         protected virtual string NormalizeLinks(
-            string content, 
-            string projectShortName, 
+            string content,
+            string projectShortName,
             string version,
             string documentLocalDirectory)
         {
-            var normalized = Regex.Replace(content, MarkdownLinkRegExp, delegate(Match match)
+            var normalized = Regex.Replace(content, MarkdownLinkRegExp, delegate (Match match)
             {
                 var link = match.Groups[2].Value;
                 if (UrlHelper.IsExternalLink(link))

From 58ef23db03f4d663dbb71e53048bbc6b0152ecb9 Mon Sep 17 00:00:00 2001
From: Halil ibrahim Kalkan 
Date: Tue, 11 Dec 2018 16:54:23 +0300
Subject: [PATCH 16/36] #247 Implement IHasConcurrencyStamp and
 IHasExtraProperties for aggregate root.

---
 .../Volo/Abp/Domain/Entities/AggregateRoot.cs | 41 +++++++++++++++----
 .../Volo/Abp/Identity/IdentityRole.cs         |  8 +---
 .../Volo/Abp/Identity/IdentityUser.cs         | 12 +-----
 ...IdentityDbContextModelBuilderExtensions.cs |  2 +
 .../MongoDB/AbpIdentityBsonClassMap.cs        |  1 +
 .../MyProjectNameApplicationModule.cs         |  3 +-
 6 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs
index 2916b7de3b..3521672445 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs
@@ -1,15 +1,31 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using Volo.Abp.Auditing;
+using Volo.Abp.Data;
 
 namespace Volo.Abp.Domain.Entities
 {
     [Serializable]
-    public abstract class AggregateRoot : Entity, IAggregateRoot, IGeneratesDomainEvents
+    public abstract class AggregateRoot : Entity, 
+        IAggregateRoot,
+        IGeneratesDomainEvents, 
+        IHasExtraProperties,
+        IHasConcurrencyStamp
     {
+        public Dictionary ExtraProperties { get; protected set; }
+
+        [DisableAuditing]
+        public string ConcurrencyStamp { get; set; }
+
         private readonly ICollection _localEvents = new Collection();
         private readonly ICollection _distributedEvents = new Collection();
 
+        protected AggregateRoot()
+        {
+            ExtraProperties = new Dictionary();
+        }
+
         protected virtual void AddLocalEvent(object eventData)
         {
             _localEvents.Add(eventData);
@@ -25,7 +41,7 @@ namespace Volo.Abp.Domain.Entities
             return _localEvents;
         }
 
-        public IEnumerable GetDistributedEvents()
+        public virtual IEnumerable GetDistributedEvents()
         {
             return _distributedEvents;
         }
@@ -35,27 +51,36 @@ namespace Volo.Abp.Domain.Entities
             _localEvents.Clear();
         }
 
-        public void ClearDistributedEvents()
+        public virtual void ClearDistributedEvents()
         {
             _distributedEvents.Clear();
         }
     }
 
     [Serializable]
-    public abstract class AggregateRoot : Entity, IAggregateRoot, IGeneratesDomainEvents
+    public abstract class AggregateRoot : Entity, 
+        IAggregateRoot, 
+        IGeneratesDomainEvents, 
+        IHasExtraProperties,
+        IHasConcurrencyStamp
     {
+        public Dictionary ExtraProperties { get; protected set; }
+
+        [DisableAuditing]
+        public string ConcurrencyStamp { get; set; }
+
         private readonly ICollection _localEvents = new Collection();
         private readonly ICollection _distributedEvents = new Collection();
 
         protected AggregateRoot()
         {
-            
+            ExtraProperties = new Dictionary();
         }
 
         protected AggregateRoot(TKey id)
             : base(id)
         {
-
+            ExtraProperties = new Dictionary();
         }
 
         protected virtual void AddLocalEvent(object eventData)
@@ -73,7 +98,7 @@ namespace Volo.Abp.Domain.Entities
             return _localEvents;
         }
 
-        public IEnumerable GetDistributedEvents()
+        public virtual IEnumerable GetDistributedEvents()
         {
             return _distributedEvents;
         }
@@ -83,7 +108,7 @@ namespace Volo.Abp.Domain.Entities
             _localEvents.Clear();
         }
 
-        public void ClearDistributedEvents()
+        public virtual void ClearDistributedEvents()
         {
             _distributedEvents.Clear();
         }
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs
index 8d87bf8788..1b2a849438 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs
@@ -13,7 +13,7 @@ namespace Volo.Abp.Identity
     /// 
     /// Represents a role in the identity system
     /// 
-    public class IdentityRole : AggregateRoot, IHasConcurrencyStamp, IMultiTenant
+    public class IdentityRole : AggregateRoot, IMultiTenant
     {
         public virtual Guid? TenantId { get; protected set; }
 
@@ -33,12 +33,6 @@ namespace Volo.Abp.Identity
         /// 
         public virtual ICollection Claims { get; protected set; }
 
-        /// 
-        /// A random value that should change whenever a role is persisted to the store
-        /// 
-        [DisableAuditing]
-        public virtual string ConcurrencyStamp { get; set; }
-
         /// 
         /// A default role is automatically assigned to a new user
         /// 
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs
index 449561bc27..38c1904532 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs
@@ -6,8 +6,6 @@ using System.Security.Claims;
 using JetBrains.Annotations;
 using Microsoft.AspNetCore.Identity;
 using Volo.Abp.Auditing;
-using Volo.Abp.Data;
-using Volo.Abp.Domain.Entities;
 using Volo.Abp.Domain.Entities.Auditing;
 using Volo.Abp.Guids;
 using Volo.Abp.ObjectMapping;
@@ -15,7 +13,7 @@ using Volo.Abp.Users;
 
 namespace Volo.Abp.Identity
 {
-    public class IdentityUser : FullAuditedAggregateRoot, IHasConcurrencyStamp, IUser, IHasExtraProperties, IMapTo
+    public class IdentityUser : FullAuditedAggregateRoot, IUser, IMapTo
     {
         public virtual Guid? TenantId { get; protected set; }
 
@@ -69,12 +67,6 @@ namespace Volo.Abp.Identity
         [DisableAuditing]
         public virtual string SecurityStamp { get; protected internal set; }
 
-        /// 
-        /// A random value that must change whenever a user is persisted to the store
-        /// 
-        [DisableAuditing]
-        public virtual string ConcurrencyStamp { get; set; }
-
         /// 
         /// Gets or sets a telephone number for the user.
         /// 
@@ -133,8 +125,6 @@ namespace Volo.Abp.Identity
         /// 
         public virtual ICollection Tokens { get; protected set; }
 
-        public Dictionary ExtraProperties { get; protected set; }
-
         protected IdentityUser()
         {
             ExtraProperties = new Dictionary();
diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs
index af5cfd19e8..a0ffadea8c 100644
--- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs
+++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs
@@ -95,6 +95,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
             {
                 b.ToTable(options.TablePrefix + "Roles", options.Schema);
 
+                b.ConfigureExtraProperties();
+
                 b.Property(r => r.Name).IsRequired().HasMaxLength(IdentityRoleConsts.MaxNameLength);
                 b.Property(r => r.NormalizedName).IsRequired().HasMaxLength(IdentityRoleConsts.MaxNormalizedNameLength);
                 b.Property(r => r.IsDefault).HasColumnName(nameof(IdentityRole.IsDefault));
diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs
index 5d380afde9..6bd6ff8623 100644
--- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs
+++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs
@@ -21,6 +21,7 @@ namespace Volo.Abp.Identity.MongoDB
                 BsonClassMap.RegisterClassMap(map =>
                 {
                     map.AutoMap();
+                    map.ConfigureExtraProperties();
                 });
 
                 BsonClassMap.RegisterClassMap(map =>
diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameApplicationModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameApplicationModule.cs
index 464e982a1e..644b18ac34 100644
--- a/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameApplicationModule.cs
+++ b/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameApplicationModule.cs
@@ -1,5 +1,4 @@
-using Microsoft.Extensions.DependencyInjection;
-using MyCompanyName.MyProjectName.Permissions;
+using MyCompanyName.MyProjectName.Permissions;
 using Volo.Abp.Authorization.Permissions;
 using Volo.Abp.AutoMapper;
 using Volo.Abp.Identity;

From 0c1aaccebb121b678ce5fe78bfc126b4cc1738d4 Mon Sep 17 00:00:00 2001
From: Halil ibrahim Kalkan 
Date: Tue, 11 Dec 2018 17:08:51 +0300
Subject: [PATCH 17/36] ConfigureExtraProperties for test aggregate roots.

---
 .../TestApp/SecondContext/SecondDbContext.cs  |  7 +++++
 .../Domain/ConcurrencyStamp_Tests.cs          |  8 ++++++
 .../TestMigrationsDbContext.cs                | 21 +++++++++++++++
 .../EntityFrameworkCore/TestAppDbContext.cs   | 16 ++++++++++++
 .../TestApp/Testing/ConcurrencyStamp_Tests.cs | 26 +++++++++++++++++++
 5 files changed, 78 insertions(+)
 create mode 100644 framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ConcurrencyStamp_Tests.cs
 create mode 100644 framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs

diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondDbContext.cs
index f07ffbc5a3..bb2f0504ad 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondDbContext.cs
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondDbContext.cs
@@ -1,4 +1,5 @@
 using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
 
 namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext
 {
@@ -20,6 +21,12 @@ namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext
             modelBuilder.Entity(b =>
             {
                 b.HasKey(p => new { p.PersonId, p.Number });
+                b.ConfigureExtraProperties();
+            });
+
+            modelBuilder.Entity(b =>
+            {
+                b.ConfigureExtraProperties();
             });
         }
     }
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ConcurrencyStamp_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ConcurrencyStamp_Tests.cs
new file mode 100644
index 0000000000..ffda538b50
--- /dev/null
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ConcurrencyStamp_Tests.cs
@@ -0,0 +1,8 @@
+using Volo.Abp.TestApp.Testing;
+
+namespace Volo.Abp.EntityFrameworkCore.Domain
+{
+    public class ConcurrencyStamp_Tests : ConcurrencyStamp_Tests
+    {
+    }
+}
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
index cb9726d6b4..68e6ac97cb 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
@@ -1,4 +1,5 @@
 using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
 using Volo.Abp.EntityFrameworkCore.TestApp.SecondContext;
 using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext;
 using Volo.Abp.TestApp.Domain;
@@ -29,6 +30,26 @@ namespace Volo.Abp.EntityFrameworkCore
             {
                 b.HasKey(p => new { p.PersonId, p.Number });
             });
+
+            modelBuilder.Entity(b =>
+            {
+                b.ConfigureExtraProperties();
+            });
+
+            modelBuilder.Entity(b =>
+            {
+                b.ConfigureExtraProperties();
+            });
+
+            modelBuilder.Entity(b =>
+            {
+                b.ConfigureExtraProperties();
+            });
+
+            modelBuilder.Entity(b =>
+            {
+                b.ConfigureExtraProperties();
+            });
         }
     }
 }
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
index 00e052d2dd..bef7830567 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
@@ -1,5 +1,6 @@
 using Microsoft.EntityFrameworkCore;
 using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
 using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext;
 using Volo.Abp.TestApp.Domain;
 
@@ -23,10 +24,25 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore
         {
             base.OnModelCreating(modelBuilder);
 
+            modelBuilder.Entity(b =>
+            {
+                b.ConfigureExtraProperties();
+            });
+
             modelBuilder.Entity(b =>
             {
                 b.HasKey(p => new {p.PersonId, p.Number});
             });
+
+            modelBuilder.Entity(b =>
+            {
+                b.ConfigureExtraProperties();
+            });
+
+            modelBuilder.Entity(b =>
+            {
+                b.ConfigureExtraProperties();
+            });
         }
     }
 }
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs
new file mode 100644
index 0000000000..bc83d08216
--- /dev/null
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs
@@ -0,0 +1,26 @@
+using System.Threading.Tasks;
+using Volo.Abp.Modularity;
+using Volo.Abp.TestApp.Domain;
+using Xunit;
+
+namespace Volo.Abp.TestApp.Testing
+{
+    public class ConcurrencyStamp_Tests : TestAppTestBase
+        where TStartupModule : IAbpModule
+    {
+        protected readonly ICityRepository CityRepository;
+
+        public ConcurrencyStamp_Tests()
+        {
+            CityRepository = GetRequiredService();
+        }
+
+        [Fact]
+        public async Task Should_Not_Allow_To_Update_If_The_Entity_Has_Changed()
+        {
+            var london = await CityRepository.FindByNameAsync("London");
+            london.Name = "London-1";
+            await CityRepository.UpdateAsync(london);
+        }
+    }
+}

From 60c0e6b5e5a4808ecef052d024fd1aca646c4ba5 Mon Sep 17 00:00:00 2001
From: Halil ibrahim Kalkan 
Date: Tue, 11 Dec 2018 17:11:22 +0300
Subject: [PATCH 18/36] Added concurrency stamp test

---
 .../Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs
index bc83d08216..e74e482cac 100644
--- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs
@@ -1,4 +1,5 @@
 using System.Threading.Tasks;
+using Volo.Abp.Data;
 using Volo.Abp.Modularity;
 using Volo.Abp.TestApp.Domain;
 using Xunit;
@@ -18,9 +19,17 @@ namespace Volo.Abp.TestApp.Testing
         [Fact]
         public async Task Should_Not_Allow_To_Update_If_The_Entity_Has_Changed()
         {
-            var london = await CityRepository.FindByNameAsync("London");
-            london.Name = "London-1";
-            await CityRepository.UpdateAsync(london);
+            var london1 = await CityRepository.FindByNameAsync("London");
+            london1.Name = "London-1";
+
+            var london2 = await CityRepository.FindByNameAsync("London");
+            london2.Name = "London-2";
+            await CityRepository.UpdateAsync(london2);
+
+            await Assert.ThrowsAsync(async () =>
+            {
+                await CityRepository.UpdateAsync(london1);
+            });
         }
     }
 }

From c45ea271e4f3b873d4612e43a3285c4d90ebba09 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=A2=81=E5=A3=AB=E4=BC=9F?= 
Date: Fri, 30 Nov 2018 15:01:02 +0800
Subject: [PATCH 19/36] Fix document spelling errors

---
 docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
index 12c913511f..a9e333690f 100644
--- a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
+++ b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
@@ -295,7 +295,7 @@ successfully created the book with id: f3f03580-c1aa-d6a9-072d-39e75c69f5c7
 现在我们来创建一些可见的可用的东西,我们使用[Razor Pages UI](https://docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/razor-pages-start)代替经典的MVC.微软也推荐使用Razor Pages UI
 
 
-在 `Acme.BookStore.Web`项目的`Pages`文件夹下创建一个新的文件夹叫`Books`并添加一个名叫`Index.html`的Razor Page.
+在 `Acme.BookStore.Web`项目的`Pages`文件夹下创建一个新的文件夹叫`Books`并添加一个名叫`Index.cshtml`的Razor Page.
 
 ![bookstore-add-index-page](images/bookstore-add-index-page.png)
 

From 1da137a131f8e5adadb487569be37166fc5bcff2 Mon Sep 17 00:00:00 2001
From: maliming 
Date: Fri, 30 Nov 2018 15:04:38 +0800
Subject: [PATCH 20/36] Update Getting-Started-AspNetCore-MVC-Template.md

---
 docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md b/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md
index ebb832c04b..6f274b5177 100644
--- a/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md
+++ b/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md
@@ -28,8 +28,6 @@
 * ``.Web`` 为是表示层.
 * ``.EntityFrameworkCore`` 是EF Core集成.
 
-The solution also contains unit & integration test projects properly configured to work with **EF Core** & **SQLite in-memory** database.
-
 解决方案还包含配置好的的单元&集成测试项目, 以便与 **EF Core** 和 **SQLite内存中** 数据库配合使用.
 
 ### 创建数据库
@@ -44,8 +42,6 @@ The solution also contains unit & integration test projects properly configured
 }
 ````
 
-The solution is configured to use **Entity Framework Core** with **MS SQL Server**. EF Core supports [various](https://docs.microsoft.com/en-us/ef/core/providers/) database providers, so you can use another DBMS if you want.
-
 解决方案使用 **Entity Framework Core** 和 **MS SQL Server**. EF Core支持[各种](https://docs.microsoft.com/en-us/ef/core/providers/)数据库提供程序,因此你可以根据实际需要使用其他DBMS.
 
 右键单击`.Web`项目并**设置启动项目**

From e5531687c4084261fe7a50001e4937d517152c1f Mon Sep 17 00:00:00 2001
From: Yunus Emre Kalkan 
Date: Wed, 12 Dec 2018 08:44:01 +0300
Subject: [PATCH 21/36] AggregateRoot class improvements

https://github.com/abpframework/abp/issues/247
---
 .../Volo/Abp/AuditLogging/AuditLog.cs         |   4 +-
 ...11140407_AggragateRoot_Changes.Designer.cs |  71 ++
 .../20181211140407_AggragateRoot_Changes.cs   |  31 +
 .../DemoAppDbContextModelSnapshot.cs          |   5 +
 ...undJobsDbContextModelCreatingExtensions.cs |   1 +
 .../MongoDB/BackgroundJobsBsonClassMap.cs     |   2 +
 ...11141402_AggregateRoot_Changes.Designer.cs | 721 ++++++++++++++++++
 .../20181211141402_AggregateRoot_Changes.cs   | 103 +++
 .../BloggingTestAppDbContextModelSnapshot.cs  |  25 +
 ...BloggingDbContextModelBuilderExtensions.cs |  10 +-
 .../MongoDB/AbpBloggingBsonClassMap.cs        |  29 +-
 ...11141818_AggregateRoot_Changes.Designer.cs |  68 ++
 .../20181211141818_AggregateRoot_Changes.cs   |  22 +
 .../DocsTestAppDbContextModelSnapshot.cs      |   2 +
 .../Volo/Docs/Projects/Project.cs             |   4 +-
 .../DocsDbContextModelBuilderExtensions.cs    |   2 +
 ...yServerDbContextModelCreatingExtensions.cs |   9 +
 .../MongoDB/AbpIdentityServerBsonClassMap.cs  |   5 +
 .../Volo/Abp/TenantManagement/Tenant.cs       |   4 +-
 ...agementDbContextModelCreatingExtensions.cs |   3 +
 20 files changed, 1105 insertions(+), 16 deletions(-)
 create mode 100644 modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/20181211140407_AggragateRoot_Changes.Designer.cs
 create mode 100644 modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/20181211140407_AggragateRoot_Changes.cs
 create mode 100644 modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181211141402_AggregateRoot_Changes.Designer.cs
 create mode 100644 modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181211141402_AggregateRoot_Changes.cs
 create mode 100644 modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181211141818_AggregateRoot_Changes.Designer.cs
 create mode 100644 modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181211141818_AggregateRoot_Changes.cs

diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs
index e92871c1de..f27e4d1e63 100644
--- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs
+++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs
@@ -10,7 +10,7 @@ using Volo.Abp.MultiTenancy;
 namespace Volo.Abp.AuditLogging
 {
     [DisableAuditing]
-    public class AuditLog : AggregateRoot, IHasExtraProperties, IMultiTenant
+    public class AuditLog : AggregateRoot, IMultiTenant
     {
         public virtual Guid? UserId { get; protected set; }
 
@@ -42,8 +42,6 @@ namespace Volo.Abp.AuditLogging
 
         public virtual int? HttpStatusCode { get; set; }
 
-        public virtual Dictionary ExtraProperties { get; protected set; }
-
         public virtual ICollection EntityChanges { get; protected set; }
 
         public virtual ICollection Actions { get; protected set; }
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/20181211140407_AggragateRoot_Changes.Designer.cs b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/20181211140407_AggragateRoot_Changes.Designer.cs
new file mode 100644
index 0000000000..d4ed20351c
--- /dev/null
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/20181211140407_AggragateRoot_Changes.Designer.cs
@@ -0,0 +1,71 @@
+// 
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Volo.Abp.BackgroundJobs;
+using Volo.Abp.BackgroundJobs.DemoApp.Db;
+
+namespace Volo.Abp.BackgroundJobs.DemoApp.Migrations
+{
+    [DbContext(typeof(DemoAppDbContext))]
+    [Migration("20181211140407_AggragateRoot_Changes")]
+    partial class AggragateRoot_Changes
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "2.1.0-rtm-30799")
+                .HasAnnotation("Relational:MaxIdentifierLength", 128)
+                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+            modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsAbandoned")
+                        .ValueGeneratedOnAdd()
+                        .HasDefaultValue(false);
+
+                    b.Property("JobArgs")
+                        .IsRequired()
+                        .HasMaxLength(1048576);
+
+                    b.Property("JobName")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("LastTryTime");
+
+                    b.Property("NextTryTime");
+
+                    b.Property("Priority")
+                        .ValueGeneratedOnAdd()
+                        .HasDefaultValue((byte)15);
+
+                    b.Property("TryCount")
+                        .ValueGeneratedOnAdd()
+                        .HasDefaultValue((short)0);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("IsAbandoned", "NextTryTime");
+
+                    b.ToTable("AbpBackgroundJobs");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/20181211140407_AggragateRoot_Changes.cs b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/20181211140407_AggragateRoot_Changes.cs
new file mode 100644
index 0000000000..25aa036ed3
--- /dev/null
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/20181211140407_AggragateRoot_Changes.cs
@@ -0,0 +1,31 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Volo.Abp.BackgroundJobs.DemoApp.Migrations
+{
+    public partial class AggragateRoot_Changes : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "AbpBackgroundJobs",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "AbpBackgroundJobs",
+                nullable: true);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "AbpBackgroundJobs");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "AbpBackgroundJobs");
+        }
+    }
+}
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs
index d7ca501dfb..d58d7a4966 100644
--- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs
@@ -25,9 +25,14 @@ namespace Volo.Abp.BackgroundJobs.DemoApp.Migrations
                     b.Property("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("CreationTime")
                         .HasColumnName("CreationTime");
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsAbandoned")
                         .ValueGeneratedOnAdd()
                         .HasDefaultValue(false);
diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs
index 026ed8efe0..191b0bd8ee 100644
--- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs
+++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs
@@ -21,6 +21,7 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore
                 b.ToTable(options.TablePrefix + "BackgroundJobs", options.Schema);
 
                 b.ConfigureCreationTime();
+                b.ConfigureExtraProperties();
 
                 b.Property(x => x.JobName).IsRequired().HasMaxLength(BackgroundJobRecordConsts.MaxJobNameLength);
                 b.Property(x => x.JobArgs).IsRequired().HasMaxLength(BackgroundJobRecordConsts.MaxJobArgsLength);
diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsBsonClassMap.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsBsonClassMap.cs
index 246635e66d..7dbdd0f96f 100644
--- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsBsonClassMap.cs
+++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobsBsonClassMap.cs
@@ -1,4 +1,5 @@
 using MongoDB.Bson.Serialization;
+using Volo.Abp.MongoDB;
 using Volo.Abp.Threading;
 
 namespace Volo.Abp.BackgroundJobs.MongoDB
@@ -14,6 +15,7 @@ namespace Volo.Abp.BackgroundJobs.MongoDB
                 BsonClassMap.RegisterClassMap(map =>
                 {
                     map.AutoMap();
+                    map.ConfigureExtraProperties();
                 });
             });
         }
diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181211141402_AggregateRoot_Changes.Designer.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181211141402_AggregateRoot_Changes.Designer.cs
new file mode 100644
index 0000000000..d022e46fcf
--- /dev/null
+++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181211141402_AggregateRoot_Changes.Designer.cs
@@ -0,0 +1,721 @@
+// 
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Volo.BloggingTestApp.EntityFrameworkCore;
+
+namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
+{
+    [DbContext(typeof(BloggingTestAppDbContext))]
+    [Migration("20181211141402_AggregateRoot_Changes")]
+    partial class AggregateRoot_Changes
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "2.1.1-rtm-30846")
+                .HasAnnotation("Relational:MaxIdentifierLength", 128)
+                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Description")
+                        .HasMaxLength(256);
+
+                    b.Property("IsStatic");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("Regex")
+                        .HasMaxLength(512);
+
+                    b.Property("RegexDescription")
+                        .HasMaxLength(128);
+
+                    b.Property("Required");
+
+                    b.Property("ValueType");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("AbpClaimTypes");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDefault")
+                        .HasColumnName("IsDefault");
+
+                    b.Property("IsPublic")
+                        .HasColumnName("IsPublic");
+
+                    b.Property("IsStatic")
+                        .HasColumnName("IsStatic");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("NormalizedName")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("TenantId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("NormalizedName");
+
+                    b.ToTable("AbpRoles");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ClaimType")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("ClaimValue")
+                        .HasMaxLength(1024);
+
+                    b.Property("RoleId");
+
+                    b.Property("TenantId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("RoleId");
+
+                    b.ToTable("AbpRoleClaims");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("AccessFailedCount")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("AccessFailedCount")
+                        .HasDefaultValue(0);
+
+                    b.Property("ConcurrencyStamp")
+                        .IsRequired()
+                        .HasColumnName("ConcurrencyStamp")
+                        .HasMaxLength(256);
+
+                    b.Property("CreationTime");
+
+                    b.Property("CreatorId");
+
+                    b.Property("DeleterId");
+
+                    b.Property("DeletionTime");
+
+                    b.Property("Email")
+                        .HasColumnName("Email")
+                        .HasMaxLength(256);
+
+                    b.Property("EmailConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("EmailConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted");
+
+                    b.Property("LastModificationTime");
+
+                    b.Property("LastModifierId");
+
+                    b.Property("LockoutEnabled")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("LockoutEnabled")
+                        .HasDefaultValue(false);
+
+                    b.Property("LockoutEnd");
+
+                    b.Property("Name")
+                        .HasColumnName("Name")
+                        .HasMaxLength(64);
+
+                    b.Property("NormalizedEmail")
+                        .HasColumnName("NormalizedEmail")
+                        .HasMaxLength(256);
+
+                    b.Property("NormalizedUserName")
+                        .IsRequired()
+                        .HasColumnName("NormalizedUserName")
+                        .HasMaxLength(256);
+
+                    b.Property("PasswordHash")
+                        .HasColumnName("PasswordHash")
+                        .HasMaxLength(256);
+
+                    b.Property("PhoneNumber")
+                        .HasColumnName("PhoneNumber")
+                        .HasMaxLength(16);
+
+                    b.Property("PhoneNumberConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("PhoneNumberConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("SecurityStamp")
+                        .IsRequired()
+                        .HasColumnName("SecurityStamp")
+                        .HasMaxLength(256);
+
+                    b.Property("Surname")
+                        .HasColumnName("Surname")
+                        .HasMaxLength(64);
+
+                    b.Property("TenantId")
+                        .HasColumnName("TenantId");
+
+                    b.Property("TwoFactorEnabled")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("TwoFactorEnabled")
+                        .HasDefaultValue(false);
+
+                    b.Property("UserName")
+                        .IsRequired()
+                        .HasColumnName("UserName")
+                        .HasMaxLength(256);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Email");
+
+                    b.HasIndex("NormalizedEmail");
+
+                    b.HasIndex("NormalizedUserName");
+
+                    b.HasIndex("UserName");
+
+                    b.ToTable("AbpUsers");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ClaimType")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("ClaimValue")
+                        .HasMaxLength(1024);
+
+                    b.Property("TenantId");
+
+                    b.Property("UserId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("AbpUserClaims");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
+                {
+                    b.Property("UserId");
+
+                    b.Property("LoginProvider")
+                        .HasMaxLength(64);
+
+                    b.Property("ProviderDisplayName")
+                        .HasMaxLength(128);
+
+                    b.Property("ProviderKey")
+                        .IsRequired()
+                        .HasMaxLength(196);
+
+                    b.Property("TenantId");
+
+                    b.HasKey("UserId", "LoginProvider");
+
+                    b.HasIndex("LoginProvider", "ProviderKey");
+
+                    b.ToTable("AbpUserLogins");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
+                {
+                    b.Property("UserId");
+
+                    b.Property("RoleId");
+
+                    b.Property("TenantId");
+
+                    b.HasKey("UserId", "RoleId");
+
+                    b.HasIndex("RoleId", "UserId");
+
+                    b.ToTable("AbpUserRoles");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
+                {
+                    b.Property("UserId");
+
+                    b.Property("LoginProvider")
+                        .HasMaxLength(64);
+
+                    b.Property("Name")
+                        .HasMaxLength(128);
+
+                    b.Property("TenantId");
+
+                    b.Property("Value");
+
+                    b.HasKey("UserId", "LoginProvider", "Name");
+
+                    b.ToTable("AbpUserTokens");
+                });
+
+            modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("ProviderKey")
+                        .IsRequired()
+                        .HasMaxLength(64);
+
+                    b.Property("ProviderName")
+                        .IsRequired()
+                        .HasMaxLength(64);
+
+                    b.Property("TenantId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name", "ProviderName", "ProviderKey");
+
+                    b.ToTable("AbpPermissionGrants");
+                });
+
+            modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("ProviderKey")
+                        .HasMaxLength(64);
+
+                    b.Property("ProviderName")
+                        .HasMaxLength(64);
+
+                    b.Property("Value")
+                        .IsRequired()
+                        .HasMaxLength(2048);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name", "ProviderName", "ProviderKey");
+
+                    b.ToTable("AbpSettings");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("Description")
+                        .HasColumnName("Description")
+                        .HasMaxLength(1024);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasColumnName("Name")
+                        .HasMaxLength(256);
+
+                    b.Property("ShortName")
+                        .IsRequired()
+                        .HasColumnName("ShortName")
+                        .HasMaxLength(32);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BlgBlogs");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("PostId")
+                        .HasColumnName("PostId");
+
+                    b.Property("RepliedCommentId")
+                        .HasColumnName("RepliedCommentId");
+
+                    b.Property("Text")
+                        .IsRequired()
+                        .HasColumnName("Text")
+                        .HasMaxLength(1024);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("PostId");
+
+                    b.HasIndex("RepliedCommentId");
+
+                    b.ToTable("BlgComments");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("BlogId")
+                        .HasColumnName("BlogId");
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("Content")
+                        .HasColumnName("Content")
+                        .HasMaxLength(1048576);
+
+                    b.Property("CoverImage")
+                        .IsRequired()
+                        .HasColumnName("CoverImage");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("ReadCount");
+
+                    b.Property("Title")
+                        .IsRequired()
+                        .HasColumnName("Title")
+                        .HasMaxLength(512);
+
+                    b.Property("Url")
+                        .IsRequired()
+                        .HasColumnName("Url")
+                        .HasMaxLength(64);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("BlogId");
+
+                    b.ToTable("BlgPosts");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
+                {
+                    b.Property("PostId")
+                        .HasColumnName("PostId");
+
+                    b.Property("TagId")
+                        .HasColumnName("TagId");
+
+                    b.Property("CreationTime");
+
+                    b.Property("CreatorId");
+
+                    b.HasKey("PostId", "TagId");
+
+                    b.HasIndex("TagId");
+
+                    b.ToTable("BlgPostTags");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("BlogId");
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("Description")
+                        .HasColumnName("Description")
+                        .HasMaxLength(512);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasColumnName("Name")
+                        .HasMaxLength(64);
+
+                    b.Property("UsageCount")
+                        .HasColumnName("UsageCount");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BlgTags");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Users.BlogUser", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("Email")
+                        .HasColumnName("Email")
+                        .HasMaxLength(256);
+
+                    b.Property("EmailConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("EmailConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("Name")
+                        .HasColumnName("Name")
+                        .HasMaxLength(64);
+
+                    b.Property("PhoneNumber")
+                        .HasColumnName("PhoneNumber")
+                        .HasMaxLength(16);
+
+                    b.Property("PhoneNumberConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("PhoneNumberConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("Surname")
+                        .HasColumnName("Surname")
+                        .HasMaxLength(64);
+
+                    b.Property("TenantId")
+                        .HasColumnName("TenantId");
+
+                    b.Property("UserName")
+                        .IsRequired()
+                        .HasColumnName("UserName")
+                        .HasMaxLength(256);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BlgUsers");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityRole")
+                        .WithMany("Claims")
+                        .HasForeignKey("RoleId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Claims")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Logins")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityRole")
+                        .WithMany()
+                        .HasForeignKey("RoleId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Roles")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Tokens")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
+                {
+                    b.HasOne("Volo.Blogging.Posts.Post")
+                        .WithMany()
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.HasOne("Volo.Blogging.Comments.Comment")
+                        .WithMany()
+                        .HasForeignKey("RepliedCommentId");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
+                {
+                    b.HasOne("Volo.Blogging.Blogs.Blog")
+                        .WithMany()
+                        .HasForeignKey("BlogId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
+                {
+                    b.HasOne("Volo.Blogging.Posts.Post")
+                        .WithMany("Tags")
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.HasOne("Volo.Blogging.Tagging.Tag")
+                        .WithMany()
+                        .HasForeignKey("TagId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181211141402_AggregateRoot_Changes.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181211141402_AggregateRoot_Changes.cs
new file mode 100644
index 0000000000..561adcbf78
--- /dev/null
+++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181211141402_AggregateRoot_Changes.cs
@@ -0,0 +1,103 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
+{
+    public partial class AggregateRoot_Changes : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgUsers",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgTags",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "BlgTags",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgPosts",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "BlgPosts",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgComments",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "BlgComments",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgBlogs",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "BlgBlogs",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "AbpRoles",
+                nullable: true);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgUsers");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgTags");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "BlgTags");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgPosts");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "BlgPosts");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgComments");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "BlgComments");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgBlogs");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "BlgBlogs");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "AbpRoles");
+        }
+    }
+}
diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs
index b8f0d22220..fda99109a6 100644
--- a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs
+++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs
@@ -55,6 +55,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
 
                     b.Property("ConcurrencyStamp");
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDefault")
                         .HasColumnName("IsDefault");
 
@@ -350,6 +353,8 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
                     b.Property("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("CreationTime")
                         .HasColumnName("CreationTime");
 
@@ -366,6 +371,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
                         .HasColumnName("Description")
                         .HasMaxLength(1024);
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDeleted")
                         .ValueGeneratedOnAdd()
                         .HasColumnName("IsDeleted")
@@ -397,6 +405,8 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
                     b.Property("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("CreationTime")
                         .HasColumnName("CreationTime");
 
@@ -409,6 +419,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
                     b.Property("DeletionTime")
                         .HasColumnName("DeletionTime");
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDeleted")
                         .ValueGeneratedOnAdd()
                         .HasColumnName("IsDeleted")
@@ -448,6 +461,8 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
                     b.Property("BlogId")
                         .HasColumnName("BlogId");
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("Content")
                         .HasColumnName("Content")
                         .HasMaxLength(1048576);
@@ -468,6 +483,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
                     b.Property("DeletionTime")
                         .HasColumnName("DeletionTime");
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDeleted")
                         .ValueGeneratedOnAdd()
                         .HasColumnName("IsDeleted")
@@ -524,6 +542,8 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
 
                     b.Property("BlogId");
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("CreationTime")
                         .HasColumnName("CreationTime");
 
@@ -540,6 +560,9 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
                         .HasColumnName("Description")
                         .HasMaxLength(512);
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDeleted")
                         .ValueGeneratedOnAdd()
                         .HasColumnName("IsDeleted")
@@ -569,6 +592,8 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
                     b.Property("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("Email")
                         .HasColumnName("Email")
                         .HasMaxLength(256);
diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs
index 529c6b3e6f..7b7728c0f7 100644
--- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs
+++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs
@@ -36,6 +36,7 @@ namespace Volo.Blogging.EntityFrameworkCore
                 b.ToTable(options.TablePrefix + "Blogs", options.Schema);
 
                 b.ConfigureFullAudited();
+                b.ConfigureExtraProperties();
 
                 b.Property(x => x.Name).IsRequired().HasMaxLength(BlogConsts.MaxNameLength).HasColumnName(nameof(Blog.Name));
                 b.Property(x => x.ShortName).IsRequired().HasMaxLength(BlogConsts.MaxShortNameLength).HasColumnName(nameof(Blog.ShortName));
@@ -47,7 +48,8 @@ namespace Volo.Blogging.EntityFrameworkCore
                 b.ToTable(options.TablePrefix + "Posts", options.Schema);
 
                 b.ConfigureFullAudited();
-                
+                b.ConfigureExtraProperties();
+
                 b.Property(x => x.BlogId).HasColumnName(nameof(Post.BlogId));
                 b.Property(x => x.Title).IsRequired().HasMaxLength(PostConsts.MaxTitleLength).HasColumnName(nameof(Post.Title));
                 b.Property(x => x.CoverImage).IsRequired().HasColumnName(nameof(Post.CoverImage));
@@ -64,7 +66,8 @@ namespace Volo.Blogging.EntityFrameworkCore
                 b.ToTable(options.TablePrefix + "Comments", options.Schema);
 
                 b.ConfigureFullAudited();
-                
+                b.ConfigureExtraProperties();
+
                 b.Property(x => x.Text).IsRequired().HasMaxLength(CommentConsts.MaxTextLength).HasColumnName(nameof(Comment.Text));
                 b.Property(x => x.RepliedCommentId).HasColumnName(nameof(Comment.RepliedCommentId));
                 b.Property(x => x.PostId).IsRequired().HasColumnName(nameof(Comment.PostId));
@@ -78,7 +81,8 @@ namespace Volo.Blogging.EntityFrameworkCore
                 b.ToTable(options.TablePrefix + "Tags", options.Schema);
 
                 b.ConfigureFullAudited();
-                
+                b.ConfigureExtraProperties();
+
                 b.Property(x => x.Name).IsRequired().HasMaxLength(TagConsts.MaxNameLength).HasColumnName(nameof(Tag.Name));
                 b.Property(x => x.Description).HasMaxLength(TagConsts.MaxDescriptionLength).HasColumnName(nameof(Tag.Description));
                 b.Property(x => x.UsageCount).HasColumnName(nameof(Tag.UsageCount));
diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/AbpBloggingBsonClassMap.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/AbpBloggingBsonClassMap.cs
index 4ff5d387d3..589b96b765 100644
--- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/AbpBloggingBsonClassMap.cs
+++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/MongoDB/AbpBloggingBsonClassMap.cs
@@ -1,9 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using MongoDB.Bson.Serialization;
+using MongoDB.Bson.Serialization;
 using Volo.Abp.MongoDB;
 using Volo.Abp.Threading;
+using Volo.Blogging.Blogs;
+using Volo.Blogging.Comments;
+using Volo.Blogging.Posts;
+using Volo.Blogging.Tagging;
 using Volo.Blogging.Users;
 
 namespace Volo.Blogging.MongoDB
@@ -21,6 +22,26 @@ namespace Volo.Blogging.MongoDB
                     map.AutoMap();
                     map.ConfigureExtraProperties();
                 });
+                BsonClassMap.RegisterClassMap(map =>
+                {
+                    map.AutoMap();
+                    map.ConfigureExtraProperties();
+                });
+                BsonClassMap.RegisterClassMap(map =>
+                {
+                    map.AutoMap();
+                    map.ConfigureExtraProperties();
+                });
+                BsonClassMap.RegisterClassMap(map =>
+                {
+                    map.AutoMap();
+                    map.ConfigureExtraProperties();
+                });
+                BsonClassMap.RegisterClassMap(map =>
+                {
+                    map.AutoMap();
+                    map.ConfigureExtraProperties();
+                });
             });
         }
     }
diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181211141818_AggregateRoot_Changes.Designer.cs b/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181211141818_AggregateRoot_Changes.Designer.cs
new file mode 100644
index 0000000000..3465acc006
--- /dev/null
+++ b/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181211141818_AggregateRoot_Changes.Designer.cs
@@ -0,0 +1,68 @@
+// 
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Volo.DocsTestApp.EntityFrameworkCore;
+
+namespace Volo.DocsTestApp.EntityFrameworkCore.Migrations
+{
+    [DbContext(typeof(DocsTestAppDbContext))]
+    [Migration("20181211141818_AggregateRoot_Changes")]
+    partial class AggregateRoot_Changes
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "2.1.1-rtm-30846")
+                .HasAnnotation("Relational:MaxIdentifierLength", 128)
+                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+            modelBuilder.Entity("Volo.Docs.Projects.Project", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("DefaultDocumentName")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("DocumentStoreType");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("Format");
+
+                    b.Property("LatestVersionBranchName")
+                        .HasMaxLength(128);
+
+                    b.Property("MainWebsiteUrl");
+
+                    b.Property("MinimumVersion");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("NavigationDocumentName")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("ShortName")
+                        .IsRequired()
+                        .HasMaxLength(32);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("DocsProjects");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181211141818_AggregateRoot_Changes.cs b/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181211141818_AggregateRoot_Changes.cs
new file mode 100644
index 0000000000..cfc39411b1
--- /dev/null
+++ b/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181211141818_AggregateRoot_Changes.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Volo.DocsTestApp.EntityFrameworkCore.Migrations
+{
+    public partial class AggregateRoot_Changes : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "DocsProjects",
+                nullable: true);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "DocsProjects");
+        }
+    }
+}
diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/DocsTestAppDbContextModelSnapshot.cs b/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/DocsTestAppDbContextModelSnapshot.cs
index 9c1f4f448c..a568d3ef13 100644
--- a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/DocsTestAppDbContextModelSnapshot.cs
+++ b/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/DocsTestAppDbContextModelSnapshot.cs
@@ -24,6 +24,8 @@ namespace Volo.DocsTestApp.EntityFrameworkCore.Migrations
                     b.Property("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("DefaultDocumentName")
                         .IsRequired()
                         .HasMaxLength(128);
diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Project.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Project.cs
index b5c5c784f0..7472ace4e3 100644
--- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Project.cs
+++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Project.cs
@@ -7,7 +7,7 @@ using Volo.Abp.Domain.Entities;
 
 namespace Volo.Docs.Projects
 {
-    public class Project : AggregateRoot, IHasExtraProperties
+    public class Project : AggregateRoot
     {
         /// 
         /// Name of the project for display purposes.
@@ -41,8 +41,6 @@ namespace Volo.Docs.Projects
         /// 
         public virtual string DocumentStoreType { get; protected set; }
 
-        public virtual Dictionary ExtraProperties { get; protected set; }
-
         public virtual string MainWebsiteUrl { get; set; }
 
         public virtual string LatestVersionBranchName { get; set; }
diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs
index 75fc26421c..1235bf5fb2 100644
--- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs
+++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs
@@ -22,6 +22,8 @@ namespace Volo.Docs.EntityFrameworkCore
             {
                 b.ToTable(options.TablePrefix + "Projects", options.Schema);
 
+                b.ConfigureExtraProperties();
+
                 b.Property(x => x.Name).IsRequired().HasMaxLength(ProjectConsts.MaxNameLength);
                 b.Property(x => x.ShortName).IsRequired().HasMaxLength(ProjectConsts.MaxShortNameLength);
                 b.Property(x => x.DefaultDocumentName).IsRequired().HasMaxLength(ProjectConsts.MaxDefaultDocumentNameLength);
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs
index a6e9522919..efda009d68 100644
--- a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs
+++ b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs
@@ -1,5 +1,6 @@
 using JetBrains.Annotations;
 using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
 using Volo.Abp.IdentityServer.ApiResources;
 using Volo.Abp.IdentityServer.Clients;
 using Volo.Abp.IdentityServer.Grants;
@@ -25,6 +26,8 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
             {
                 client.ToTable(tablePrefix + "Clients", schema);
 
+                client.ConfigureExtraProperties();
+
                 client.Property(x => x.ClientId).HasMaxLength(ClientConsts.ClientIdMaxLength).IsRequired();
                 client.Property(x => x.ProtocolType).HasMaxLength(ClientConsts.ProtocolTypeMaxLength).IsRequired();
                 client.Property(x => x.ClientName).HasMaxLength(ClientConsts.ClientNameMaxLength);
@@ -136,6 +139,8 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
             {
                 grant.ToTable(tablePrefix + "PersistedGrants", schema);
 
+                grant.ConfigureExtraProperties();
+
                 grant.Property(x => x.Key).HasMaxLength(PersistedGrantConsts.KeyMaxLength).ValueGeneratedNever();
                 grant.Property(x => x.Type).HasMaxLength(PersistedGrantConsts.TypeMaxLength).IsRequired();
                 grant.Property(x => x.SubjectId).HasMaxLength(PersistedGrantConsts.SubjectIdMaxLength);
@@ -152,6 +157,8 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
             {
                 identityResource.ToTable(tablePrefix + "IdentityResources", schema);
 
+                identityResource.ConfigureExtraProperties();
+
                 identityResource.Property(x => x.Name).HasMaxLength(IdentityResourceConsts.NameMaxLength).IsRequired();
                 identityResource.Property(x => x.DisplayName).HasMaxLength(IdentityResourceConsts.DisplayNameMaxLength);
                 identityResource.Property(x => x.Description).HasMaxLength(IdentityResourceConsts.DescriptionMaxLength);
@@ -172,6 +179,8 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
             {
                 apiResource.ToTable(tablePrefix + "ApiResources", schema);
 
+                apiResource.ConfigureExtraProperties();
+
                 apiResource.Property(x => x.Name).HasMaxLength(ApiResourceConsts.NameMaxLength).IsRequired();
                 apiResource.Property(x => x.DisplayName).HasMaxLength(ApiResourceConsts.DisplayNameMaxLength);
                 apiResource.Property(x => x.Description).HasMaxLength(ApiResourceConsts.DescriptionMaxLength);
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerBsonClassMap.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerBsonClassMap.cs
index f55ad596c8..5128aee20a 100644
--- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerBsonClassMap.cs
+++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerBsonClassMap.cs
@@ -3,6 +3,7 @@ using Volo.Abp.IdentityServer.ApiResources;
 using Volo.Abp.IdentityServer.Clients;
 using Volo.Abp.IdentityServer.Grants;
 using Volo.Abp.IdentityServer.IdentityResources;
+using Volo.Abp.MongoDB;
 using Volo.Abp.Threading;
 
 namespace Volo.Abp.IdentityServer.MongoDB
@@ -18,18 +19,22 @@ namespace Volo.Abp.IdentityServer.MongoDB
                 BsonClassMap.RegisterClassMap(map =>
                 {
                     map.AutoMap();
+                    map.ConfigureExtraProperties();
                 });
                 BsonClassMap.RegisterClassMap(map =>
                 {
                     map.AutoMap();
+                    map.ConfigureExtraProperties();
                 });
                 BsonClassMap.RegisterClassMap(map =>
                 {
                     map.AutoMap();
+                    map.ConfigureExtraProperties();
                 });
                 BsonClassMap.RegisterClassMap(map =>
                 {
                     map.AutoMap();
+                    map.ConfigureExtraProperties();
                 });
             });
         }
diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs
index 7c70746816..d9da76e254 100644
--- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs
+++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs
@@ -7,14 +7,12 @@ using Volo.Abp.Domain.Entities;
 
 namespace Volo.Abp.TenantManagement
 {
-    public class Tenant : AggregateRoot, IHasExtraProperties
+    public class Tenant : AggregateRoot
     {
         public virtual string Name { get; protected set; }
 
         public virtual List ConnectionStrings { get; protected set; }
 
-        public Dictionary ExtraProperties { get; }
-
         protected Tenant()
         {
             ExtraProperties = new Dictionary();
diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs
index 636692cf56..0022ee8475 100644
--- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs
+++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs
@@ -1,5 +1,6 @@
 using JetBrains.Annotations;
 using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
 
 namespace Volo.Abp.TenantManagement.EntityFrameworkCore
 {
@@ -21,6 +22,8 @@ namespace Volo.Abp.TenantManagement.EntityFrameworkCore
             {
                 b.ToTable(tablePrefix + "Tenants", schema);
 
+                b.ConfigureExtraProperties();
+
                 b.Property(t => t.Name).IsRequired().HasMaxLength(TenantConsts.MaxNameLength);
 
                 b.HasMany(u => u.ConnectionStrings).WithOne().HasForeignKey(uc => uc.TenantId).IsRequired();

From 66ed2f034c7bf91ce0417ffd077f902acad28413 Mon Sep 17 00:00:00 2001
From: Yunus Emre Kalkan 
Date: Wed, 12 Dec 2018 09:01:14 +0300
Subject: [PATCH 22/36] Abp web site AggregateRoot changes

---
 ...12060034_AggregateRoot_Changes.Designer.cs | 800 ++++++++++++++++++
 .../20181212060034_AggregateRoot_Changes.cs   | 130 +++
 .../AbpWebSiteDbContextModelSnapshot.cs       |  33 +
 .../AbpWebSiteDbContext.cs                    |   3 +
 4 files changed, 966 insertions(+)
 create mode 100644 abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181212060034_AggregateRoot_Changes.Designer.cs
 create mode 100644 abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181212060034_AggregateRoot_Changes.cs

diff --git a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181212060034_AggregateRoot_Changes.Designer.cs b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181212060034_AggregateRoot_Changes.Designer.cs
new file mode 100644
index 0000000000..4fa460df1e
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181212060034_AggregateRoot_Changes.Designer.cs
@@ -0,0 +1,800 @@
+// 
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Volo.AbpWebSite.EntityFrameworkCore;
+
+namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
+{
+    [DbContext(typeof(AbpWebSiteDbContext))]
+    [Migration("20181212060034_AggregateRoot_Changes")]
+    partial class AggregateRoot_Changes
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "2.1.1-rtm-30846")
+                .HasAnnotation("Relational:MaxIdentifierLength", 128)
+                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Description")
+                        .HasMaxLength(256);
+
+                    b.Property("IsStatic");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("Regex")
+                        .HasMaxLength(512);
+
+                    b.Property("RegexDescription")
+                        .HasMaxLength(128);
+
+                    b.Property("Required");
+
+                    b.Property("ValueType");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("AbpClaimTypes");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDefault")
+                        .HasColumnName("IsDefault");
+
+                    b.Property("IsPublic")
+                        .HasColumnName("IsPublic");
+
+                    b.Property("IsStatic")
+                        .HasColumnName("IsStatic");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("NormalizedName")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("TenantId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("NormalizedName");
+
+                    b.ToTable("AbpRoles");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ClaimType")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("ClaimValue")
+                        .HasMaxLength(1024);
+
+                    b.Property("RoleId");
+
+                    b.Property("TenantId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("RoleId");
+
+                    b.ToTable("AbpRoleClaims");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("AccessFailedCount")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("AccessFailedCount")
+                        .HasDefaultValue(0);
+
+                    b.Property("ConcurrencyStamp")
+                        .IsRequired()
+                        .HasColumnName("ConcurrencyStamp")
+                        .HasMaxLength(256);
+
+                    b.Property("CreationTime");
+
+                    b.Property("CreatorId");
+
+                    b.Property("DeleterId");
+
+                    b.Property("DeletionTime");
+
+                    b.Property("Email")
+                        .HasColumnName("Email")
+                        .HasMaxLength(256);
+
+                    b.Property("EmailConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("EmailConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted");
+
+                    b.Property("LastModificationTime");
+
+                    b.Property("LastModifierId");
+
+                    b.Property("LockoutEnabled")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("LockoutEnabled")
+                        .HasDefaultValue(false);
+
+                    b.Property("LockoutEnd");
+
+                    b.Property("Name")
+                        .HasColumnName("Name")
+                        .HasMaxLength(64);
+
+                    b.Property("NormalizedEmail")
+                        .HasColumnName("NormalizedEmail")
+                        .HasMaxLength(256);
+
+                    b.Property("NormalizedUserName")
+                        .IsRequired()
+                        .HasColumnName("NormalizedUserName")
+                        .HasMaxLength(256);
+
+                    b.Property("PasswordHash")
+                        .HasColumnName("PasswordHash")
+                        .HasMaxLength(256);
+
+                    b.Property("PhoneNumber")
+                        .HasColumnName("PhoneNumber")
+                        .HasMaxLength(16);
+
+                    b.Property("PhoneNumberConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("PhoneNumberConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("SecurityStamp")
+                        .IsRequired()
+                        .HasColumnName("SecurityStamp")
+                        .HasMaxLength(256);
+
+                    b.Property("Surname")
+                        .HasColumnName("Surname")
+                        .HasMaxLength(64);
+
+                    b.Property("TenantId")
+                        .HasColumnName("TenantId");
+
+                    b.Property("TwoFactorEnabled")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("TwoFactorEnabled")
+                        .HasDefaultValue(false);
+
+                    b.Property("UserName")
+                        .IsRequired()
+                        .HasColumnName("UserName")
+                        .HasMaxLength(256);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Email");
+
+                    b.HasIndex("NormalizedEmail");
+
+                    b.HasIndex("NormalizedUserName");
+
+                    b.HasIndex("UserName");
+
+                    b.ToTable("AbpUsers");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ClaimType")
+                        .IsRequired()
+                        .HasMaxLength(256);
+
+                    b.Property("ClaimValue")
+                        .HasMaxLength(1024);
+
+                    b.Property("TenantId");
+
+                    b.Property("UserId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("AbpUserClaims");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
+                {
+                    b.Property("UserId");
+
+                    b.Property("LoginProvider")
+                        .HasMaxLength(64);
+
+                    b.Property("ProviderDisplayName")
+                        .HasMaxLength(128);
+
+                    b.Property("ProviderKey")
+                        .IsRequired()
+                        .HasMaxLength(196);
+
+                    b.Property("TenantId");
+
+                    b.HasKey("UserId", "LoginProvider");
+
+                    b.HasIndex("LoginProvider", "ProviderKey");
+
+                    b.ToTable("AbpUserLogins");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
+                {
+                    b.Property("UserId");
+
+                    b.Property("RoleId");
+
+                    b.Property("TenantId");
+
+                    b.HasKey("UserId", "RoleId");
+
+                    b.HasIndex("RoleId", "UserId");
+
+                    b.ToTable("AbpUserRoles");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
+                {
+                    b.Property("UserId");
+
+                    b.Property("LoginProvider")
+                        .HasMaxLength(64);
+
+                    b.Property("Name")
+                        .HasMaxLength(128);
+
+                    b.Property("TenantId");
+
+                    b.Property("Value");
+
+                    b.HasKey("UserId", "LoginProvider", "Name");
+
+                    b.ToTable("AbpUserTokens");
+                });
+
+            modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("ProviderKey")
+                        .IsRequired()
+                        .HasMaxLength(64);
+
+                    b.Property("ProviderName")
+                        .IsRequired()
+                        .HasMaxLength(64);
+
+                    b.Property("TenantId");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name", "ProviderName", "ProviderKey");
+
+                    b.ToTable("AbpPermissionGrants");
+                });
+
+            modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("ProviderKey")
+                        .HasMaxLength(64);
+
+                    b.Property("ProviderName")
+                        .HasMaxLength(64);
+
+                    b.Property("Value")
+                        .IsRequired()
+                        .HasMaxLength(2048);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name", "ProviderName", "ProviderKey");
+
+                    b.ToTable("AbpSettings");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("Description")
+                        .HasColumnName("Description")
+                        .HasMaxLength(1024);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasColumnName("Name")
+                        .HasMaxLength(256);
+
+                    b.Property("ShortName")
+                        .IsRequired()
+                        .HasColumnName("ShortName")
+                        .HasMaxLength(32);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BlgBlogs");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("PostId")
+                        .HasColumnName("PostId");
+
+                    b.Property("RepliedCommentId")
+                        .HasColumnName("RepliedCommentId");
+
+                    b.Property("Text")
+                        .IsRequired()
+                        .HasColumnName("Text")
+                        .HasMaxLength(1024);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("PostId");
+
+                    b.HasIndex("RepliedCommentId");
+
+                    b.ToTable("BlgComments");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("BlogId")
+                        .HasColumnName("BlogId");
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("Content")
+                        .HasColumnName("Content")
+                        .HasMaxLength(1048576);
+
+                    b.Property("CoverImage")
+                        .IsRequired()
+                        .HasColumnName("CoverImage");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("ReadCount");
+
+                    b.Property("Title")
+                        .IsRequired()
+                        .HasColumnName("Title")
+                        .HasMaxLength(512);
+
+                    b.Property("Url")
+                        .IsRequired()
+                        .HasColumnName("Url")
+                        .HasMaxLength(64);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("BlogId");
+
+                    b.ToTable("BlgPosts");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
+                {
+                    b.Property("PostId")
+                        .HasColumnName("PostId");
+
+                    b.Property("TagId")
+                        .HasColumnName("TagId");
+
+                    b.Property("CreationTime");
+
+                    b.Property("CreatorId");
+
+                    b.HasKey("PostId", "TagId");
+
+                    b.HasIndex("TagId");
+
+                    b.ToTable("BlgPostTags");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("BlogId");
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("CreationTime")
+                        .HasColumnName("CreationTime");
+
+                    b.Property("CreatorId")
+                        .HasColumnName("CreatorId");
+
+                    b.Property("DeleterId")
+                        .HasColumnName("DeleterId");
+
+                    b.Property("DeletionTime")
+                        .HasColumnName("DeletionTime");
+
+                    b.Property("Description")
+                        .HasColumnName("Description")
+                        .HasMaxLength(512);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("IsDeleted")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("IsDeleted")
+                        .HasDefaultValue(false);
+
+                    b.Property("LastModificationTime")
+                        .HasColumnName("LastModificationTime");
+
+                    b.Property("LastModifierId")
+                        .HasColumnName("LastModifierId");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasColumnName("Name")
+                        .HasMaxLength(64);
+
+                    b.Property("UsageCount")
+                        .HasColumnName("UsageCount");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BlgTags");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Users.BlogUser", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("Email")
+                        .HasColumnName("Email")
+                        .HasMaxLength(256);
+
+                    b.Property("EmailConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("EmailConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("Name")
+                        .HasColumnName("Name")
+                        .HasMaxLength(64);
+
+                    b.Property("PhoneNumber")
+                        .HasColumnName("PhoneNumber")
+                        .HasMaxLength(16);
+
+                    b.Property("PhoneNumberConfirmed")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnName("PhoneNumberConfirmed")
+                        .HasDefaultValue(false);
+
+                    b.Property("Surname")
+                        .HasColumnName("Surname")
+                        .HasMaxLength(64);
+
+                    b.Property("TenantId")
+                        .HasColumnName("TenantId");
+
+                    b.Property("UserName")
+                        .IsRequired()
+                        .HasColumnName("UserName")
+                        .HasMaxLength(256);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BlgUsers");
+                });
+
+            modelBuilder.Entity("Volo.Docs.Projects.Project", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property("ConcurrencyStamp");
+
+                    b.Property("DefaultDocumentName")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("DocumentStoreType");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("Format");
+
+                    b.Property("LatestVersionBranchName")
+                        .HasMaxLength(128);
+
+                    b.Property("MainWebsiteUrl");
+
+                    b.Property("MinimumVersion");
+
+                    b.Property("Name")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("NavigationDocumentName")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("ShortName")
+                        .IsRequired()
+                        .HasMaxLength(32);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("DocsProjects");
+                });
+
+            modelBuilder.Entity("Volo.Utils.SolutionTemplating.DownloadInfo", b =>
+                {
+                    b.Property("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+                    b.Property("ConcurrencyStamp")
+                        .IsConcurrencyToken();
+
+                    b.Property("CreationDuration");
+
+                    b.Property("CreationTime");
+
+                    b.Property("CreatorId");
+
+                    b.Property("DatabaseProvider");
+
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
+                    b.Property("ProjectName")
+                        .IsRequired()
+                        .HasMaxLength(128);
+
+                    b.Property("TemplateName")
+                        .IsRequired()
+                        .HasMaxLength(42);
+
+                    b.Property("Version")
+                        .IsRequired()
+                        .HasMaxLength(20);
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Downloads");
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityRole")
+                        .WithMany("Claims")
+                        .HasForeignKey("RoleId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Claims")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Logins")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityRole")
+                        .WithMany()
+                        .HasForeignKey("RoleId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Roles")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
+                {
+                    b.HasOne("Volo.Abp.Identity.IdentityUser")
+                        .WithMany("Tokens")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Comments.Comment", b =>
+                {
+                    b.HasOne("Volo.Blogging.Posts.Post")
+                        .WithMany()
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.HasOne("Volo.Blogging.Comments.Comment")
+                        .WithMany()
+                        .HasForeignKey("RepliedCommentId");
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.Post", b =>
+                {
+                    b.HasOne("Volo.Blogging.Blogs.Blog")
+                        .WithMany()
+                        .HasForeignKey("BlogId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b =>
+                {
+                    b.HasOne("Volo.Blogging.Posts.Post")
+                        .WithMany("Tags")
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.HasOne("Volo.Blogging.Tagging.Tag")
+                        .WithMany()
+                        .HasForeignKey("TagId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181212060034_AggregateRoot_Changes.cs b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181212060034_AggregateRoot_Changes.cs
new file mode 100644
index 0000000000..4e2b72996d
--- /dev/null
+++ b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/20181212060034_AggregateRoot_Changes.cs
@@ -0,0 +1,130 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
+{
+    public partial class AggregateRoot_Changes : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "Downloads",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "Downloads",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "DocsProjects",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgUsers",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgTags",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "BlgTags",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgPosts",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "BlgPosts",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgComments",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "BlgComments",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgBlogs",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "BlgBlogs",
+                nullable: true);
+
+            migrationBuilder.AddColumn(
+                name: "ExtraProperties",
+                table: "AbpRoles",
+                nullable: true);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "Downloads");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "Downloads");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "DocsProjects");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgUsers");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgTags");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "BlgTags");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgPosts");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "BlgPosts");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgComments");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "BlgComments");
+
+            migrationBuilder.DropColumn(
+                name: "ConcurrencyStamp",
+                table: "BlgBlogs");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "BlgBlogs");
+
+            migrationBuilder.DropColumn(
+                name: "ExtraProperties",
+                table: "AbpRoles");
+        }
+    }
+}
diff --git a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/AbpWebSiteDbContextModelSnapshot.cs b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/AbpWebSiteDbContextModelSnapshot.cs
index 4ec11d491e..f1af866317 100644
--- a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/AbpWebSiteDbContextModelSnapshot.cs
+++ b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Migrations/AbpWebSiteDbContextModelSnapshot.cs
@@ -55,6 +55,9 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
 
                     b.Property("ConcurrencyStamp");
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDefault")
                         .HasColumnName("IsDefault");
 
@@ -350,6 +353,8 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                     b.Property("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("CreationTime")
                         .HasColumnName("CreationTime");
 
@@ -366,6 +371,9 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                         .HasColumnName("Description")
                         .HasMaxLength(1024);
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDeleted")
                         .ValueGeneratedOnAdd()
                         .HasColumnName("IsDeleted")
@@ -397,6 +405,8 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                     b.Property("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("CreationTime")
                         .HasColumnName("CreationTime");
 
@@ -409,6 +419,9 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                     b.Property("DeletionTime")
                         .HasColumnName("DeletionTime");
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDeleted")
                         .ValueGeneratedOnAdd()
                         .HasColumnName("IsDeleted")
@@ -448,6 +461,8 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                     b.Property("BlogId")
                         .HasColumnName("BlogId");
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("Content")
                         .HasColumnName("Content")
                         .HasMaxLength(1048576);
@@ -468,6 +483,9 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                     b.Property("DeletionTime")
                         .HasColumnName("DeletionTime");
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDeleted")
                         .ValueGeneratedOnAdd()
                         .HasColumnName("IsDeleted")
@@ -524,6 +542,8 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
 
                     b.Property("BlogId");
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("CreationTime")
                         .HasColumnName("CreationTime");
 
@@ -540,6 +560,9 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                         .HasColumnName("Description")
                         .HasMaxLength(512);
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("IsDeleted")
                         .ValueGeneratedOnAdd()
                         .HasColumnName("IsDeleted")
@@ -569,6 +592,8 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                     b.Property("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("Email")
                         .HasColumnName("Email")
                         .HasMaxLength(256);
@@ -616,6 +641,8 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                     b.Property("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property("ConcurrencyStamp");
+
                     b.Property("DefaultDocumentName")
                         .IsRequired()
                         .HasMaxLength(128);
@@ -657,6 +684,9 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
                         .ValueGeneratedOnAdd()
                         .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 
+                    b.Property("ConcurrencyStamp")
+                        .IsConcurrencyToken();
+
                     b.Property("CreationDuration");
 
                     b.Property("CreationTime");
@@ -665,6 +695,9 @@ namespace Volo.AbpWebSite.EntityFrameworkCore.Migrations
 
                     b.Property("DatabaseProvider");
 
+                    b.Property("ExtraProperties")
+                        .HasColumnName("ExtraProperties");
+
                     b.Property("ProjectName")
                         .IsRequired()
                         .HasMaxLength(128);
diff --git a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Volo/AbpWebSite/EntityFrameworkCore/AbpWebSiteDbContext.cs b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Volo/AbpWebSite/EntityFrameworkCore/AbpWebSiteDbContext.cs
index 0167e55d03..4bc8f010ec 100644
--- a/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Volo/AbpWebSite/EntityFrameworkCore/AbpWebSiteDbContext.cs
+++ b/abp_io/src/Volo.AbpWebSite.EntityFrameworkCore/Volo/AbpWebSite/EntityFrameworkCore/AbpWebSiteDbContext.cs
@@ -1,5 +1,6 @@
 using Microsoft.EntityFrameworkCore;
 using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
 using Volo.Abp.Identity.EntityFrameworkCore;
 using Volo.Abp.PermissionManagement.EntityFrameworkCore;
 using Volo.Abp.SettingManagement.EntityFrameworkCore;
@@ -23,6 +24,8 @@ namespace Volo.AbpWebSite.EntityFrameworkCore
         {
             base.OnModelCreating(modelBuilder);
 
+            modelBuilder.Entity(b => b.ConfigureExtraProperties());
+
             modelBuilder.ConfigurePermissionManagement();
             modelBuilder.ConfigureSettingManagement();
             modelBuilder.ConfigureIdentity();

From c083f7f326d828255d91c9c78e083d47a1ae3f41 Mon Sep 17 00:00:00 2001
From: Yunus Emre Kalkan 
Date: Wed, 12 Dec 2018 10:01:36 +0300
Subject: [PATCH 23/36] abp-button tag helper improvmenets

---
 .../TagHelpers/Button/AbpButtonSize.cs        |  1 +
 .../Button/AbpButtonSizeExtensions.cs         |  2 ++
 .../TagHelpers/Button/AbpButtonTagHelper.cs   |  2 ++
 .../Button/AbpButtonTagHelperServiceBase.cs   |  5 ++++
 .../Button/AbpLinkButtonTagHelper.cs          |  2 ++
 .../TagHelpers/Button/IButtonTagHelperBase.cs |  2 ++
 .../Pages/Components/Buttons.cshtml           | 24 ++++++++++++++++---
 7 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSize.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSize.cs
index 40a1b4ea26..65a0842d7b 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSize.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSize.cs
@@ -4,6 +4,7 @@
     {
         Default,
         Small,
+        Medium,
         Large
     }
 }
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSizeExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSizeExtensions.cs
index 79ec7c0d10..4231ac7ba6 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSizeExtensions.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSizeExtensions.cs
@@ -8,6 +8,8 @@
             {
                 case AbpButtonSize.Small:
                     return "btn-sm";
+                case AbpButtonSize.Medium:
+                    return "btn-md";
                 case AbpButtonSize.Large:
                     return "btn-lg";
                 case AbpButtonSize.Default:
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs
index ba13dff54e..1be9524800 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs
@@ -9,6 +9,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
 
         public AbpButtonSize Size { get; set; } = AbpButtonSize.Default;
 
+        public bool? Block { get; set; } = false;
+
         public string BusyText { get; set; }
 
         public string Text { get; set; }
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs
index f4d5d33325..3d8a3bf4e8 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs
@@ -33,6 +33,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
             {
                 output.Attributes.AddClass(TagHelper.Size.ToClassName());
             }
+
+            if (TagHelper.Block ?? false)
+            {
+                output.Attributes.AddClass("btn-block");
+            }
         }
 
         protected virtual void AddIcon(TagHelperContext context, TagHelperOutput output)
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelper.cs
index 08b2ecd41c..8e517ea493 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelper.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelper.cs
@@ -11,6 +11,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
 
         public AbpButtonSize Size { get; set; } = AbpButtonSize.Default;
 
+        public bool? Block { get; set; } = false;
+
         public string Text { get; set; }
 
         public string Icon { get; set; }
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/IButtonTagHelperBase.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/IButtonTagHelperBase.cs
index a0e34b039c..dbe20def2a 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/IButtonTagHelperBase.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/IButtonTagHelperBase.cs
@@ -6,6 +6,8 @@
 
         AbpButtonSize Size { get; }
 
+        bool? Block { get;}
+
         string Text { get; }
 
         string Icon { get; }
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml
index ce2cb2d42d..0525029462 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml
@@ -70,13 +70,31 @@
 
 
- + + + +
+
+
+<abp-button size="Default" text="Default" />
+<abp-button size="Small" text="Small" />
+<abp-button size="Medium" text="Medium" />
+<abp-button size="Large" text="Large" />
+
+
+
+ +

# Example

+ + +
+
+
-<abp-button size="Large" text="Large"/>
-<abp-button size="Small" text="Small"/>
+<abp-button block="true" text="Block" />
 
From 643611c32f8dfe1f9d21cb941dc4501af606b632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=A3=AB=E4=BC=9F?= Date: Wed, 12 Dec 2018 15:41:20 +0800 Subject: [PATCH 24/36] Chinese document synchronization update --- docs/zh-Hans/Background-Jobs-Hangfire.md | 3 + docs/zh-Hans/Background-Jobs-RabbitMq.md | 3 + docs/zh-Hans/Background-Jobs.md | 165 +++++++++++++++++- .../Best-Practices/Application-Services.md | 10 +- .../Best-Practices/Data-Transfer-Objects.md | 3 +- docs/zh-Hans/Emailing.md | 3 + docs/zh-Hans/Index.md | 2 + docs/zh-Hans/Modules/Background-Jobs.md | 3 + docs/zh-Hans/docs-nav.json | 19 ++ 9 files changed, 203 insertions(+), 8 deletions(-) create mode 100644 docs/zh-Hans/Background-Jobs-Hangfire.md create mode 100644 docs/zh-Hans/Background-Jobs-RabbitMq.md create mode 100644 docs/zh-Hans/Emailing.md create mode 100644 docs/zh-Hans/Modules/Background-Jobs.md diff --git a/docs/zh-Hans/Background-Jobs-Hangfire.md b/docs/zh-Hans/Background-Jobs-Hangfire.md new file mode 100644 index 0000000000..5ef9aad32d --- /dev/null +++ b/docs/zh-Hans/Background-Jobs-Hangfire.md @@ -0,0 +1,3 @@ +# Hangfire Background Job Manager + +待添加 \ No newline at end of file diff --git a/docs/zh-Hans/Background-Jobs-RabbitMq.md b/docs/zh-Hans/Background-Jobs-RabbitMq.md new file mode 100644 index 0000000000..979beec872 --- /dev/null +++ b/docs/zh-Hans/Background-Jobs-RabbitMq.md @@ -0,0 +1,3 @@ +# RabbitMQ Background Job Manager + +待添加 \ No newline at end of file diff --git a/docs/zh-Hans/Background-Jobs.md b/docs/zh-Hans/Background-Jobs.md index cfd8cb60b8..c66330f816 100644 --- a/docs/zh-Hans/Background-Jobs.md +++ b/docs/zh-Hans/Background-Jobs.md @@ -1,6 +1,6 @@ -## 后台作业 +# 后台作业 -### 介绍 +## 介绍 后台作业用来在后台里执行应用里的一些任务, 出于几个原因, 你可能需要后台工作, 以下是一些例子: @@ -11,14 +11,167 @@ ABP为后台作业提供了一个**抽象**模块和几个后台作业**实现**. 它具有内置/默认的实现以及与Hangfire和RabbitMQ的集成. -### 抽象模块 +## 抽象模块 -待添加 +ABP为后台作业提供了一个 **abstraction** 模块和 **多个实现**. 它有一个内置/默认实现以及Hangfire与RabbitMQ集成. + +`Volo.Abp.BackgroundJobs.Abstractions` nuget package 提供了创建后台作业和队列作业所需要的服务. 如果你的模块只依赖这个包,那么它可以独立于其实现/集成. + +> `Volo.Abp.BackgroundJobs.Abstractions` package 默认在启动模板中已经安装. ### 创建后台作业 后台作业是一个实现`IBackgroundJob`接口或继承自`BackgroundJob`类的类.`TArgs`是一个简单的C#类, 用于存储作业数据. -在后台发送电子邮件的后台作业例子: +在示例中使用后台作业发送电子邮件,首先定义一个类来存储后台作业的参数 + +````csharp +public class EmailSendingArgs +{ + public string EmailAddress { get; set; } + public string Subject { get; set; } + public string Body { get; set; } +} +```` + +然后创建后台作业类,它使用 `EmailSendingArgs` 对象发送电子邮件: + +````csharp +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Emailing; + +namespace MyProject +{ + public class EmailSendingJob : BackgroundJob + { + private readonly IEmailSender _emailSender; + + public EmailSendingJob(IEmailSender emailSender) + { + _emailSender = emailSender; + } + + public override void Execute(EmailSendingArgs args) + { + _emailSender.Send( + args.EmailAddress, + args.Subject, + args.Body + ); + } + } +} +```` + +这个作业简单的使用了 `IEmailSender` 发送电子邮件 (请参阅 [邮件发送文档](Emailing.md)). + +#### 异常处理 + +后台作业不应该隐藏异常. 如果它抛出一个异常, 在稍后后台作业将会自动重试. 只有在你不想为当前参数重新运行后台作业时才隐藏异常. + +### 队列作业 + +现在, 你可以使用 `IBackgroundJobManager` 服务向队列中添加一个发送电子邮件作业: + +````csharp +public class RegistrationService : ApplicationService +{ + private readonly IBackgroundJobManager _backgroundJobManager; + + public RegistrationService(IBackgroundJobManager backgroundJobManager) + { + _backgroundJobManager = backgroundJobManager; + } + + public async Task RegisterAsync(string userName, string emailAddress, string password) + { + //TODO: 创建一个新用户到数据库中... + + await _backgroundJobManager.EnqueueAsync( + new EmailSendingArgs + { + EmailAddress = emailAddress, + Subject = "You've successfully registered!", + Body = "..." + } + ); + } +} +```` + +刚才我们注入 `IBackgroundJobManager` 服务了并且使用它的 `EnqueueAsync` 方法添加一个新的作业到队列中. + +Enqueue方法接收一些可选参数用于控制后台作业: + +* **priority** 用于控制作业项的优先级. 它接收一个 `BackgroundJobPriority` 类型的枚举,它有 `Low`, `BelowNormal`, `Normal` (默认), `AboveNormal` 和 `Hight` 字段. +* **delay** 用于作业第一次重试之前的等待时间 (`TimeSpan`)类型. + +### 禁用作业执行 + +你可能希望在你的应用程序中禁用后台作业执行. 如果你希望在另一个进程中执行后台作业并在当前进程中禁用它,通常可以使用以下命令. + +使用 `BackgroundJobOptions` 配置作业执行: + +````csharp +[DependsOn(typeof(AbpBackgroundJobsModule))] +public class MyModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsJobExecutionEnabled = false; //禁用作业执行 + }); + } +} +```` + +> 默认后台管理器(见下文)不支持多进程执行相同的作业队列. 所以, 如果你的应用程序中有多个正在运行的实现,并且使用的是默认的后台管理器, 你应该只在一个应用程序实例进程中启用作业队列. + +## 默认后台作业管理器 + +ABP framework 包含一个简单的 `IBackgroundJobManager` 实现; + +- 在**单线程**中**FIFO(先入先出)**. +- **重试**作业执行直到作业**执行成功**或**超时**. 默认作业超时时间是2天. 记录所有异常 . +- 作业执行成功时从存储中(数据库)**删除**作业. 如果超时, 作业会在数据库中被设置为**abandoned**. +- 作业的**重试等待时间会越来越长**. 作业第一次重试等待1分钟, 第二次重试等待2分钟, 第三次重试等待4分钟,以此类推. +- 以固定的时间间隔轮询存储中的作业. 查询作业, 按优先级排序(asc)然后按尝试次数排序(asc). + +> `Volo.Abp.BackgroundJobs` nuget package 包含默认的后台作业管理器并且在默认在启动模板中已经安装. + +### 配置 + +在你的[模块类](Module-Development-Basics.md)中使用 `BackgroundJobWorkerOptions` 配置默认作业管理器. +示例中更改后台作业的的超时时间: + +````csharp +[DependsOn(typeof(AbpBackgroundJobsModule))] +public class MyModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.DefaultTimeout = 864000; //10 days (as seconds) + }); + } +} +```` + +### 数据存储 + +默认的后台作业管理器需要数据存储用来保存和读取作业. 它将 `IBackgroundJobStore` 定义为抽象的. 所以, 如果你想要的话你可以替换它的实现. + +后台作业模块使用各种数据访问提供程序实现 `IBackgroundJobStore`. 参阅 [后台工作模块文档](Modules/Background-Jobs.md). + +> 默认情况下,后台作业模块已经安装到启动模板中,它基于你的ORM/数据访问选项. + +## 集成 + +后台作业系统是可扩展的,你可以使用自己的实现或预先构建的集成更改默认后台作业管理器. + +请参阅预构建的作业管理器备选方案: -待添加 \ No newline at end of file +* [Hangfire 后台作业管理器](Background-Jobs-Hangfire.md) +* [RabbitMQ 后台作业管理器](Background-Jobs-RabbitMq.md) \ No newline at end of file diff --git a/docs/zh-Hans/Best-Practices/Application-Services.md b/docs/zh-Hans/Best-Practices/Application-Services.md index 90f5fd4606..8e9c85d63a 100644 --- a/docs/zh-Hans/Best-Practices/Application-Services.md +++ b/docs/zh-Hans/Best-Practices/Application-Services.md @@ -26,6 +26,7 @@ 示例: ```c# +[Serializable] public class IssueDto : FullAuditedEntityDto { public string Title { get; set; } @@ -34,6 +35,7 @@ public class IssueDto : FullAuditedEntityDto public Collection Labels { get; set; } } +[Serializable] public class IssueLabelDto { public Guid IssueId { get; set; } @@ -54,6 +56,7 @@ public class IssueLabelDto 示例: ````C# +[Serializable] public class IssueWithDetailsDto : FullAuditedEntityDto { public string Title { get; set; } @@ -62,12 +65,14 @@ public class IssueWithDetailsDto : FullAuditedEntityDto public Collection Labels { get; set; } } +[Serializable] public class MilestoneDto : EntityDto { public string Name { get; set; } public bool IsClosed { get; set; } } +[Serializable] public class LabelDto : EntityDto { public string Name { get; set; } @@ -128,6 +133,7 @@ Task CreateAsync(CreateQuestionDto questionDto); 输入**DTO**: ````C# +[Serializable] public class CreateQuestionDto { [Required] @@ -181,11 +187,13 @@ Task VoteAsync(Guid id, VoteType type); * **推荐** 在**应用层**实现应用服务接口. * **推荐** 使用命名约定. 如: 为 `IProductAppService` 接口创建 `ProductAppService` 类. * **推荐** 继承自 `ApplicationService` 基类. +* **推荐** 将所有的公开方法定义为 **virtual**, 以便开发人员继承和覆盖它们. +* **不推荐** 定义 **private** 方法. 应该定义为 **protected virtual**, 这样开发人员可以继承和覆盖它们. #### 使用仓储 * **推荐** 使用专门设计的仓储 (如 `IProductRepository`). -* **不推荐** 使用泛型仓储 (如 `IRepository`). +* **不推荐** 使用泛型仓储 (如 `IRepository`).z` #### 查询数据 diff --git a/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md b/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md index 0a523beb71..e0db48397e 100644 --- a/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md +++ b/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md @@ -4,4 +4,5 @@ * **推荐** 在可能和必要的情况下从预构建的 **基础DTO类** 继承 (如 `EntityDto`, `CreationAuditedEntityDto`, `AuditedEntityDto`, `FullAuditedEntityDto` 等). * **推荐** 定义 **public getter 和 setter** 的DTO成员 . * **推荐** 使用 **data annotations** **验证** service输入DTO的属性. -* **不推荐** 在DTO中添加任何 **逻辑**, 在必要的时候可以实现 `IValidatableObject` 接口. \ No newline at end of file +* **不推荐** 在DTO中添加任何 **逻辑**, 在必要的时候可以实现 `IValidatableObject` 接口. +* **推荐** 为所有的DTO标记 **[Serializable]** Attribute. 因为它们已经是可序列化的, 开人发员可能会希望进行二进制序列化. \ No newline at end of file diff --git a/docs/zh-Hans/Emailing.md b/docs/zh-Hans/Emailing.md new file mode 100644 index 0000000000..d285e5bde2 --- /dev/null +++ b/docs/zh-Hans/Emailing.md @@ -0,0 +1,3 @@ +# Emailing + +待添加 \ No newline at end of file diff --git a/docs/zh-Hans/Index.md b/docs/zh-Hans/Index.md index 655d0f8e79..e14bd67fa5 100644 --- a/docs/zh-Hans/Index.md +++ b/docs/zh-Hans/Index.md @@ -60,6 +60,8 @@ * [捆绑&压缩](AspNetCore/Bundling-Minification.md) * [Tag Helpers](Tag-Helpers.md) * [主题](AspNetCore/Theming.md) +* 后台服务 + * [后台作业](Background-Jobs.md) * 数据访问 * [Entity Framework Core 集成](Entity-Framework-Core.md) * [MongoDB 集成](MongoDB.md) diff --git a/docs/zh-Hans/Modules/Background-Jobs.md b/docs/zh-Hans/Modules/Background-Jobs.md new file mode 100644 index 0000000000..b183febd80 --- /dev/null +++ b/docs/zh-Hans/Modules/Background-Jobs.md @@ -0,0 +1,3 @@ +# Background Jobs Module + +待添加 \ No newline at end of file diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 47f504251e..362e6fbc65 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -224,6 +224,25 @@ } ] }, + { + "text": "后台服务", + "items": [ + { + "text": "后台作业", + "path": "Background-Jobs.md", + "items": [ + { + "text": "Hangfire 集成", + "path": "Background-Jobs-Hangfire.md" + }, + { + "text": "RabbitMQ 集成", + "path": "Background-Jobs-RabbitMq.md" + } + ] + } + ] + }, { "text": "测试" }, From 53fbfa9ccb8cea83b522553a8cfd91bd415557b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=A3=AB=E4=BC=9F?= Date: Wed, 12 Dec 2018 15:42:54 +0800 Subject: [PATCH 25/36] Start template to add Chinese language --- .../MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs index 7cb18ab3df..82813d892d 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs @@ -130,6 +130,7 @@ namespace MyCompanyName.MyProjectName options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); }); } From 88e7cbabce7e35f930826eccce3a95c5f75ed8c2 Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Wed, 12 Dec 2018 12:09:55 +0300 Subject: [PATCH 26/36] #246 Implement concurrency control for mongodb too. --- .../Volo/Abp/Domain/Entities/AggregateRoot.cs | 3 + .../Abp/EntityFrameworkCore/AbpDbContext.cs | 25 +++- .../Repositories/MongoDB/MongoDbRepository.cs | 108 +++++++++++++++--- .../MongoDB/Domain/ConcurrencyStamp_Tests.cs | 9 ++ .../TestApp/Testing/ConcurrencyStamp_Tests.cs | 25 +++- 5 files changed, 146 insertions(+), 24 deletions(-) create mode 100644 framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs index 3521672445..be222839cd 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/AggregateRoot.cs @@ -24,6 +24,7 @@ namespace Volo.Abp.Domain.Entities protected AggregateRoot() { ExtraProperties = new Dictionary(); + ConcurrencyStamp = Guid.NewGuid().ToString("N"); } protected virtual void AddLocalEvent(object eventData) @@ -75,12 +76,14 @@ namespace Volo.Abp.Domain.Entities protected AggregateRoot() { ExtraProperties = new Dictionary(); + ConcurrencyStamp = Guid.NewGuid().ToString("N"); } protected AggregateRoot(TKey id) : base(id) { ExtraProperties = new Dictionary(); + ConcurrencyStamp = Guid.NewGuid().ToString("N"); } protected virtual void AddLocalEvent(object eventData) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index b5860824cc..530fb45ccf 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -201,13 +201,14 @@ namespace Volo.Abp.EntityFrameworkCore protected virtual void ApplyAbpConceptsForAddedEntity(EntityEntry entry, EntityChangeReport changeReport) { CheckAndSetId(entry); + SetConcurrencyStampIfNull(entry); SetCreationAuditProperties(entry); changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Created)); } protected virtual void ApplyAbpConceptsForModifiedEntity(EntityEntry entry, EntityChangeReport changeReport) { - HandleConcurrencyStamp(entry); + UpdateConcurrencyStamp(entry); SetModificationAuditProperties(entry); if (entry.Entity is ISoftDelete && entry.Entity.As().IsDeleted) @@ -224,7 +225,7 @@ namespace Volo.Abp.EntityFrameworkCore protected virtual void ApplyAbpConceptsForDeletedEntity(EntityEntry entry, EntityChangeReport changeReport) { CancelDeletionForSoftDelete(entry); - HandleConcurrencyStamp(entry); + UpdateConcurrencyStamp(entry); SetDeletionAuditProperties(entry); changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Deleted)); } @@ -252,7 +253,7 @@ namespace Volo.Abp.EntityFrameworkCore } } - protected virtual void HandleConcurrencyStamp(EntityEntry entry) + protected virtual void UpdateConcurrencyStamp(EntityEntry entry) { var entity = entry.Entity as IHasConcurrencyStamp; if (entity == null) @@ -260,7 +261,23 @@ namespace Volo.Abp.EntityFrameworkCore return; } - entity.ConcurrencyStamp = Guid.NewGuid().ToString(); + entity.ConcurrencyStamp = Guid.NewGuid().ToString("N"); + } + + protected virtual void SetConcurrencyStampIfNull(EntityEntry entry) + { + var entity = entry.Entity as IHasConcurrencyStamp; + if (entity == null) + { + return; + } + + if (entity.ConcurrencyStamp != null) + { + return; + } + + entity.ConcurrencyStamp = Guid.NewGuid().ToString("N"); } protected virtual void CancelDeletionForSoftDelete(EntityEntry entry) diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index f5170210bd..b4877d8246 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -1,12 +1,13 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; -using MongoDB.Driver; -using MongoDB.Driver.Linq; using Volo.Abp.Auditing; +using Volo.Abp.Data; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities.Events; using Volo.Abp.EventBus; @@ -97,11 +98,18 @@ namespace Volo.Abp.Domain.Repositories.MongoDB AsyncHelper.RunSync(() => TriggerDomainEventsAsync(entity)); - Collection.ReplaceOne( - CreateEntityFilter(entity), + var oldConcurrencyStamp = SetNewConcurrencyStamp(entity); + + var result = Collection.ReplaceOne( + CreateEntityFilter(entity, true, oldConcurrencyStamp), entity ); + if (result.MatchedCount <= 0) + { + ThrowOptimisticConcurrencyException(); + } + return entity; } @@ -124,32 +132,50 @@ namespace Volo.Abp.Domain.Repositories.MongoDB await TriggerDomainEventsAsync(entity); - await Collection.ReplaceOneAsync( - CreateEntityFilter(entity), + var oldConcurrencyStamp = SetNewConcurrencyStamp(entity); + + var result = await Collection.ReplaceOneAsync( + CreateEntityFilter(entity, true, oldConcurrencyStamp), entity, cancellationToken: GetCancellationToken(cancellationToken) ); + if (result.MatchedCount <= 0) + { + ThrowOptimisticConcurrencyException(); + } + return entity; } public override void Delete(TEntity entity, bool autoSave = false) { AsyncHelper.RunSync(() => ApplyAbpConceptsForDeletedEntityAsync(entity)); + var oldConcurrencyStamp = SetNewConcurrencyStamp(entity); if (entity is ISoftDelete softDeleteEntity) { softDeleteEntity.IsDeleted = true; - Collection.ReplaceOne( - CreateEntityFilter(entity), + var result = Collection.ReplaceOne( + CreateEntityFilter(entity, true, oldConcurrencyStamp), entity ); + + if (result.MatchedCount <= 0) + { + ThrowOptimisticConcurrencyException(); + } } else { - Collection.DeleteOne( - CreateEntityFilter(entity) + var result = Collection.DeleteOne( + CreateEntityFilter(entity, true, oldConcurrencyStamp) ); + + if (result.DeletedCount <= 0) + { + ThrowOptimisticConcurrencyException(); + } } } @@ -159,22 +185,33 @@ namespace Volo.Abp.Domain.Repositories.MongoDB CancellationToken cancellationToken = default) { await ApplyAbpConceptsForDeletedEntityAsync(entity); + var oldConcurrencyStamp = SetNewConcurrencyStamp(entity); if (entity is ISoftDelete softDeleteEntity) { softDeleteEntity.IsDeleted = true; - await Collection.ReplaceOneAsync( - CreateEntityFilter(entity), + var result = await Collection.ReplaceOneAsync( + CreateEntityFilter(entity, true, oldConcurrencyStamp), entity, cancellationToken: GetCancellationToken(cancellationToken) ); + + if (result.MatchedCount <= 0) + { + ThrowOptimisticConcurrencyException(); + } } else { - await Collection.DeleteOneAsync( - CreateEntityFilter(entity), + var result = await Collection.DeleteOneAsync( + CreateEntityFilter(entity, true, oldConcurrencyStamp), GetCancellationToken(cancellationToken) ); + + if (result.DeletedCount <= 0) + { + ThrowOptimisticConcurrencyException(); + } } } @@ -239,7 +276,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB ); } - protected virtual FilterDefinition CreateEntityFilter(TEntity entity) + protected virtual FilterDefinition CreateEntityFilter(TEntity entity, bool withConcurrencyStamp = false, string concurrencyStamp = null) { throw new NotImplementedException( $"{nameof(CreateEntityFilter)} is not implemented for MongoDB by default. It should be overrided and implemented by the deriving class!" @@ -332,6 +369,28 @@ namespace Volo.Abp.Domain.Repositories.MongoDB generatesDomainEventsEntity.ClearDistributedEvents(); } } + + /// + /// Sets a new value + /// if given entity implements interface. + /// Returns the old value. + /// + protected virtual string SetNewConcurrencyStamp(TEntity entity) + { + if (!(entity is IHasConcurrencyStamp concurrencyStampEntity)) + { + return null; + } + + var oldConcurrencyStamp = concurrencyStampEntity.ConcurrencyStamp; + concurrencyStampEntity.ConcurrencyStamp = Guid.NewGuid().ToString("N"); + return oldConcurrencyStamp; + } + + protected virtual void ThrowOptimisticConcurrencyException() + { + throw new AbpDbConcurrencyException("Database operation expected to affect 1 row but actually affected 0 row. Data may have been modified or deleted since entities were loaded. This exception has been thrown on optimistic concurrency check."); + } } public class MongoDbRepository @@ -390,7 +449,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB public virtual void Delete(TKey id, bool autoSave = false) { - Collection.DeleteOne(CreateEntityFilter(id)); + Collection.DeleteOne(CreateEntityFilter(id)); //TODO: How to handle concurrency stamp! } public virtual Task DeleteAsync( @@ -404,9 +463,22 @@ namespace Volo.Abp.Domain.Repositories.MongoDB ); } - protected override FilterDefinition CreateEntityFilter(TEntity entity) + protected override FilterDefinition CreateEntityFilter(TEntity entity, bool withConcurrencyStamp = false, string concurrencyStamp = null) { - return Builders.Filter.Eq(e => e.Id, entity.Id); + if (!withConcurrencyStamp || !(entity is IHasConcurrencyStamp entityWithConcurrencyStamp)) + { + return Builders.Filter.Eq(e => e.Id, entity.Id); + } + + if (concurrencyStamp == null) + { + concurrencyStamp = entityWithConcurrencyStamp.ConcurrencyStamp; + } + + return Builders.Filter.And( + Builders.Filter.Eq(e => e.Id, entity.Id), + Builders.Filter.Eq(e => ((IHasConcurrencyStamp)e).ConcurrencyStamp, concurrencyStamp) + ); } protected virtual FilterDefinition CreateEntityFilter(TKey id, bool applyFilters = false) diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs new file mode 100644 index 0000000000..117cd5dde1 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs @@ -0,0 +1,9 @@ +using Volo.Abp.TestApp.Testing; + +namespace Volo.Abp.MongoDB.Domain +{ + public class ConcurrencyStamp_Tests : ConcurrencyStamp_Tests + { + + } +} diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs index e74e482cac..2c5a5d89ab 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ConcurrencyStamp_Tests.cs @@ -6,12 +6,12 @@ using Xunit; namespace Volo.Abp.TestApp.Testing { - public class ConcurrencyStamp_Tests : TestAppTestBase + public abstract class ConcurrencyStamp_Tests : TestAppTestBase where TStartupModule : IAbpModule { protected readonly ICityRepository CityRepository; - public ConcurrencyStamp_Tests() + protected ConcurrencyStamp_Tests() { CityRepository = GetRequiredService(); } @@ -19,17 +19,38 @@ namespace Volo.Abp.TestApp.Testing [Fact] public async Task Should_Not_Allow_To_Update_If_The_Entity_Has_Changed() { + //Got an entity from database, changed its value, but not updated in the database yet var london1 = await CityRepository.FindByNameAsync("London"); london1.Name = "London-1"; + //Another user has changed it just before I update var london2 = await CityRepository.FindByNameAsync("London"); london2.Name = "London-2"; await CityRepository.UpdateAsync(london2); + //And updating my old entity throws exception! await Assert.ThrowsAsync(async () => { await CityRepository.UpdateAsync(london1); }); } + + [Fact] + public async Task Should_Not_Allow_To_Delete_If_The_Entity_Has_Changed() + { + //Got an entity from database, but not deleted in the database yet + var london1 = await CityRepository.FindByNameAsync("London"); + + //Another user has changed it just before I delete + var london2 = await CityRepository.FindByNameAsync("London"); + london2.Name = "London-updated"; + await CityRepository.UpdateAsync(london2); + + //And deleting my old entity throws exception! + await Assert.ThrowsAsync(async () => + { + await CityRepository.DeleteAsync(london1); + }); + } } } From 1c3165a32ca9f44314617f59e49cdb6d4572983b Mon Sep 17 00:00:00 2001 From: Mostafa F Date: Wed, 12 Dec 2018 12:48:10 +0330 Subject: [PATCH 27/36] Rename AbpIdentityWebMainMenuContributor.cs to AbpTenantManagementWebMainMenuContributor.cs --- ...tributor.cs => AbpTenantManagementWebMainMenuContributor.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/{AbpIdentityWebMainMenuContributor.cs => AbpTenantManagementWebMainMenuContributor.cs} (99%) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpIdentityWebMainMenuContributor.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpTenantManagementWebMainMenuContributor.cs similarity index 99% rename from modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpIdentityWebMainMenuContributor.cs rename to modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpTenantManagementWebMainMenuContributor.cs index ff8dc7f1a6..5726df320e 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpIdentityWebMainMenuContributor.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpTenantManagementWebMainMenuContributor.cs @@ -28,4 +28,4 @@ namespace Volo.Abp.TenantManagement.Web.Navigation } } } -} \ No newline at end of file +} From 91020efb075e8d20f8ca4b7a0b8b97200f12a75f Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Wed, 12 Dec 2018 13:03:06 +0300 Subject: [PATCH 28/36] Remove unnecessary todo --- .../Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index b4877d8246..11e79b32e2 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -10,7 +10,6 @@ using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities.Events; -using Volo.Abp.EventBus; using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Local; using Volo.Abp.Guids; @@ -449,7 +448,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB public virtual void Delete(TKey id, bool autoSave = false) { - Collection.DeleteOne(CreateEntityFilter(id)); //TODO: How to handle concurrency stamp! + Collection.DeleteOne(CreateEntityFilter(id)); } public virtual Task DeleteAsync( From d60836c8dbcb09aa8d59bab26f5152eda26eddea Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Wed, 12 Dec 2018 14:24:07 +0300 Subject: [PATCH 29/36] #246 Implement concurrency stamp --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 1 + .../Abp/MongoDB/AbpBsonClassMapExtensions.cs | 5 +- .../Testing/EntityChangeEvents_Tests.cs | 54 +------------------ 3 files changed, 6 insertions(+), 54 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index 530fb45ccf..6540930405 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -261,6 +261,7 @@ namespace Volo.Abp.EntityFrameworkCore return; } + Entry(entity).Property(x => x.ConcurrencyStamp).OriginalValue = entity.ConcurrencyStamp; entity.ConcurrencyStamp = Guid.NewGuid().ToString("N"); } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpBsonClassMapExtensions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpBsonClassMapExtensions.cs index 67fe25d9b6..68a2719c38 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpBsonClassMapExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpBsonClassMapExtensions.cs @@ -8,7 +8,10 @@ namespace Volo.Abp.MongoDB public static void ConfigureExtraProperties(this BsonClassMap map) where T : class, IHasExtraProperties { - map.MapExtraElementsProperty(x => x.ExtraProperties); + map.SetExtraElementsMember(new BsonMemberMap( + map, + typeof(T).GetMember(nameof(IHasExtraProperties.ExtraProperties))[0]) + ); } } } diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs index 67032507f3..184b7698be 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs @@ -35,9 +35,6 @@ namespace Volo.Abp.TestApp.Testing var creatingEventTriggered = false; var createdEventTriggered = false; var createdEtoTriggered = false; - var updatedEtoTriggered = false; - var updatingEventTriggered = false; - var updatedEventTriggered = false; using (var uow = GetRequiredService().Begin()) { @@ -45,18 +42,14 @@ namespace Volo.Abp.TestApp.Testing { creatingEventTriggered.ShouldBeFalse(); createdEventTriggered.ShouldBeFalse(); - updatingEventTriggered.ShouldBeFalse(); - updatedEventTriggered.ShouldBeFalse(); creatingEventTriggered = true; data.Entity.Name.ShouldBe(personName); - /* Want to change age from 15 to 18 - * Expect to trigger EntityUpdatingEventData, EntityUpdatedEventData events */ + /* Want to change age from 15 to 18 */ data.Entity.Age.ShouldBe(15); data.Entity.Age = 18; - PersonRepository.Update(data.Entity); return Task.CompletedTask; }); @@ -64,8 +57,6 @@ namespace Volo.Abp.TestApp.Testing { creatingEventTriggered.ShouldBeTrue(); createdEventTriggered.ShouldBeFalse(); - updatingEventTriggered.ShouldBeTrue(); - updatedEventTriggered.ShouldBeFalse(); createdEventTriggered = true; @@ -84,46 +75,6 @@ namespace Volo.Abp.TestApp.Testing return Task.CompletedTask; }); - LocalEventBus.Subscribe>(data => - { - creatingEventTriggered.ShouldBeTrue(); - createdEventTriggered.ShouldBeFalse(); - updatingEventTriggered.ShouldBeFalse(); - updatedEventTriggered.ShouldBeFalse(); - - updatingEventTriggered = true; - - data.Entity.Name.ShouldBe(personName); - data.Entity.Age.ShouldBe(18); - - return Task.CompletedTask; - }); - - LocalEventBus.Subscribe>(data => - { - creatingEventTriggered.ShouldBeTrue(); - createdEventTriggered.ShouldBeTrue(); - updatingEventTriggered.ShouldBeTrue(); - updatedEventTriggered.ShouldBeFalse(); - - updatedEventTriggered = true; - - data.Entity.Name.ShouldBe(personName); - data.Entity.Age.ShouldBe(18); - - return Task.CompletedTask; - }); - - DistributedEventBus.Subscribe>(eto => - { - eto.Entity.Name.ShouldBe(personName); - eto.Entity.Age.ShouldBe(18); - - updatedEtoTriggered = true; - - return Task.CompletedTask; - }); - PersonRepository.Insert(new Person(Guid.NewGuid(), personName, 15)); uow.Complete(); @@ -132,9 +83,6 @@ namespace Volo.Abp.TestApp.Testing creatingEventTriggered.ShouldBeTrue(); createdEventTriggered.ShouldBeTrue(); createdEtoTriggered.ShouldBeTrue(); - updatingEventTriggered.ShouldBeTrue(); - updatedEventTriggered.ShouldBeTrue(); - updatedEtoTriggered.ShouldBeTrue(); } } } From e664da27f778815faec7374fc978f1637c820054 Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Wed, 12 Dec 2018 14:34:22 +0300 Subject: [PATCH 30/36] Ignore ConcurrencyStamp and ExtraProperties for mapping --- .../BackgroundJobs/BackgroundJobsDomainAutoMapperProfile.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDomainAutoMapperProfile.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDomainAutoMapperProfile.cs index 2ba2bed8cb..a20a01392b 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDomainAutoMapperProfile.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDomainAutoMapperProfile.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Volo.Abp.AutoMapper; namespace Volo.Abp.BackgroundJobs { @@ -7,6 +8,8 @@ namespace Volo.Abp.BackgroundJobs public BackgroundJobsDomainAutoMapperProfile() { CreateMap() + .Ignore(record => record.ConcurrencyStamp) + .Ignore(record => record.ExtraProperties) .ReverseMap(); } } From 431bfab0bc990250fc7fe817f9e57a2d65836597 Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Wed, 12 Dec 2018 14:43:24 +0300 Subject: [PATCH 31/36] Use optimistic concurrency in identity user and role edit. Apply migrations for the MVC template. --- .../Application/Services/CrudAppService.cs | 3 +- .../Services/CrudAppServiceBase.cs | 4 +- .../Volo/Abp/Identity/IProfileAppService.cs | 6 +-- .../Volo/Abp/Identity/IdentityRoleDto.cs | 5 ++- .../Abp/Identity/IdentityRoleUpdateDto.cs | 8 ++-- .../Volo/Abp/Identity/IdentityUserDto.cs | 5 ++- .../Abp/Identity/IdentityUserUpdateDto.cs | 7 +++- .../Abp/Identity/IdentityRoleAppService.cs | 1 + .../Abp/Identity/IdentityUserAppService.cs | 1 + .../Abp/Identity/IdentityClaimTypeConsts.cs | 10 +---- .../Volo/Abp/Identity/IdentityRoleConsts.cs | 1 + .../Volo/Abp/Identity/IdentityClaimType.cs | 8 ++-- ...IdentityDbContextModelBuilderExtensions.cs | 7 +++- .../Pages/Identity/Roles/EditModal.cshtml | 3 +- .../Pages/Identity/Roles/EditModal.cshtml.cs | 6 ++- .../Pages/Identity/Users/EditModal.cshtml | 1 + .../Pages/Identity/Users/EditModal.cshtml.cs | 6 ++- .../Identity/IdentityRoleAppService_Tests.cs | 5 ++- .../Identity/IdentityUserAppService_Tests.cs | 39 ++++++++++++++++++- ....cs => 20181212113826_Initial.Designer.cs} | 28 ++++++++++++- ...7_Initial.cs => 20181212113826_Initial.cs} | 14 +++++-- .../MyProjectNameDbContextModelSnapshot.cs | 26 ++++++++++++- ...e.MyProjectName.EntityFrameworkCore.csproj | 4 ++ 23 files changed, 156 insertions(+), 42 deletions(-) rename templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20181114070127_Initial.Designer.cs => 20181212113826_Initial.Designer.cs} (95%) rename templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20181114070127_Initial.cs => 20181212113826_Initial.cs} (97%) diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs index f705593e87..8127e88f23 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs @@ -1,5 +1,4 @@ using System.Linq; -using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; @@ -99,7 +98,7 @@ namespace Volo.Abp.Application.Services CheckUpdatePolicy(); var entity = GetEntityById(id); - + MapToEntity(input, entity); CurrentUnitOfWork.SaveChanges(); diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs index 947c622081..eb4c7a200f 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs @@ -4,6 +4,7 @@ using System.Linq.Dynamic.Core; using Volo.Abp.Application.Dtos; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; +using Volo.Abp.ObjectMapping; namespace Volo.Abp.Application.Services { @@ -11,7 +12,8 @@ namespace Volo.Abp.Application.Services /// This is a common base class for CrudAppService and AsyncCrudAppService classes. /// Inherit either from CrudAppService or AsyncCrudAppService, not from this class. /// - public abstract class CrudAppServiceBase : ApplicationService + public abstract class CrudAppServiceBase : + ApplicationService where TEntity : class, IEntity where TEntityDto : IEntityDto { diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IProfileAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IProfileAppService.cs index 9e0a5cbacf..cb61fc6a82 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IProfileAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IProfileAppService.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; +using System.Threading.Tasks; using Volo.Abp.Application.Services; namespace Volo.Abp.Identity diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleDto.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleDto.cs index c25ceace56..d55b68fcb1 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleDto.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleDto.cs @@ -1,9 +1,10 @@ using System; using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Entities; namespace Volo.Abp.Identity { - public class IdentityRoleDto : EntityDto + public class IdentityRoleDto : EntityDto, IHasConcurrencyStamp { public string Name { get; set; } @@ -12,5 +13,7 @@ namespace Volo.Abp.Identity public bool IsStatic { get; set; } public bool IsPublic { get; set; } + + public string ConcurrencyStamp { get; set; } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleUpdateDto.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleUpdateDto.cs index c569957f23..c8a44f92c2 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleUpdateDto.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityRoleUpdateDto.cs @@ -1,7 +1,9 @@ -namespace Volo.Abp.Identity +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.Identity { - public class IdentityRoleUpdateDto : IdentityRoleCreateOrUpdateDtoBase + public class IdentityRoleUpdateDto : IdentityRoleCreateOrUpdateDtoBase, IHasConcurrencyStamp { - + public string ConcurrencyStamp { get; set; } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs index bc28a79f8e..02d1b10166 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs @@ -1,10 +1,11 @@ using System; using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Entities; using Volo.Abp.MultiTenancy; namespace Volo.Abp.Identity { - public class IdentityUserDto : FullAuditedEntityDto, IMultiTenant + public class IdentityUserDto : FullAuditedEntityDto, IMultiTenant, IHasConcurrencyStamp { public Guid? TenantId { get; set; } @@ -27,5 +28,7 @@ namespace Volo.Abp.Identity public bool LockoutEnabled { get; set; } public DateTimeOffset? LockoutEnd { get; set; } + + public string ConcurrencyStamp { get; set; } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserUpdateDto.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserUpdateDto.cs index 3117ff8003..a599207f23 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserUpdateDto.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserUpdateDto.cs @@ -1,6 +1,9 @@ -namespace Volo.Abp.Identity +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.Identity { - public class IdentityUserUpdateDto : IdentityUserCreateOrUpdateDtoBase + public class IdentityUserUpdateDto : IdentityUserCreateOrUpdateDtoBase, IHasConcurrencyStamp { + public string ConcurrencyStamp { get; set; } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityRoleAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityRoleAppService.cs index f3ad2f880a..ed78156052 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityRoleAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityRoleAppService.cs @@ -84,6 +84,7 @@ namespace Volo.Abp.Identity public async Task UpdateAsync(Guid id, IdentityRoleUpdateDto input) { var role = await _roleManager.GetByIdAsync(id); + role.ConcurrencyStamp = input.ConcurrencyStamp; (await _roleManager.SetRoleNameAsync(role, input.Name)).CheckErrors(); diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs index 054ce247ac..8c9a8ef015 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs @@ -72,6 +72,7 @@ namespace Volo.Abp.Identity public async Task UpdateAsync(Guid id, IdentityUserUpdateDto input) { var user = await _userManager.GetByIdAsync(id); + user.ConcurrencyStamp = input.ConcurrencyStamp; (await _userManager.SetUserNameAsync(user, input.UserName)).CheckErrors(); await UpdateUserByInput(user, input); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs index 1b691f404c..32e3197e12 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Volo.Abp.Identity +namespace Volo.Abp.Identity { public class IdentityClaimTypeConsts { public const int MaxNameLength = 256; - public const int MaxRegexLength = 512; - public const int MaxRegexDescriptionLength = 128; - public const int MaxDescriptionLength = 256; + public const int MaxConcurrencyStampLength = 256; } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityRoleConsts.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityRoleConsts.cs index 11bde27f34..cac33aa53d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityRoleConsts.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityRoleConsts.cs @@ -4,5 +4,6 @@ { public const int MaxNameLength = 256; public const int MaxNormalizedNameLength = MaxNameLength; + public const int MaxConcurrencyStampLength = 256; } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs index 5755279585..d8722669fb 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs @@ -1,12 +1,10 @@ using System; -using System.Collections.Generic; -using System.Text; using JetBrains.Annotations; using Volo.Abp.Domain.Entities; namespace Volo.Abp.Identity { - public class IdentityClaimType : Entity + public class IdentityClaimType : AggregateRoot { public virtual string Name { get; protected set; } @@ -24,12 +22,14 @@ namespace Volo.Abp.Identity protected IdentityClaimType() { + } public IdentityClaimType(Guid id, [NotNull] string name, bool required, bool isStatic, [CanBeNull]string regex, [CanBeNull]string regexDescription, [CanBeNull] string description, IdentityClaimValueType valueType = IdentityClaimValueType.String) { Check.NotNull(name, nameof(name)); + Id = id; Name = name; Required = required; IsStatic = isStatic; @@ -38,7 +38,5 @@ namespace Volo.Abp.Identity Description = description; ValueType = valueType; } - - } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index a0ffadea8c..27727da177 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -30,7 +30,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.Property(u => u.NormalizedEmail).HasMaxLength(IdentityUserConsts.MaxNormalizedEmailLength).HasColumnName(nameof(IdentityUser.NormalizedEmail)); b.Property(u => u.PasswordHash).HasMaxLength(IdentityUserConsts.MaxPasswordHashLength).HasColumnName(nameof(IdentityUser.PasswordHash)); b.Property(u => u.SecurityStamp).IsRequired().HasMaxLength(IdentityUserConsts.MaxSecurityStampLength).HasColumnName(nameof(IdentityUser.SecurityStamp)); - b.Property(u => u.ConcurrencyStamp).IsRequired().HasMaxLength(IdentityUserConsts.MaxConcurrencyStampLength).HasColumnName(nameof(IdentityUser.ConcurrencyStamp)); + b.Property(u => u.ConcurrencyStamp).IsRequired().IsConcurrencyToken().HasMaxLength(IdentityUserConsts.MaxConcurrencyStampLength).HasColumnName(nameof(IdentityUser.ConcurrencyStamp)); b.Property(u => u.TwoFactorEnabled).HasDefaultValue(false).HasColumnName(nameof(IdentityUser.TwoFactorEnabled)); b.Property(u => u.LockoutEnabled).HasDefaultValue(false).HasColumnName(nameof(IdentityUser.LockoutEnabled)); b.Property(u => u.AccessFailedCount).HasDefaultValue(0).HasColumnName(nameof(IdentityUser.AccessFailedCount)); @@ -99,6 +99,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.Property(r => r.Name).IsRequired().HasMaxLength(IdentityRoleConsts.MaxNameLength); b.Property(r => r.NormalizedName).IsRequired().HasMaxLength(IdentityRoleConsts.MaxNormalizedNameLength); + b.Property(u => u.ConcurrencyStamp).IsRequired().IsConcurrencyToken().HasMaxLength(IdentityRoleConsts.MaxConcurrencyStampLength).HasColumnName(nameof(IdentityRole.ConcurrencyStamp)); b.Property(r => r.IsDefault).HasColumnName(nameof(IdentityRole.IsDefault)); b.Property(r => r.IsStatic).HasColumnName(nameof(IdentityRole.IsStatic)); b.Property(r => r.IsPublic).HasColumnName(nameof(IdentityRole.IsPublic)); @@ -122,11 +123,13 @@ namespace Volo.Abp.Identity.EntityFrameworkCore { b.ToTable(options.TablePrefix + "ClaimTypes", options.Schema); + b.ConfigureExtraProperties(); + b.Property(uc => uc.Name).HasMaxLength(IdentityClaimTypeConsts.MaxNameLength).IsRequired(); // make unique b.Property(uc => uc.Regex).HasMaxLength(IdentityClaimTypeConsts.MaxRegexLength); b.Property(uc => uc.RegexDescription).HasMaxLength(IdentityClaimTypeConsts.MaxRegexDescriptionLength); b.Property(uc => uc.Description).HasMaxLength(IdentityClaimTypeConsts.MaxDescriptionLength); - + b.Property(uc => uc.ConcurrencyStamp).IsRequired().IsConcurrencyToken().HasMaxLength(IdentityClaimTypeConsts.MaxConcurrencyStampLength).HasColumnName(nameof(IdentityClaimType.ConcurrencyStamp)); }); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml index b09cfe2dcb..0a3cd3668d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml @@ -12,9 +12,10 @@ + @if (Model.Role.IsStatic) { - + } else { diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml.cs index 58703c211e..66259c6ba0 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml.cs @@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Domain.Entities; namespace Volo.Abp.Identity.Web.Pages.Identity.Roles { @@ -35,11 +36,14 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Roles return NoContent(); } - public class RoleInfoModel + public class RoleInfoModel : IHasConcurrencyStamp { [HiddenInput] public Guid Id { get; set; } + [HiddenInput] + public string ConcurrencyStamp { get; set; } + [Required] [StringLength(IdentityRoleConsts.MaxNameLength)] [Display(Name = "DisplayName:RoleName")] diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml index afa0df85ed..be9cc9b205 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml @@ -15,6 +15,7 @@ @* TODO: Can we use dynamic form? *@ + diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs index 25615aca94..0655331fb9 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Domain.Entities; namespace Volo.Abp.Identity.Web.Pages.Identity.Users { @@ -54,11 +55,14 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users return NoContent(); } - public class UserInfoViewModel + public class UserInfoViewModel : IHasConcurrencyStamp { [HiddenInput] public Guid Id { get; set; } + [HiddenInput] + public string ConcurrencyStamp { get; set; } + [Required] [StringLength(IdentityUserConsts.MaxUserNameLength)] public string UserName { get; set; } diff --git a/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityRoleAppService_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityRoleAppService_Tests.cs index 8801f7073a..d20294da5c 100644 --- a/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityRoleAppService_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityRoleAppService_Tests.cs @@ -78,7 +78,10 @@ namespace Volo.Abp.Identity var input = new IdentityRoleUpdateDto { - Name = Guid.NewGuid().ToString("N").Left(8) + Name = Guid.NewGuid().ToString("N").Left(8), + ConcurrencyStamp = moderator.ConcurrencyStamp, + IsDefault = moderator.IsDefault, + IsPublic = moderator.IsPublic }; //Act diff --git a/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserAppService_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserAppService_Tests.cs index 14864ce7da..c418c261ff 100644 --- a/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserAppService_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserAppService_Tests.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Shouldly; +using Volo.Abp.Data; using Xunit; namespace Volo.Abp.Identity @@ -9,11 +10,13 @@ namespace Volo.Abp.Identity { private readonly IIdentityUserAppService _userAppService; private readonly IIdentityUserRepository _userRepository; + private readonly IdentityTestData _testData; public IdentityUserAppService_Tests() { _userAppService = GetRequiredService(); _userRepository = GetRequiredService(); + _testData = GetRequiredService(); } [Fact] @@ -98,7 +101,10 @@ namespace Volo.Abp.Identity TwoFactorEnabled = true, PhoneNumber = CreateRandomPhoneNumber(), Email = CreateRandomEmail(), - RoleNames = new[] { "admin", "moderator" } + RoleNames = new[] { "admin", "moderator" }, + ConcurrencyStamp = johnNash.ConcurrencyStamp, + Surname = johnNash.Surname, + Name = johnNash.Name }; //Act @@ -122,6 +128,37 @@ namespace Volo.Abp.Identity user.Roles.Count.ShouldBe(2); } + + [Fact] + public async Task UpdateAsync_Concurrency_Exception() + { + //Get user + var johnNash = await _userAppService.GetAsync(_testData.UserJohnId); + + //Act + + var input = new IdentityUserUpdateDto + { + Name = "John-updated", + Surname = "Nash-updated", + UserName = johnNash.UserName, + LockoutEnabled = true, + TwoFactorEnabled = true, + PhoneNumber = CreateRandomPhoneNumber(), + Email = CreateRandomEmail(), + RoleNames = new[] { "admin", "moderator" }, + ConcurrencyStamp = johnNash.ConcurrencyStamp + }; + + await _userAppService.UpdateAsync(johnNash.Id, input); + + //Second update with same input will throw exception because the entity has been modified + (await Assert.ThrowsAsync(async () => + { + await _userAppService.UpdateAsync(johnNash.Id, input); + })).Message.ShouldContain("Optimistic concurrency failure"); + } + [Fact] public async Task DeleteAsync() { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181114070127_Initial.Designer.cs b/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181212113826_Initial.Designer.cs similarity index 95% rename from templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181114070127_Initial.Designer.cs rename to templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181212113826_Initial.Designer.cs index 9abe09e5c4..8afbe89363 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181114070127_Initial.Designer.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181212113826_Initial.Designer.cs @@ -11,7 +11,7 @@ using Volo.Abp.BackgroundJobs; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20181114070127_Initial")] + [Migration("20181212113826_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -43,6 +43,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnName("Comments") .HasMaxLength(256); + b.Property("ConcurrencyStamp"); + b.Property("Exceptions") .HasColumnName("Exceptions") .HasMaxLength(4000); @@ -221,9 +223,14 @@ namespace MyCompanyName.MyProjectName.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp"); + b.Property("CreationTime") .HasColumnName("CreationTime"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("IsAbandoned") .ValueGeneratedOnAdd() .HasDefaultValue(false); @@ -260,9 +267,18 @@ namespace MyCompanyName.MyProjectName.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + b.Property("Description") .HasMaxLength(256); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("IsStatic"); b.Property("Name") @@ -289,7 +305,14 @@ namespace MyCompanyName.MyProjectName.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("ConcurrencyStamp"); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); b.Property("IsDefault") .HasColumnName("IsDefault"); @@ -351,6 +374,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasDefaultValue(0); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() .IsRequired() .HasColumnName("ConcurrencyStamp") .HasMaxLength(256); diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181114070127_Initial.cs b/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181212113826_Initial.cs similarity index 97% rename from templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181114070127_Initial.cs rename to templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181212113826_Initial.cs index 01f4f9cd7f..5dd6559191 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181114070127_Initial.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20181212113826_Initial.cs @@ -12,6 +12,7 @@ namespace MyCompanyName.MyProjectName.Migrations columns: table => new { Id = table.Column(nullable: false), + ConcurrencyStamp = table.Column(nullable: true), UserId = table.Column(nullable: true), UserName = table.Column(maxLength: 256, nullable: true), TenantId = table.Column(nullable: true), @@ -39,6 +40,8 @@ namespace MyCompanyName.MyProjectName.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), JobName = table.Column(maxLength: 128, nullable: false), JobArgs = table.Column(maxLength: 1048576, nullable: false), TryCount = table.Column(nullable: false, defaultValue: (short)0), @@ -58,6 +61,8 @@ namespace MyCompanyName.MyProjectName.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), Name = table.Column(maxLength: 256, nullable: false), Required = table.Column(nullable: false), IsStatic = table.Column(nullable: false), @@ -91,10 +96,11 @@ namespace MyCompanyName.MyProjectName.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), TenantId = table.Column(nullable: true), Name = table.Column(maxLength: 256, nullable: false), NormalizedName = table.Column(maxLength: 256, nullable: false), - ConcurrencyStamp = table.Column(nullable: true), IsDefault = table.Column(nullable: false), IsStatic = table.Column(nullable: false), IsPublic = table.Column(nullable: false) @@ -124,6 +130,8 @@ namespace MyCompanyName.MyProjectName.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), CreationTime = table.Column(nullable: false), CreatorId = table.Column(nullable: true), LastModificationTime = table.Column(nullable: true), @@ -141,14 +149,12 @@ namespace MyCompanyName.MyProjectName.Migrations EmailConfirmed = table.Column(nullable: false, defaultValue: false), PasswordHash = table.Column(maxLength: 256, nullable: true), SecurityStamp = table.Column(maxLength: 256, nullable: false), - ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), PhoneNumber = table.Column(maxLength: 16, nullable: true), PhoneNumberConfirmed = table.Column(nullable: false, defaultValue: false), TwoFactorEnabled = table.Column(nullable: false, defaultValue: false), LockoutEnd = table.Column(nullable: true), LockoutEnabled = table.Column(nullable: false, defaultValue: false), - AccessFailedCount = table.Column(nullable: false, defaultValue: 0), - ExtraProperties = table.Column(nullable: true) + AccessFailedCount = table.Column(nullable: false, defaultValue: 0) }, constraints: table => { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs index eff7489955..8a05ab5bc3 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -41,6 +41,8 @@ namespace MyCompanyName.MyProjectName.Migrations .HasColumnName("Comments") .HasMaxLength(256); + b.Property("ConcurrencyStamp"); + b.Property("Exceptions") .HasColumnName("Exceptions") .HasMaxLength(4000); @@ -219,9 +221,14 @@ namespace MyCompanyName.MyProjectName.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp"); + b.Property("CreationTime") .HasColumnName("CreationTime"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("IsAbandoned") .ValueGeneratedOnAdd() .HasDefaultValue(false); @@ -258,9 +265,18 @@ namespace MyCompanyName.MyProjectName.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + b.Property("Description") .HasMaxLength(256); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("IsStatic"); b.Property("Name") @@ -287,7 +303,14 @@ namespace MyCompanyName.MyProjectName.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("ConcurrencyStamp"); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); b.Property("IsDefault") .HasColumnName("IsDefault"); @@ -349,6 +372,7 @@ namespace MyCompanyName.MyProjectName.Migrations .HasDefaultValue(0); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() .IsRequired() .HasColumnName("ConcurrencyStamp") .HasMaxLength(256); diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj index c3e54f4327..c393a58161 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj @@ -5,6 +5,10 @@ MyCompanyName.MyProjectName + + + + From 5674fc39ae5382963213b666568f68f53c0aefee Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Wed, 12 Dec 2018 14:55:44 +0300 Subject: [PATCH 32/36] Update migration --- ....cs => 20181212114934_Initial.Designer.cs} | 86 ++++++++++++++++++- ...9_Initial.cs => 20181212114934_Initial.cs} | 48 +++++++++-- .../DemoAppDbContextModelSnapshot.cs | 84 +++++++++++++++++- ...MyCompanyName.MyProjectName.DemoApp.csproj | 8 -- 4 files changed, 205 insertions(+), 21 deletions(-) rename templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/{20180711153639_Initial.Designer.cs => 20181212114934_Initial.Designer.cs} (80%) rename templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/{20180711153639_Initial.cs => 20181212114934_Initial.cs} (83%) diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20180711153639_Initial.Designer.cs b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20181212114934_Initial.Designer.cs similarity index 80% rename from templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20180711153639_Initial.Designer.cs rename to templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20181212114934_Initial.Designer.cs index 7f69d96beb..9f8a2b4adf 100644 --- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20180711153639_Initial.Designer.cs +++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20181212114934_Initial.Designer.cs @@ -10,7 +10,7 @@ using MyCompanyName.MyProjectName.DemoApp; namespace MyCompanyName.MyProjectName.DemoApp.Migrations { [DbContext(typeof(DemoAppDbContext))] - [Migration("20180711153639_Initial")] + [Migration("20181212114934_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -21,12 +21,66 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256); + + b.Property("Regex") + .HasMaxLength(512); + + b.Property("RegexDescription") + .HasMaxLength(128); + + b.Property("Required"); + + b.Property("ValueType"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("ConcurrencyStamp"); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnName("IsStatic"); b.Property("Name") .IsRequired() @@ -79,10 +133,19 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations .HasDefaultValue(0); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() .IsRequired() .HasColumnName("ConcurrencyStamp") .HasMaxLength(256); + b.Property("CreationTime"); + + b.Property("CreatorId"); + + b.Property("DeleterId"); + + b.Property("DeletionTime"); + b.Property("Email") .HasColumnName("Email") .HasMaxLength(256); @@ -95,6 +158,12 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("IsDeleted"); + + b.Property("LastModificationTime"); + + b.Property("LastModifierId"); + b.Property("LockoutEnabled") .ValueGeneratedOnAdd() .HasColumnName("LockoutEnabled") @@ -102,6 +171,10 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations b.Property("LockoutEnd"); + b.Property("Name") + .HasColumnName("Name") + .HasMaxLength(64); + b.Property("NormalizedEmail") .HasColumnName("NormalizedEmail") .HasMaxLength(256); @@ -129,6 +202,10 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations .HasColumnName("SecurityStamp") .HasMaxLength(256); + b.Property("Surname") + .HasColumnName("Surname") + .HasMaxLength(64); + b.Property("TenantId") .HasColumnName("TenantId"); @@ -221,9 +298,10 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations b.Property("UserId"); b.Property("LoginProvider") - .HasMaxLength(128); + .HasMaxLength(64); - b.Property("Name"); + b.Property("Name") + .HasMaxLength(128); b.Property("TenantId"); diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20180711153639_Initial.cs b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20181212114934_Initial.cs similarity index 83% rename from templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20180711153639_Initial.cs rename to templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20181212114934_Initial.cs index 68dae7e9c6..cefa12dfaf 100644 --- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20180711153639_Initial.cs +++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20181212114934_Initial.cs @@ -7,6 +7,26 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations { protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), + Name = table.Column(maxLength: 256, nullable: false), + Required = table.Column(nullable: false), + IsStatic = table.Column(nullable: false), + Regex = table.Column(maxLength: 512, nullable: true), + RegexDescription = table.Column(maxLength: 128, nullable: true), + Description = table.Column(maxLength: 256, nullable: true), + ValueType = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + migrationBuilder.CreateTable( name: "AbpPermissionGrants", columns: table => new @@ -27,10 +47,14 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), TenantId = table.Column(nullable: true), Name = table.Column(maxLength: 256, nullable: false), NormalizedName = table.Column(maxLength: 256, nullable: false), - ConcurrencyStamp = table.Column(nullable: true) + IsDefault = table.Column(nullable: false), + IsStatic = table.Column(nullable: false), + IsPublic = table.Column(nullable: false) }, constraints: table => { @@ -57,22 +81,31 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), TenantId = table.Column(nullable: true), UserName = table.Column(maxLength: 256, nullable: false), NormalizedUserName = table.Column(maxLength: 256, nullable: false), + Name = table.Column(maxLength: 64, nullable: true), + Surname = table.Column(maxLength: 64, nullable: true), Email = table.Column(maxLength: 256, nullable: true), NormalizedEmail = table.Column(maxLength: 256, nullable: true), EmailConfirmed = table.Column(nullable: false, defaultValue: false), PasswordHash = table.Column(maxLength: 256, nullable: true), SecurityStamp = table.Column(maxLength: 256, nullable: false), - ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), PhoneNumber = table.Column(maxLength: 16, nullable: true), PhoneNumberConfirmed = table.Column(nullable: false, defaultValue: false), TwoFactorEnabled = table.Column(nullable: false, defaultValue: false), LockoutEnd = table.Column(nullable: true), LockoutEnabled = table.Column(nullable: false, defaultValue: false), - AccessFailedCount = table.Column(nullable: false, defaultValue: 0), - ExtraProperties = table.Column(nullable: true) + AccessFailedCount = table.Column(nullable: false, defaultValue: 0) }, constraints: table => { @@ -173,8 +206,8 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations { TenantId = table.Column(nullable: true), UserId = table.Column(nullable: false), - LoginProvider = table.Column(maxLength: 128, nullable: false), - Name = table.Column(nullable: false), + LoginProvider = table.Column(maxLength: 64, nullable: false), + Name = table.Column(maxLength: 128, nullable: false), Value = table.Column(nullable: true) }, constraints: table => @@ -246,6 +279,9 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations protected override void Down(MigrationBuilder migrationBuilder) { + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + migrationBuilder.DropTable( name: "AbpPermissionGrants"); diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs index ad9f1b82c9..b64a132e07 100644 --- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs +++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs @@ -19,12 +19,66 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256); + + b.Property("Regex") + .HasMaxLength(512); + + b.Property("RegexDescription") + .HasMaxLength(128); + + b.Property("Required"); + + b.Property("ValueType"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("ConcurrencyStamp"); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnName("IsStatic"); b.Property("Name") .IsRequired() @@ -77,10 +131,19 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations .HasDefaultValue(0); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() .IsRequired() .HasColumnName("ConcurrencyStamp") .HasMaxLength(256); + b.Property("CreationTime"); + + b.Property("CreatorId"); + + b.Property("DeleterId"); + + b.Property("DeletionTime"); + b.Property("Email") .HasColumnName("Email") .HasMaxLength(256); @@ -93,6 +156,12 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("IsDeleted"); + + b.Property("LastModificationTime"); + + b.Property("LastModifierId"); + b.Property("LockoutEnabled") .ValueGeneratedOnAdd() .HasColumnName("LockoutEnabled") @@ -100,6 +169,10 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations b.Property("LockoutEnd"); + b.Property("Name") + .HasColumnName("Name") + .HasMaxLength(64); + b.Property("NormalizedEmail") .HasColumnName("NormalizedEmail") .HasMaxLength(256); @@ -127,6 +200,10 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations .HasColumnName("SecurityStamp") .HasMaxLength(256); + b.Property("Surname") + .HasColumnName("Surname") + .HasMaxLength(64); + b.Property("TenantId") .HasColumnName("TenantId"); @@ -219,9 +296,10 @@ namespace MyCompanyName.MyProjectName.DemoApp.Migrations b.Property("UserId"); b.Property("LoginProvider") - .HasMaxLength(128); + .HasMaxLength(64); - b.Property("Name"); + b.Property("Name") + .HasMaxLength(128); b.Property("TenantId"); diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj index 054c032e18..c42f5f663c 100644 --- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj +++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj @@ -33,12 +33,4 @@ - - - - - - - - From 67086b466aec9197a54dcd8a0d294efe83547a6a Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Wed, 12 Dec 2018 15:13:28 +0300 Subject: [PATCH 33/36] Update migrations. --- .../20181031075019_Initial.Designer.cs | 526 ------------------ .../20181031081104_Added_Identity.cs | 252 --------- ....cs => 20181212121034_Initial.Designer.cs} | 74 ++- ...9_Initial.cs => 20181212121034_Initial.cs} | 261 +++++++++ .../DemoAppDbContextModelSnapshot.cs | 70 ++- ....cs => 20181212121232_Initial.Designer.cs} | 4 +- ...0_Initial.cs => 20181212121232_Initial.cs} | 5 +- .../DemoAppDbContextModelSnapshot.cs | 2 + 8 files changed, 409 insertions(+), 785 deletions(-) delete mode 100644 templates/service/host/IdentityServerHost/Migrations/20181031075019_Initial.Designer.cs delete mode 100644 templates/service/host/IdentityServerHost/Migrations/20181031081104_Added_Identity.cs rename templates/service/host/IdentityServerHost/Migrations/{20181031081104_Added_Identity.Designer.cs => 20181212121034_Initial.Designer.cs} (91%) rename templates/service/host/IdentityServerHost/Migrations/{20181031075019_Initial.cs => 20181212121034_Initial.cs} (63%) rename templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/{20181030142530_Initial.Designer.cs => 20181212121232_Initial.Designer.cs} (99%) rename templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/{20181030142530_Initial.cs => 20181212121232_Initial.cs} (99%) diff --git a/templates/service/host/IdentityServerHost/Migrations/20181031075019_Initial.Designer.cs b/templates/service/host/IdentityServerHost/Migrations/20181031075019_Initial.Designer.cs deleted file mode 100644 index 6b85820f8a..0000000000 --- a/templates/service/host/IdentityServerHost/Migrations/20181031075019_Initial.Designer.cs +++ /dev/null @@ -1,526 +0,0 @@ -// -using System; -using IdentityServerHost; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace IdentityServerHost.Migrations -{ - [DbContext(typeof(DemoAppDbContext))] - [Migration("20181031075019_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.1.1-rtm-30846") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Enabled"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.ToTable("IdentityServerApiResources"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => - { - b.Property("ApiResourceId"); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("ApiResourceId", "Type"); - - b.ToTable("IdentityServerApiClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => - { - b.Property("ApiResourceId"); - - b.Property("Name") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("DisplayName") - .HasMaxLength(128); - - b.Property("Emphasize"); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("ApiResourceId", "Name"); - - b.ToTable("IdentityServerApiScopes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => - { - b.Property("ApiResourceId"); - - b.Property("Name") - .HasMaxLength(196); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("ApiResourceId", "Name", "Type"); - - b.ToTable("IdentityServerApiScopeClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => - { - b.Property("ApiResourceId"); - - b.Property("Type") - .HasMaxLength(32); - - b.Property("Value") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("Expiration"); - - b.HasKey("ApiResourceId", "Type", "Value"); - - b.ToTable("IdentityServerApiSecrets"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AbsoluteRefreshTokenLifetime"); - - b.Property("AccessTokenLifetime"); - - b.Property("AccessTokenType"); - - b.Property("AllowAccessTokensViaBrowser"); - - b.Property("AllowOfflineAccess"); - - b.Property("AllowPlainTextPkce"); - - b.Property("AllowRememberConsent"); - - b.Property("AlwaysIncludeUserClaimsInIdToken"); - - b.Property("AlwaysSendClientClaims"); - - b.Property("AuthorizationCodeLifetime"); - - b.Property("BackChannelLogoutSessionRequired"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ClientName") - .HasMaxLength(200); - - b.Property("ClientUri") - .HasMaxLength(2000); - - b.Property("ConsentLifetime"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("EnableLocalLogin"); - - b.Property("Enabled"); - - b.Property("FrontChannelLogoutSessionRequired"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("IdentityTokenLifetime"); - - b.Property("IncludeJwtId"); - - b.Property("LogoUri") - .HasMaxLength(2000); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200); - - b.Property("RefreshTokenExpiration"); - - b.Property("RefreshTokenUsage"); - - b.Property("RequireClientSecret"); - - b.Property("RequireConsent"); - - b.Property("RequirePkce"); - - b.Property("SlidingRefreshTokenLifetime"); - - b.Property("UpdateAccessTokenClaimsOnRefresh"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("IdentityServerClients"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClientId"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("IdentityServerClientClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => - { - b.Property("ClientId"); - - b.Property("Origin") - .HasMaxLength(150); - - b.HasKey("ClientId", "Origin"); - - b.ToTable("IdentityServerClientCorsOrigins"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => - { - b.Property("ClientId"); - - b.Property("GrantType") - .HasMaxLength(196); - - b.HasKey("ClientId", "GrantType"); - - b.ToTable("IdentityServerClientGrantTypes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => - { - b.Property("ClientId"); - - b.Property("Provider") - .HasMaxLength(64); - - b.HasKey("ClientId", "Provider"); - - b.ToTable("IdentityServerClientIdPRestrictions"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => - { - b.Property("ClientId"); - - b.Property("PostLogoutRedirectUri") - .HasMaxLength(2000); - - b.HasKey("ClientId", "PostLogoutRedirectUri"); - - b.ToTable("IdentityServerClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => - { - b.Property("ClientId"); - - b.Property("Key") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("ClientId", "Key"); - - b.ToTable("IdentityServerClientProperties"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => - { - b.Property("ClientId"); - - b.Property("RedirectUri") - .HasMaxLength(2000); - - b.HasKey("ClientId", "RedirectUri"); - - b.ToTable("IdentityServerClientRedirectUris"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => - { - b.Property("ClientId"); - - b.Property("Scope") - .HasMaxLength(196); - - b.HasKey("ClientId", "Scope"); - - b.ToTable("IdentityServerClientScopes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => - { - b.Property("ClientId"); - - b.Property("Type") - .HasMaxLength(32); - - b.Property("Value") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("Expiration"); - - b.HasKey("ClientId", "Type", "Value"); - - b.ToTable("IdentityServerClientSecrets"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Grants.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("CreationTime"); - - b.Property("Data") - .IsRequired(); - - b.Property("Expiration"); - - b.Property("Id"); - - b.Property("SubjectId") - .HasMaxLength(200); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50); - - b.HasKey("Key"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.ToTable("IdentityServerPersistedGrants"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => - { - b.Property("IdentityResourceId"); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("IdentityResourceId", "Type"); - - b.ToTable("IdentityServerIdentityClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Enabled"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.ToTable("IdentityServerIdentityResources"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiScope") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId", "Name") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/templates/service/host/IdentityServerHost/Migrations/20181031081104_Added_Identity.cs b/templates/service/host/IdentityServerHost/Migrations/20181031081104_Added_Identity.cs deleted file mode 100644 index e0f5642cd7..0000000000 --- a/templates/service/host/IdentityServerHost/Migrations/20181031081104_Added_Identity.cs +++ /dev/null @@ -1,252 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace IdentityServerHost.Migrations -{ - public partial class Added_Identity : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AbpClaimTypes", - columns: table => new - { - Id = table.Column(nullable: false), - Name = table.Column(maxLength: 256, nullable: false), - Required = table.Column(nullable: false), - IsStatic = table.Column(nullable: false), - Regex = table.Column(maxLength: 512, nullable: true), - RegexDescription = table.Column(maxLength: 128, nullable: true), - Description = table.Column(maxLength: 256, nullable: true), - ValueType = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpRoles", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - Name = table.Column(maxLength: 256, nullable: false), - NormalizedName = table.Column(maxLength: 256, nullable: false), - ConcurrencyStamp = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpUsers", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - UserName = table.Column(maxLength: 256, nullable: false), - NormalizedUserName = table.Column(maxLength: 256, nullable: false), - Email = table.Column(maxLength: 256, nullable: true), - NormalizedEmail = table.Column(maxLength: 256, nullable: true), - EmailConfirmed = table.Column(nullable: false, defaultValue: false), - PasswordHash = table.Column(maxLength: 256, nullable: true), - SecurityStamp = table.Column(maxLength: 256, nullable: false), - ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), - PhoneNumber = table.Column(maxLength: 16, nullable: true), - PhoneNumberConfirmed = table.Column(nullable: false, defaultValue: false), - TwoFactorEnabled = table.Column(nullable: false, defaultValue: false), - LockoutEnd = table.Column(nullable: true), - LockoutEnabled = table.Column(nullable: false, defaultValue: false), - AccessFailedCount = table.Column(nullable: false, defaultValue: 0), - ExtraProperties = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUsers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpRoleClaims", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - ClaimType = table.Column(maxLength: 256, nullable: false), - ClaimValue = table.Column(maxLength: 1024, nullable: true), - RoleId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AbpRoleClaims_AbpRoles_RoleId", - column: x => x.RoleId, - principalTable: "AbpRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpUserClaims", - columns: table => new - { - Id = table.Column(nullable: false), - TenantId = table.Column(nullable: true), - ClaimType = table.Column(maxLength: 256, nullable: false), - ClaimValue = table.Column(maxLength: 1024, nullable: true), - UserId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AbpUserClaims_AbpUsers_UserId", - column: x => x.UserId, - principalTable: "AbpUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpUserLogins", - columns: table => new - { - TenantId = table.Column(nullable: true), - UserId = table.Column(nullable: false), - LoginProvider = table.Column(maxLength: 64, nullable: false), - ProviderKey = table.Column(maxLength: 196, nullable: false), - ProviderDisplayName = table.Column(maxLength: 128, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); - table.ForeignKey( - name: "FK_AbpUserLogins_AbpUsers_UserId", - column: x => x.UserId, - principalTable: "AbpUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpUserRoles", - columns: table => new - { - TenantId = table.Column(nullable: true), - UserId = table.Column(nullable: false), - RoleId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AbpUserRoles_AbpRoles_RoleId", - column: x => x.RoleId, - principalTable: "AbpRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AbpUserRoles_AbpUsers_UserId", - column: x => x.UserId, - principalTable: "AbpUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AbpUserTokens", - columns: table => new - { - TenantId = table.Column(nullable: true), - UserId = table.Column(nullable: false), - LoginProvider = table.Column(maxLength: 64, nullable: false), - Name = table.Column(maxLength: 128, nullable: false), - Value = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AbpUserTokens_AbpUsers_UserId", - column: x => x.UserId, - principalTable: "AbpUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AbpRoleClaims_RoleId", - table: "AbpRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpRoles_NormalizedName", - table: "AbpRoles", - column: "NormalizedName"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUserClaims_UserId", - table: "AbpUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUserLogins_LoginProvider_ProviderKey", - table: "AbpUserLogins", - columns: new[] { "LoginProvider", "ProviderKey" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpUserRoles_RoleId_UserId", - table: "AbpUserRoles", - columns: new[] { "RoleId", "UserId" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpUsers_Email", - table: "AbpUsers", - column: "Email"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUsers_NormalizedEmail", - table: "AbpUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUsers_NormalizedUserName", - table: "AbpUsers", - column: "NormalizedUserName"); - - migrationBuilder.CreateIndex( - name: "IX_AbpUsers_UserName", - table: "AbpUsers", - column: "UserName"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AbpClaimTypes"); - - migrationBuilder.DropTable( - name: "AbpRoleClaims"); - - migrationBuilder.DropTable( - name: "AbpUserClaims"); - - migrationBuilder.DropTable( - name: "AbpUserLogins"); - - migrationBuilder.DropTable( - name: "AbpUserRoles"); - - migrationBuilder.DropTable( - name: "AbpUserTokens"); - - migrationBuilder.DropTable( - name: "AbpRoles"); - - migrationBuilder.DropTable( - name: "AbpUsers"); - } - } -} diff --git a/templates/service/host/IdentityServerHost/Migrations/20181031081104_Added_Identity.Designer.cs b/templates/service/host/IdentityServerHost/Migrations/20181212121034_Initial.Designer.cs similarity index 91% rename from templates/service/host/IdentityServerHost/Migrations/20181031081104_Added_Identity.Designer.cs rename to templates/service/host/IdentityServerHost/Migrations/20181212121034_Initial.Designer.cs index e3603c4fec..63b2af58a7 100644 --- a/templates/service/host/IdentityServerHost/Migrations/20181031081104_Added_Identity.Designer.cs +++ b/templates/service/host/IdentityServerHost/Migrations/20181212121034_Initial.Designer.cs @@ -10,8 +10,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace IdentityServerHost.Migrations { [DbContext(typeof(DemoAppDbContext))] - [Migration("20181031081104_Added_Identity")] - partial class Added_Identity + [Migration("20181212121034_Initial")] + partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { @@ -26,9 +26,18 @@ namespace IdentityServerHost.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + b.Property("Description") .HasMaxLength(256); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("IsStatic"); b.Property("Name") @@ -55,7 +64,23 @@ namespace IdentityServerHost.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("ConcurrencyStamp"); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnName("IsStatic"); b.Property("Name") .IsRequired() @@ -108,10 +133,19 @@ namespace IdentityServerHost.Migrations .HasDefaultValue(0); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() .IsRequired() .HasColumnName("ConcurrencyStamp") .HasMaxLength(256); + b.Property("CreationTime"); + + b.Property("CreatorId"); + + b.Property("DeleterId"); + + b.Property("DeletionTime"); + b.Property("Email") .HasColumnName("Email") .HasMaxLength(256); @@ -124,6 +158,12 @@ namespace IdentityServerHost.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("IsDeleted"); + + b.Property("LastModificationTime"); + + b.Property("LastModifierId"); + b.Property("LockoutEnabled") .ValueGeneratedOnAdd() .HasColumnName("LockoutEnabled") @@ -131,6 +171,10 @@ namespace IdentityServerHost.Migrations b.Property("LockoutEnd"); + b.Property("Name") + .HasColumnName("Name") + .HasMaxLength(64); + b.Property("NormalizedEmail") .HasColumnName("NormalizedEmail") .HasMaxLength(256); @@ -158,6 +202,10 @@ namespace IdentityServerHost.Migrations .HasColumnName("SecurityStamp") .HasMaxLength(256); + b.Property("Surname") + .HasColumnName("Surname") + .HasMaxLength(64); + b.Property("TenantId") .HasColumnName("TenantId"); @@ -269,6 +317,8 @@ namespace IdentityServerHost.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp"); + b.Property("Description") .HasMaxLength(1000); @@ -277,6 +327,9 @@ namespace IdentityServerHost.Migrations b.Property("Enabled"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -400,6 +453,8 @@ namespace IdentityServerHost.Migrations b.Property("ClientUri") .HasMaxLength(2000); + b.Property("ConcurrencyStamp"); + b.Property("ConsentLifetime"); b.Property("Description") @@ -409,6 +464,9 @@ namespace IdentityServerHost.Migrations b.Property("Enabled"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("FrontChannelLogoutSessionRequired"); b.Property("FrontChannelLogoutUri") @@ -589,6 +647,8 @@ namespace IdentityServerHost.Migrations .IsRequired() .HasMaxLength(200); + b.Property("ConcurrencyStamp"); + b.Property("CreationTime"); b.Property("Data") @@ -596,6 +656,9 @@ namespace IdentityServerHost.Migrations b.Property("Expiration"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("Id"); b.Property("SubjectId") @@ -629,6 +692,8 @@ namespace IdentityServerHost.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp"); + b.Property("Description") .HasMaxLength(1000); @@ -639,6 +704,9 @@ namespace IdentityServerHost.Migrations b.Property("Enabled"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("Name") .IsRequired() .HasMaxLength(200); diff --git a/templates/service/host/IdentityServerHost/Migrations/20181031075019_Initial.cs b/templates/service/host/IdentityServerHost/Migrations/20181212121034_Initial.cs similarity index 63% rename from templates/service/host/IdentityServerHost/Migrations/20181031075019_Initial.cs rename to templates/service/host/IdentityServerHost/Migrations/20181212121034_Initial.cs index 106f351d90..cab668b256 100644 --- a/templates/service/host/IdentityServerHost/Migrations/20181031075019_Initial.cs +++ b/templates/service/host/IdentityServerHost/Migrations/20181212121034_Initial.cs @@ -7,11 +7,88 @@ namespace IdentityServerHost.Migrations { protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), + Name = table.Column(maxLength: 256, nullable: false), + Required = table.Column(nullable: false), + IsStatic = table.Column(nullable: false), + Regex = table.Column(maxLength: 512, nullable: true), + RegexDescription = table.Column(maxLength: 128, nullable: true), + Description = table.Column(maxLength: 256, nullable: true), + ValueType = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), + TenantId = table.Column(nullable: true), + Name = table.Column(maxLength: 256, nullable: false), + NormalizedName = table.Column(maxLength: 256, nullable: false), + IsDefault = table.Column(nullable: false), + IsStatic = table.Column(nullable: false), + IsPublic = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(maxLength: 256, nullable: false), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + UserName = table.Column(maxLength: 256, nullable: false), + NormalizedUserName = table.Column(maxLength: 256, nullable: false), + Name = table.Column(maxLength: 64, nullable: true), + Surname = table.Column(maxLength: 64, nullable: true), + Email = table.Column(maxLength: 256, nullable: true), + NormalizedEmail = table.Column(maxLength: 256, nullable: true), + EmailConfirmed = table.Column(nullable: false, defaultValue: false), + PasswordHash = table.Column(maxLength: 256, nullable: true), + SecurityStamp = table.Column(maxLength: 256, nullable: false), + PhoneNumber = table.Column(maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false, defaultValue: false), + TwoFactorEnabled = table.Column(nullable: false, defaultValue: false), + LockoutEnd = table.Column(nullable: true), + LockoutEnabled = table.Column(nullable: false, defaultValue: false), + AccessFailedCount = table.Column(nullable: false, defaultValue: 0) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }); + migrationBuilder.CreateTable( name: "IdentityServerApiResources", columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), Name = table.Column(maxLength: 200, nullable: false), DisplayName = table.Column(maxLength: 200, nullable: true), Description = table.Column(maxLength: 1000, nullable: true), @@ -27,6 +104,8 @@ namespace IdentityServerHost.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), ClientId = table.Column(maxLength: 200, nullable: false), ClientName = table.Column(maxLength: 200, nullable: true), Description = table.Column(maxLength: 1000, nullable: true), @@ -72,6 +151,8 @@ namespace IdentityServerHost.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), Name = table.Column(maxLength: 200, nullable: false), DisplayName = table.Column(maxLength: 200, nullable: true), Description = table.Column(maxLength: 1000, nullable: true), @@ -90,6 +171,8 @@ namespace IdentityServerHost.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), Key = table.Column(maxLength: 200, nullable: false), Type = table.Column(maxLength: 50, nullable: false), SubjectId = table.Column(maxLength: 200, nullable: true), @@ -103,6 +186,115 @@ namespace IdentityServerHost.Migrations table.PrimaryKey("PK_IdentityServerPersistedGrants", x => x.Key); }); + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(nullable: false), + TenantId = table.Column(nullable: true), + ClaimType = table.Column(maxLength: 256, nullable: false), + ClaimValue = table.Column(maxLength: 1024, nullable: true), + RoleId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(nullable: false), + TenantId = table.Column(nullable: true), + ClaimType = table.Column(maxLength: 256, nullable: false), + ClaimValue = table.Column(maxLength: 1024, nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + TenantId = table.Column(nullable: true), + UserId = table.Column(nullable: false), + LoginProvider = table.Column(maxLength: 64, nullable: false), + ProviderKey = table.Column(maxLength: 196, nullable: false), + ProviderDisplayName = table.Column(maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + TenantId = table.Column(nullable: true), + UserId = table.Column(nullable: false), + RoleId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + TenantId = table.Column(nullable: true), + UserId = table.Column(nullable: false), + LoginProvider = table.Column(maxLength: 64, nullable: false), + Name = table.Column(maxLength: 128, nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "IdentityServerApiClaims", columns: table => new @@ -370,6 +562,51 @@ namespace IdentityServerHost.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + migrationBuilder.CreateIndex( name: "IX_IdentityServerClientClaims_ClientId", table: "IdentityServerClientClaims", @@ -389,6 +626,24 @@ namespace IdentityServerHost.Migrations protected override void Down(MigrationBuilder migrationBuilder) { + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + migrationBuilder.DropTable( name: "IdentityServerApiClaims"); @@ -431,6 +686,12 @@ namespace IdentityServerHost.Migrations migrationBuilder.DropTable( name: "IdentityServerPersistedGrants"); + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + migrationBuilder.DropTable( name: "IdentityServerApiScopes"); diff --git a/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs b/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs index ab3992ccf8..8961166967 100644 --- a/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs +++ b/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs @@ -24,9 +24,18 @@ namespace IdentityServerHost.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + b.Property("Description") .HasMaxLength(256); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("IsStatic"); b.Property("Name") @@ -53,7 +62,23 @@ namespace IdentityServerHost.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("ConcurrencyStamp"); + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnName("IsStatic"); b.Property("Name") .IsRequired() @@ -106,10 +131,19 @@ namespace IdentityServerHost.Migrations .HasDefaultValue(0); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() .IsRequired() .HasColumnName("ConcurrencyStamp") .HasMaxLength(256); + b.Property("CreationTime"); + + b.Property("CreatorId"); + + b.Property("DeleterId"); + + b.Property("DeletionTime"); + b.Property("Email") .HasColumnName("Email") .HasMaxLength(256); @@ -122,6 +156,12 @@ namespace IdentityServerHost.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("IsDeleted"); + + b.Property("LastModificationTime"); + + b.Property("LastModifierId"); + b.Property("LockoutEnabled") .ValueGeneratedOnAdd() .HasColumnName("LockoutEnabled") @@ -129,6 +169,10 @@ namespace IdentityServerHost.Migrations b.Property("LockoutEnd"); + b.Property("Name") + .HasColumnName("Name") + .HasMaxLength(64); + b.Property("NormalizedEmail") .HasColumnName("NormalizedEmail") .HasMaxLength(256); @@ -156,6 +200,10 @@ namespace IdentityServerHost.Migrations .HasColumnName("SecurityStamp") .HasMaxLength(256); + b.Property("Surname") + .HasColumnName("Surname") + .HasMaxLength(64); + b.Property("TenantId") .HasColumnName("TenantId"); @@ -267,6 +315,8 @@ namespace IdentityServerHost.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp"); + b.Property("Description") .HasMaxLength(1000); @@ -275,6 +325,9 @@ namespace IdentityServerHost.Migrations b.Property("Enabled"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -398,6 +451,8 @@ namespace IdentityServerHost.Migrations b.Property("ClientUri") .HasMaxLength(2000); + b.Property("ConcurrencyStamp"); + b.Property("ConsentLifetime"); b.Property("Description") @@ -407,6 +462,9 @@ namespace IdentityServerHost.Migrations b.Property("Enabled"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("FrontChannelLogoutSessionRequired"); b.Property("FrontChannelLogoutUri") @@ -587,6 +645,8 @@ namespace IdentityServerHost.Migrations .IsRequired() .HasMaxLength(200); + b.Property("ConcurrencyStamp"); + b.Property("CreationTime"); b.Property("Data") @@ -594,6 +654,9 @@ namespace IdentityServerHost.Migrations b.Property("Expiration"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("Id"); b.Property("SubjectId") @@ -627,6 +690,8 @@ namespace IdentityServerHost.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("ConcurrencyStamp"); + b.Property("Description") .HasMaxLength(1000); @@ -637,6 +702,9 @@ namespace IdentityServerHost.Migrations b.Property("Enabled"); + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + b.Property("Name") .IsRequired() .HasMaxLength(200); diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181030142530_Initial.Designer.cs b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181212121232_Initial.Designer.cs similarity index 99% rename from templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181030142530_Initial.Designer.cs rename to templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181212121232_Initial.Designer.cs index 201b429008..1644e14900 100644 --- a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181030142530_Initial.Designer.cs +++ b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181212121232_Initial.Designer.cs @@ -10,7 +10,7 @@ using MyCompanyName.MyProjectName.Host; namespace MyCompanyName.MyProjectName.Host.Migrations { [DbContext(typeof(DemoAppDbContext))] - [Migration("20181030142530_Initial")] + [Migration("20181212121232_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -42,6 +42,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasColumnName("Comments") .HasMaxLength(256); + b.Property("ConcurrencyStamp"); + b.Property("Exceptions") .HasColumnName("Exceptions") .HasMaxLength(4000); diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181030142530_Initial.cs b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181212121232_Initial.cs similarity index 99% rename from templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181030142530_Initial.cs rename to templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181212121232_Initial.cs index 268d53bf1b..c191391cc9 100644 --- a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181030142530_Initial.cs +++ b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20181212121232_Initial.cs @@ -12,6 +12,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations columns: table => new { Id = table.Column(nullable: false), + ExtraProperties = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), UserId = table.Column(nullable: true), UserName = table.Column(maxLength: 256, nullable: true), TenantId = table.Column(nullable: true), @@ -26,8 +28,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations Url = table.Column(maxLength: 256, nullable: true), Exceptions = table.Column(maxLength: 4000, nullable: true), Comments = table.Column(maxLength: 256, nullable: true), - HttpStatusCode = table.Column(nullable: true), - ExtraProperties = table.Column(nullable: true) + HttpStatusCode = table.Column(nullable: true) }, constraints: table => { diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/DemoAppDbContextModelSnapshot.cs b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/DemoAppDbContextModelSnapshot.cs index a7dbc673c8..69e2cc0ae2 100644 --- a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/DemoAppDbContextModelSnapshot.cs +++ b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/DemoAppDbContextModelSnapshot.cs @@ -40,6 +40,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasColumnName("Comments") .HasMaxLength(256); + b.Property("ConcurrencyStamp"); + b.Property("Exceptions") .HasColumnName("Exceptions") .HasMaxLength(4000); From bde0a71fbbd810d378e13e1dadf8e8185c13db89 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Wed, 12 Dec 2018 15:23:12 +0300 Subject: [PATCH 34/36] fixes volosoft/vs-internal#524. filtering fixed it was broken because of the previous commits while refactoring. --- .../app/Volo.DocsTestApp/package-lock.json | 116 ++++++++++++++++++ .../Pages/Documents/Project/index.js | 2 +- .../Pages/Documents/Shared/Scripts/vs.js | 59 +++++---- .../docs/src/Volo.Docs.Web/package-lock.json | 3 + 4 files changed, 149 insertions(+), 31 deletions(-) create mode 100644 modules/docs/src/Volo.Docs.Web/package-lock.json diff --git a/modules/docs/app/Volo.DocsTestApp/package-lock.json b/modules/docs/app/Volo.DocsTestApp/package-lock.json index 859670c604..a666d3cc7c 100644 --- a/modules/docs/app/Volo.DocsTestApp/package-lock.json +++ b/modules/docs/app/Volo.DocsTestApp/package-lock.json @@ -4,6 +4,15 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@abp/anchor-js": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@abp/anchor-js/-/anchor-js-0.5.1.tgz", + "integrity": "sha512-9N/iPP9tDdq9lKRNFQuqRL+QYSv5fq789KgHHGG1/MqExJ6KTPcqUDHvQ53kz96pUgJA+Fyn3dpwgPqLVYI3Yg==", + "requires": { + "@abp/core": "^0.4.9", + "anchor-js": "^4.1.1" + } + }, "@abp/aspnetcore.mvc.ui": { "version": "0.4.9", "resolved": "https://registry.npmjs.org/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-0.4.9.tgz", @@ -52,6 +61,15 @@ "bootstrap": "^4.1.1" } }, + "@abp/clipboard": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@abp/clipboard/-/clipboard-0.5.1.tgz", + "integrity": "sha512-efOPloVL0moRqGpAMA7DU5o+vzzu7ipGOFcG9nOfDD6uGY9AsOztFc71GwIFrtwADvJSiJHD6OfEIfR++dCT0w==", + "requires": { + "@abp/core": "^0.4.9", + "clipboard": "^2.0.4" + } + }, "@abp/core": { "version": "0.4.9", "resolved": "https://registry.npmjs.org/@abp/core/-/core-0.4.9.tgz", @@ -75,6 +93,18 @@ "datatables.net-bs4": "^1.10.16" } }, + "@abp/docs": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@abp/docs/-/docs-0.5.1.tgz", + "integrity": "sha512-3pGYnxZxm2kYPfu2EwDF0QinsNTym2cWlYAo7mVUBuReTPMhwHYtgrE7AX3nCVv1iAo6ltW+mebonGt1s5yXzA==", + "requires": { + "@abp/anchor-js": "^0.5.1", + "@abp/clipboard": "^0.5.1", + "@abp/malihu-custom-scrollbar-plugin": "^0.5.1", + "@abp/popper.js": "^0.5.1", + "@abp/prismjs": "^0.5.1" + } + }, "@abp/font-awesome": { "version": "0.4.9", "resolved": "https://registry.npmjs.org/@abp/font-awesome/-/font-awesome-0.4.9.tgz", @@ -136,6 +166,33 @@ } } }, + "@abp/malihu-custom-scrollbar-plugin": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-0.5.1.tgz", + "integrity": "sha512-i9XorWsWcqb3tbbiwvE4OQCfXXJO38HlkQgvlwzxshB8xDcS9v/JL5fAAvM/Cr66fB2zybsrCseq9QcBXL+yCQ==", + "requires": { + "@abp/core": "^0.4.9", + "malihu-custom-scrollbar-plugin": "^3.1.5" + } + }, + "@abp/popper.js": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@abp/popper.js/-/popper.js-0.5.1.tgz", + "integrity": "sha512-qS97hQQtG78mVPRvmZZtBb7Vu905NpThl9PN3jPWWDiVbOV2/d+BXCTRhTRbfdup3C5cmGdntjaGxfcxlxHt1Q==", + "requires": { + "@abp/core": "^0.4.9", + "popper.js": "^1.14.6" + } + }, + "@abp/prismjs": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@abp/prismjs/-/prismjs-0.5.1.tgz", + "integrity": "sha512-DxoidAVV8LmtgFonbzGJEfszQDUaHEQc+/bcJtyQCuv5l+uflVnpAH+6W8IAErt5N96a0RJbeV9ZBXjIhqOzpA==", + "requires": { + "@abp/core": "^0.4.9", + "prismjs": "^1.15.0" + } + }, "@abp/select2": { "version": "0.4.9", "resolved": "https://registry.npmjs.org/@abp/select2/-/select2-0.4.9.tgz", @@ -177,6 +234,11 @@ "resolved": "https://registry.npmjs.org/almond/-/almond-0.3.3.tgz", "integrity": "sha1-oOfJWsdiTWQXtElLHmi/9pMWiiA=" }, + "anchor-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/anchor-js/-/anchor-js-4.1.1.tgz", + "integrity": "sha512-c2Wl9F1X0C4jkYKLla1SNE2uI6xJrSKsRC7HCCg4yLNQ5sL5D+tDEWrjRaoTuTlMTqBCnF6kOuR3dx59Erxpvw==" + }, "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -413,6 +475,16 @@ } } }, + "clipboard": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", + "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -537,6 +609,11 @@ } } }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, "deprecated": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", @@ -947,6 +1024,14 @@ "sparkles": "^1.0.0" } }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "requires": { + "delegate": "^3.1.2" + } + }, "graceful-fs": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", @@ -1413,6 +1498,14 @@ "kind-of": "^6.0.2" } }, + "malihu-custom-scrollbar-plugin": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz", + "integrity": "sha1-MQzsxeWUFaHCnp37XStuAdZqKe8=", + "requires": { + "jquery-mousewheel": ">=3.0.6" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -1715,6 +1808,11 @@ "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" }, + "popper.js": { + "version": "1.14.6", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz", + "integrity": "sha512-AGwHGQBKumlk/MDfrSOf0JHhJCImdDMcGNoqKmKkU+68GFazv3CQ6q9r7Ja1sKDZmYWTckY/uLyEznheTDycnA==" + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -1725,6 +1823,14 @@ "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" }, + "prismjs": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.15.0.tgz", + "integrity": "sha512-Lf2JrFYx8FanHrjoV5oL8YHCclLQgbJcVZR+gikGGMqz6ub5QVWDTM6YIwm3BuPxM/LOV+rKns3LssXNLIf+DA==", + "requires": { + "clipboard": "^2.0.0" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -1854,6 +1960,11 @@ "ret": "~0.1.10" } }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" + }, "select2": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.5.tgz", @@ -2150,6 +2261,11 @@ "jquery": ">=1.2.3" } }, + "tiny-emitter": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", + "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==" + }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js index 0ac501cc94..e202c6b7d1 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js @@ -23,12 +23,12 @@ }; var filterDocumentItems = function (filterText) { - $navigation.find(".mCSB_container .opened").removeClass("opened"); $navigation.find(".mCSB_container > li, .mCSB_container > li ul").hide(); if (!filterText) { $navigation.find(".mCSB_container > li").show(); + $navigation.find(".mCSB_container .selected-tree > ul").show(); return; } diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Scripts/vs.js b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Scripts/vs.js index 5eb102473f..482e50700d 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Scripts/vs.js +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Scripts/vs.js @@ -4,6 +4,7 @@ $(this).parent().children('ul.tree').toggle(100); $(this).closest("li").toggleClass("selected-tree"); }); + $('li:not(.last-link) span.plus-icon i.fa-chevron-right').click(function () { var $element = $(this).parent(); @@ -33,44 +34,42 @@ return false; }); - var navSelector = '#docs-sticky-index'; - var $myNav = $(navSelector); - Toc.init($myNav); - $('body').scrollspy({ - target: $myNav - }); - $("#docs-sticky-index a").on('click', function (event) { - if (this.hash !== "") { - event.preventDefault(); - var hash = this.hash; - $('html, body').animate({ - scrollTop: $(hash).offset().top - }, 500, function () { - window.location.hash = hash; - }); - } - }); + $(document).ready(function () { + var $myNav = $("#docs-sticky-index"); + Toc.init($myNav); + $("body").scrollspy({ + target: $myNav + }); - $('.btn-toggle').on("click", function () { - $(".toggle-row").slideToggle(400); - $(this).toggleClass("less"); - }); + $("#docs-sticky-index a").on('click', function (event) { + if (this.hash !== "") { + event.preventDefault(); + var hash = this.hash; + $('html, body').animate({ + scrollTop: $(hash).offset().top + }, 500, function () { + window.location.hash = hash; + }); + } + }); - $('.close-mmenu').on("click", function () { - $(".navbar-collapse").removeClass("show"); - }); + $(".btn-toggle").on("click", function () { + $(".toggle-row").slideToggle(400); + $(this).toggleClass("less"); + }); - $('.open-dmenu').on("click", function () { - $(".docs-tree-list").slideToggle(); - }); + $(".close-mmenu").on("click", function () { + $(".navbar-collapse").removeClass("show"); + }); + + $(".open-dmenu").on("click", function () { + $(".docs-tree-list").slideToggle(); + }); - $(window).on("load", function () { $("#sidebar-scroll").mCustomScrollbar({ theme: "minimal" }); - }); - $(window).on("load", function () { $("#scroll-index").mCustomScrollbar({ theme: "minimal-dark" }); diff --git a/modules/docs/src/Volo.Docs.Web/package-lock.json b/modules/docs/src/Volo.Docs.Web/package-lock.json new file mode 100644 index 0000000000..48e341a095 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +} From 0405476eabb45b16259c5af052d1d8bfe12805a9 Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Wed, 12 Dec 2018 17:01:12 +0300 Subject: [PATCH 35/36] #203 Implement caching for settings --- .../PermissionGrantCacheItem.cs | 2 +- .../Volo.Abp.SettingManagement.Domain.csproj | 1 + .../AbpSettingManagementDomainModule.cs | 12 ++-- .../Volo/Abp/SettingManagement/Setting.cs | 1 + .../Abp/SettingManagement/SettingCacheItem.cs | 25 ++++++++ .../SettingCacheItemInvalidator.cs | 34 +++++++++++ .../Abp/SettingManagement/SettingStore.cs | 61 ++++++++++++++----- 7 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingCacheItem.cs create mode 100644 modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingCacheItemInvalidator.cs diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItem.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItem.cs index 285bc117bc..e4d3f1648e 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItem.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItem.cs @@ -5,7 +5,7 @@ namespace Volo.Abp.PermissionManagement [Serializable] public class PermissionGrantCacheItem { - public string Name { get; set; } + public string Name { get; set; } //TODO: Consider to remove this public bool IsGranted { get; set; } diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.csproj b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.csproj index d0ccb910af..8345be068a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.csproj +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo.Abp.SettingManagement.Domain.csproj @@ -18,6 +18,7 @@ + diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementDomainModule.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementDomainModule.cs index 9280008eac..0ddc49b076 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementDomainModule.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/AbpSettingManagementDomainModule.cs @@ -1,12 +1,16 @@ -using Volo.Abp.Domain; +using Volo.Abp.Caching; +using Volo.Abp.Domain; using Volo.Abp.Modularity; using Volo.Abp.Settings; namespace Volo.Abp.SettingManagement { - [DependsOn(typeof(AbpSettingsModule))] - [DependsOn(typeof(AbpDddDomainModule))] - [DependsOn(typeof(AbpSettingManagementDomainSharedModule))] + [DependsOn( + typeof(AbpSettingsModule), + typeof(AbpDddDomainModule), + typeof(AbpSettingManagementDomainSharedModule), + typeof(AbpCachingModule) + )] public class AbpSettingManagementDomainModule : AbpModule { diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/Setting.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/Setting.cs index e875004e52..78e7b3e70c 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/Setting.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/Setting.cs @@ -4,6 +4,7 @@ using Volo.Abp.Domain.Entities; namespace Volo.Abp.SettingManagement { + //TODO: Convert to AggregateRoot public class Setting : Entity { [NotNull] diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingCacheItem.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingCacheItem.cs new file mode 100644 index 0000000000..a590775167 --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingCacheItem.cs @@ -0,0 +1,25 @@ +using System; + +namespace Volo.Abp.SettingManagement +{ + [Serializable] + public class SettingCacheItem + { + public string Value { get; set; } + + public SettingCacheItem() + { + + } + + public SettingCacheItem(string value) + { + Value = value; + } + + public static string CalculateCacheKey(string name, string providerName, string providerKey) + { + return "pn:" + providerName + ",pk:" + providerKey + ",n:" + name; + } + } +} diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingCacheItemInvalidator.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingCacheItemInvalidator.cs new file mode 100644 index 0000000000..35d358a67d --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingCacheItemInvalidator.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.EventBus; + +namespace Volo.Abp.SettingManagement +{ + public class SettingCacheItemInvalidator : ILocalEventHandler>, ITransientDependency + { + protected IDistributedCache Cache { get; } + + public SettingCacheItemInvalidator(IDistributedCache cache) + { + Cache = cache; + } + + public virtual async Task HandleEventAsync(EntityChangedEventData eventData) + { + var cacheKey = CalculateCacheKey( + eventData.Entity.Name, + eventData.Entity.ProviderName, + eventData.Entity.ProviderKey + ); + + await Cache.RemoveAsync(cacheKey); + } + + protected virtual string CalculateCacheKey(string name, string providerName, string providerKey) + { + return SettingCacheItem.CalculateCacheKey(name, providerName, providerKey); + } + } +} diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingStore.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingStore.cs index 0be50a921c..f95887658d 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingStore.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingStore.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Volo.Abp.Caching; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.Settings; @@ -9,49 +10,81 @@ namespace Volo.Abp.SettingManagement { public class SettingStore : ISettingStore, ITransientDependency { - private readonly ISettingRepository _settingRepository; - private readonly IGuidGenerator _guidGenerator; + protected IDistributedCache Cache { get; } + protected ISettingRepository SettingRepository { get; } + protected IGuidGenerator GuidGenerator { get; } - public SettingStore(ISettingRepository settingRepository, IGuidGenerator guidGenerator) + public SettingStore( + ISettingRepository settingRepository, + IGuidGenerator guidGenerator, + IDistributedCache cache) { - _settingRepository = settingRepository; - _guidGenerator = guidGenerator; + SettingRepository = settingRepository; + GuidGenerator = guidGenerator; + Cache = cache; } public async Task GetOrNullAsync(string name, string providerName, string providerKey) { - var setting = await _settingRepository.FindAsync(name, providerName, providerKey); - return setting?.Value; + var cacheItem = await GetCacheItemAsync(name, providerName, providerKey); + return cacheItem.Value; } public async Task SetAsync(string name, string value, string providerName, string providerKey) { - var setting = await _settingRepository.FindAsync(name, providerName, providerKey); + var setting = await SettingRepository.FindAsync(name, providerName, providerKey); if (setting == null) { - setting = new Setting(_guidGenerator.Create(), name, value, providerName, providerKey); - await _settingRepository.InsertAsync(setting); + setting = new Setting(GuidGenerator.Create(), name, value, providerName, providerKey); + await SettingRepository.InsertAsync(setting); } else { setting.Value = value; - await _settingRepository.UpdateAsync(setting); + await SettingRepository.UpdateAsync(setting); } } public async Task> GetListAsync(string providerName, string providerKey) { - var settings = await _settingRepository.GetListAsync(providerName, providerKey); + var settings = await SettingRepository.GetListAsync(providerName, providerKey); return settings.Select(s => new SettingValue(s.Name, s.Value)).ToList(); } public async Task DeleteAsync(string name, string providerName, string providerKey) { - var setting = await _settingRepository.FindAsync(name, providerName, providerKey); + var setting = await SettingRepository.FindAsync(name, providerName, providerKey); if (setting != null) { - await _settingRepository.DeleteAsync(setting); + await SettingRepository.DeleteAsync(setting); } } + + protected virtual async Task GetCacheItemAsync(string name, string providerName, string providerKey) + { + var cacheKey = CalculateCacheKey(name, providerName, providerKey); + var cacheItem = await Cache.GetAsync(cacheKey); + + if (cacheItem != null) + { + return cacheItem; + } + + var setting = await SettingRepository.FindAsync(name, providerName, providerKey); + + cacheItem = new SettingCacheItem(setting?.Value); + + await Cache.SetAsync( + cacheKey, + cacheItem + ); + + return cacheItem; + } + + protected virtual string CalculateCacheKey(string name, string providerName, string providerKey) + { + return SettingCacheItem.CalculateCacheKey(name, providerName, providerKey); + } } } From 8f5b7177aad5ece24091929d402d92f026dc1b40 Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Wed, 12 Dec 2018 17:30:18 +0300 Subject: [PATCH 36/36] #203 Setting Management Enhancements --- framework/Volo.Abp.sln | 7 ++++ .../Permissions/PermissionDefinition.cs | 3 ++ .../Volo.Abp.Localization.Abstractions.csproj | 20 +++++++++++ .../AbpLocalizationAbstractionsModule.cs | 9 +++++ .../Localization/FixedLocalizableString.cs | 0 .../Abp/Localization/ILocalizableString.cs | 0 .../Volo.Abp.Localization.csproj | 1 + .../Abp/Localization/AbpLocalizationModule.cs | 6 ++-- .../Volo.Abp.Settings.csproj | 4 +-- .../Volo/Abp/Settings/AbpSettingsModule.cs | 6 +++- .../Volo/Abp/Settings/SettingDefinition.cs | 36 ++++++++++++++----- 11 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 framework/src/Volo.Abp.Localization.Abstractions/Volo.Abp.Localization.Abstractions.csproj create mode 100644 framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/AbpLocalizationAbstractionsModule.cs rename framework/src/{Volo.Abp.Localization => Volo.Abp.Localization.Abstractions}/Volo/Abp/Localization/FixedLocalizableString.cs (100%) rename framework/src/{Volo.Abp.Localization => Volo.Abp.Localization.Abstractions}/Volo/Abp/Localization/ILocalizableString.cs (100%) diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index e4b3d032a4..d6518a0af3 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -212,6 +212,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EntityFrameworkCore.PostgreSql", "src\Volo.Abp.EntityFrameworkCore.PostgreSql\Volo.Abp.EntityFrameworkCore.PostgreSql.csproj", "{882E82F1-1A57-4BB9-B126-4CBF700C8F0C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Localization.Abstractions", "src\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj", "{20513A4E-FAC7-4106-8976-5D79A3BDFED1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -598,6 +600,10 @@ Global {882E82F1-1A57-4BB9-B126-4CBF700C8F0C}.Debug|Any CPU.Build.0 = Debug|Any CPU {882E82F1-1A57-4BB9-B126-4CBF700C8F0C}.Release|Any CPU.ActiveCfg = Release|Any CPU {882E82F1-1A57-4BB9-B126-4CBF700C8F0C}.Release|Any CPU.Build.0 = Release|Any CPU + {20513A4E-FAC7-4106-8976-5D79A3BDFED1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20513A4E-FAC7-4106-8976-5D79A3BDFED1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20513A4E-FAC7-4106-8976-5D79A3BDFED1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20513A4E-FAC7-4106-8976-5D79A3BDFED1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -700,6 +706,7 @@ Global {D3E07597-BB3D-4249-B873-607E2C128C0E} = {447C8A77-E5F0-4538-8687-7383196D04EA} {77A621CF-9562-411B-A707-C7C02CC3B8FA} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {882E82F1-1A57-4BB9-B126-4CBF700C8F0C} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {20513A4E-FAC7-4106-8976-5D79A3BDFED1} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs index 5b48e6101b..d7913f0d2d 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs @@ -28,6 +28,9 @@ namespace Volo.Abp.Authorization.Permissions public IReadOnlyList Children => _children.ToImmutableList(); private readonly List _children; + /// + /// Can be used to get/set custom properties for this permission definition. + /// public Dictionary Properties { get; } /// diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Volo.Abp.Localization.Abstractions.csproj b/framework/src/Volo.Abp.Localization.Abstractions/Volo.Abp.Localization.Abstractions.csproj new file mode 100644 index 0000000000..b4df348774 --- /dev/null +++ b/framework/src/Volo.Abp.Localization.Abstractions/Volo.Abp.Localization.Abstractions.csproj @@ -0,0 +1,20 @@ + + + + + + netstandard2.0 + Volo.Abp.Localization.Abstractions + Volo.Abp.Localization.Abstractions + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/AbpLocalizationAbstractionsModule.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/AbpLocalizationAbstractionsModule.cs new file mode 100644 index 0000000000..0008b7d1bc --- /dev/null +++ b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/AbpLocalizationAbstractionsModule.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.Localization +{ + public class AbpLocalizationAbstractionsModule : AbpModule + { + + } +} diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/FixedLocalizableString.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/FixedLocalizableString.cs similarity index 100% rename from framework/src/Volo.Abp.Localization/Volo/Abp/Localization/FixedLocalizableString.cs rename to framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/FixedLocalizableString.cs diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizableString.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/ILocalizableString.cs similarity index 100% rename from framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizableString.cs rename to framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/ILocalizableString.cs diff --git a/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj b/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj index 0acdb08627..a512bfc580 100644 --- a/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj +++ b/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj @@ -22,6 +22,7 @@ + diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationModule.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationModule.cs index c94d881030..3fcd90ac6d 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationModule.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationModule.cs @@ -1,5 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Localization.Resources.AbpValidation; +using Volo.Abp.Localization.Resources.AbpValidation; using Volo.Abp.Modularity; using Volo.Abp.Settings; using Volo.Abp.VirtualFileSystem; @@ -8,7 +7,8 @@ namespace Volo.Abp.Localization { [DependsOn( typeof(AbpVirtualFileSystemModule), - typeof(AbpSettingsModule) + typeof(AbpSettingsModule), + typeof(AbpLocalizationAbstractionsModule) )] public class AbpLocalizationModule : AbpModule { diff --git a/framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj b/framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj index 5d5da4549f..6ba4d46c1f 100644 --- a/framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj +++ b/framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj @@ -1,4 +1,4 @@ - + @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingsModule.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingsModule.cs index ae6d61b0c8..8900e8e0a3 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingsModule.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingsModule.cs @@ -1,7 +1,11 @@ -using Volo.Abp.Modularity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; namespace Volo.Abp.Settings { + [DependsOn( + typeof(AbpLocalizationAbstractionsModule) + )] public class AbpSettingsModule : AbpModule { diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs index d65d143362..58726492c6 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs @@ -1,15 +1,32 @@ -namespace Volo.Abp.Settings +using System.Collections.Generic; +using JetBrains.Annotations; +using Volo.Abp.Localization; + +namespace Volo.Abp.Settings { public class SettingDefinition { /// /// Unique name of the setting. /// + [NotNull] public string Name { get; } + [NotNull] + public ILocalizableString DisplayName + { + get => _displayName; + set => _displayName = Check.NotNull(value, nameof(value)); + } + private ILocalizableString _displayName; + + [CanBeNull] + public ILocalizableString Description { get; set; } + /// /// Default value of the setting. /// + [CanBeNull] public string DefaultValue { get; set; } /// @@ -26,24 +43,27 @@ public bool IsInherited { get; set; } /// - /// Can be used to store a custom object related to this setting. + /// Can be used to get/set custom properties for this setting definition. /// - public object CustomData { get; set; } //TODO: Convert to dictionary! - - //TODO: Add Properties dictionary for custom stuff (and remove CustomData) + [NotNull] + public Dictionary Properties { get; } public SettingDefinition( string name, string defaultValue = null, + ILocalizableString displayName = null, + ILocalizableString description = null, bool isVisibleToClients = false, - bool isInherited = true, - object customData = null) + bool isInherited = true) { Name = name; DefaultValue = defaultValue; IsVisibleToClients = isVisibleToClients; + DisplayName = displayName ?? new FixedLocalizableString(name); + Description = description; IsInherited = isInherited; - CustomData = customData; + + Properties = new Dictionary(); } } } \ No newline at end of file