From 1fb6b1343440ca8192c097f9618bcf0c8c9371aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BA=AE?= Date: Fri, 31 May 2019 19:10:05 +0800 Subject: [PATCH 01/75] feature: implement the interfaces for reading/writing LDAP. include: Authenticate Query Organizations Add Organization Query Users Query User --- framework/Volo.Abp.sln | 18 +- .../src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj | 24 ++ .../Volo/Abp/Ldap/AbpLdapModule.cs | 18 + .../OrganizationNotExistException.cs | 11 + .../Volo/Abp/Ldap/ILdapManager.cs | 72 ++++ .../Volo/Abp/Ldap/LdapCredentials.cs | 9 + .../Volo.Abp.Ldap/Volo/Abp/Ldap/LdapHelps.cs | 34 ++ .../Volo/Abp/Ldap/LdapManager.cs | 332 ++++++++++++++++++ .../Volo/Abp/Ldap/LdapOptions.cs | 24 ++ .../Volo/Abp/Ldap/Modeling/ILdapEntry.cs | 11 + .../Abp/Ldap/Modeling/ILdapOrganization.cs | 7 + .../Volo/Abp/Ldap/Modeling/ILdapUser.cs | 11 + .../Volo/Abp/Ldap/Modeling/LdapEntryBase.cs | 24 ++ .../Abp/Ldap/Modeling/LdapOrganization.cs | 17 + .../Volo/Abp/Ldap/Modeling/LdapUser.cs | 25 ++ framework/src/Volo.Abp.Ldap/readme.md | 173 +++++++++ .../Volo.Abp.Ldap.Tests.csproj | 18 + .../Volo/Abp/Ldap/Authenticate_Tests.cs | 70 ++++ .../Volo/Abp/Ldap/LdapHelps_Tests.cs | 84 +++++ .../Volo/Abp/Ldap/LdapManager_Tests.cs | 245 +++++++++++++ .../Volo/Abp/Ldap/LdapTestData.cs | 27 ++ 21 files changed, 1252 insertions(+), 2 deletions(-) create mode 100644 framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Exceptions/OrganizationNotExistException.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapCredentials.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapHelps.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapOptions.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapEntry.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapOrganization.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapUser.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapEntryBase.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapOrganization.cs create mode 100644 framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapUser.cs create mode 100644 framework/src/Volo.Abp.Ldap/readme.md create mode 100644 framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj create mode 100644 framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/Authenticate_Tests.cs create mode 100644 framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapHelps_Tests.cs create mode 100644 framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs create mode 100644 framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapTestData.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index be77f0ab24..42e4b28516 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.168 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28922.388 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}" EndProject @@ -238,6 +238,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Dashboards", "src\Volo.Abp.AspNetCore.Mvc.UI.Dashboards\Volo.Abp.AspNetCore.Mvc.UI.Dashboards.csproj", "{054D766D-5992-460E-A4D8-936D80BE2C1A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ldap", "src\Volo.Abp.Ldap\Volo.Abp.Ldap.csproj", "{4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ldap.Tests", "test\Volo.Abp.Ldap.Tests\Volo.Abp.Ldap.Tests.csproj", "{38FB8F75-426E-4265-8D0E-E121837B6FCC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -708,6 +712,14 @@ Global {054D766D-5992-460E-A4D8-936D80BE2C1A}.Debug|Any CPU.Build.0 = Debug|Any CPU {054D766D-5992-460E-A4D8-936D80BE2C1A}.Release|Any CPU.ActiveCfg = Release|Any CPU {054D766D-5992-460E-A4D8-936D80BE2C1A}.Release|Any CPU.Build.0 = Release|Any CPU + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F}.Release|Any CPU.Build.0 = Release|Any CPU + {38FB8F75-426E-4265-8D0E-E121837B6FCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38FB8F75-426E-4265-8D0E-E121837B6FCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38FB8F75-426E-4265-8D0E-E121837B6FCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38FB8F75-426E-4265-8D0E-E121837B6FCC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -829,6 +841,8 @@ Global {F006B0B4-F25D-4511-9FB3-F17AA44BDCEA} = {447C8A77-E5F0-4538-8687-7383196D04EA} {EE1AAB08-3FBD-487F-B0B4-BEBA4B69528A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {054D766D-5992-460E-A4D8-936D80BE2C1A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {4DADBBD2-4C63-4C90-9661-EBF6252A7D6F} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {38FB8F75-426E-4265-8D0E-E121837B6FCC} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj b/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj new file mode 100644 index 0000000000..6b1cba1094 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj @@ -0,0 +1,24 @@ + + + + + + netstandard2.0 + Volo.Abp.Ldap + Volo.Abp.Ldap + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + + + + + diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs new file mode 100644 index 0000000000..22b9ca7a76 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/AbpLdapModule.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace Volo.Abp.Ldap +{ + [DependsOn( + typeof(AbpAutofacModule) + )] + public class AbpLdapModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + Configure(configuration.GetSection("LDAP")); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Exceptions/OrganizationNotExistException.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Exceptions/OrganizationNotExistException.cs new file mode 100644 index 0000000000..9d7fb220cc --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Exceptions/OrganizationNotExistException.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.Ldap.Exceptions +{ + public class OrganizationNotExistException : BusinessException + { + public OrganizationNotExistException(string distinguishedName) + : base("LDAP:000001", $"the organization distinguished named {distinguishedName} does not exist.") + { + + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs new file mode 100644 index 0000000000..f14e88b409 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/ILdapManager.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using Volo.Abp.Ldap.Modeling; + +namespace Volo.Abp.Ldap +{ + public interface ILdapManager + { + /// + /// query the specified organizations. + /// + /// filter: (&(name=xxx)(objectClass=organizationalUnit)) when name is not null + /// filter: (&(name=*)(objectClass=organizationalUnit)) when name is null + /// + /// + /// + /// + IList GetOrganizations(string name = null); + + /// + /// query the specified organization. + /// + /// filter: (&(distinguishedName=xxx)(objectClass=organizationalUnit)) when organizationName is not null + /// + /// + /// + /// + LdapOrganization GetOrganization(string distinguishedName); + + void AddSubOrganization(string organizationName, LdapOrganization parentOrganization); + void AddSubOrganization(string organizationName, string parentDistinguishedName); + + /// + /// query the specified users. + /// + /// filter: (&(name=xxx)(objectCategory=person)(objectClass=user)) when name is not null + /// filter: (&(name=*)(objectCategory=person)(objectClass=user)) when name is null + /// + /// filter: (&(displayName=xxx)(objectCategory=person)(objectClass=user)) when displayName is not null + /// filter: (&(displayName=*)(objectCategory=person)(objectClass=user)) when displayName is null + /// + /// filter: (&(cn=xxx)(objectCategory=person)(objectClass=user)) when commonName is not null + /// filter: (&(cn=*)(objectCategory=person)(objectClass=user)) when commonName is null + /// + /// + /// + /// + /// + /// + IList GetUsers(string name = null, string displayName = null, string commonName = null); + + /// + /// query the specified User. + /// + /// filter: (&(distinguishedName=xxx)(objectCategory=person)(objectClass=user)) when distinguishedName is not null + /// + /// + /// + /// + LdapUser GetUser(string distinguishedName); + + void AddUserToOrganization(string userName, string password, LdapOrganization parentOrganization); + void AddUserToOrganization(string userName, string password, string parentDistinguishedName); + + /// + /// Authenticate + /// + /// E.g administrator@yourdomain.com.cn + /// + /// + bool Authenticate(string userDomainName, string password); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapCredentials.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapCredentials.cs new file mode 100644 index 0000000000..a2d2eefd74 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapCredentials.cs @@ -0,0 +1,9 @@ +namespace Volo.Abp.Ldap +{ + public class LdapCredentials + { + public string DomainUserName { get; set; } + + public string Password { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapHelps.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapHelps.cs new file mode 100644 index 0000000000..49a60a964f --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapHelps.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace Volo.Abp.Ldap +{ + public static class LdapHelps + { + public static string BuildCondition(string name, string value) + { + return string.IsNullOrWhiteSpace(value) ? "" : $"({name}={value})"; + } + + public static string BuildFilter(Dictionary conditions) + { + if (null == conditions ) + { + conditions = new Dictionary(); + } + + if (conditions.Keys.Count == 0) + { + conditions.Add("objectClass", "*"); // add default condition + } + + var subFilter = string.Empty; + foreach (var keyValuePair in conditions) + { + subFilter += BuildCondition(keyValuePair.Key, keyValuePair.Value); + } + + return $"(&{subFilter})"; + } + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs new file mode 100644 index 0000000000..615b22d70e --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapManager.cs @@ -0,0 +1,332 @@ +using System; +using Microsoft.Extensions.Options; +using Novell.Directory.Ldap; +using System.Collections.Generic; +using System.Text; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ldap.Exceptions; +using Volo.Abp.Ldap.Modeling; + +namespace Volo.Abp.Ldap +{ + public class LdapManager : ILdapManager, ITransientDependency + { + private readonly string _searchBase; + private readonly LdapOptions _ldapOptions; + + private readonly string[] _attributes = + { + "objectCategory", "objectClass", "cn", "name", "distinguishedName", + "ou", + "sAMAccountName", "userPrincipalName", "telephoneNumber", "mail" + }; + + public LdapManager(IOptions ldapSettingsOptions) + { + _ldapOptions = ldapSettingsOptions.Value; + _searchBase = _ldapOptions.SearchBase; + } + + #region Organization + /// + /// query the specified organizations. + /// + /// filter: (&(name=xxx)(objectClass=organizationalUnit)) when name is not null + /// filter: (&(objectClass=organizationalUnit)) when name is null + /// + /// + /// + /// + public IList GetOrganizations(string name = null) + { + var conditions = new Dictionary + { + {"name", name}, + {"objectClass", "organizationalUnit"}, + }; + return Query(_searchBase, conditions); + } + + /// + /// query the specified organization. + /// + /// filter: (&(distinguishedName=xxx)(objectClass=organizationalUnit)) when organizationName is not null + /// + /// + /// + /// + public LdapOrganization GetOrganization(string distinguishedName) + { + distinguishedName = Check.NotNullOrWhiteSpace(distinguishedName, nameof(distinguishedName)); + var conditions = new Dictionary + { + {"distinguishedName", distinguishedName}, + {"objectClass", "organizationalUnit"}, + }; + return QueryOne(_searchBase, conditions); + } + + public void AddSubOrganization(string organizationName, LdapOrganization parentOrganization) + { + organizationName = Check.NotNullOrWhiteSpace(organizationName, nameof(organizationName)); + var dn = $"OU={organizationName},{parentOrganization.DistinguishedName}"; + + var attributeSet = new LdapAttributeSet + { + new LdapAttribute("objectCategory", $"CN=Organizational-Unit,CN=Schema,CN=Configuration,{_ldapOptions.DomainDistinguishedName}"), + new LdapAttribute("objectClass", new[] {"top", "organizationalUnit"}), + new LdapAttribute("name", organizationName), + }; + + var newEntry = new LdapEntry(dn, attributeSet); + + using (var ldapConnection = GetConnection()) + { + ldapConnection.Add(newEntry); + } + } + + public void AddSubOrganization(string organizationName, string parentDistinguishedName) + { + organizationName = Check.NotNullOrWhiteSpace(organizationName, nameof(organizationName)); + parentDistinguishedName = + Check.NotNullOrWhiteSpace(parentDistinguishedName, nameof(parentDistinguishedName)); + + var parentOrganization = GetOrganization(parentDistinguishedName); + if (null == parentOrganization) + { + throw new OrganizationNotExistException(parentDistinguishedName); + } + + AddSubOrganization(organizationName, parentOrganization); + } + + #endregion + + #region User + /// + /// query the specified users. + /// + /// filter: (&(name=xxx)(objectCategory=person)(objectClass=user)) when name is not null + /// filter: (&(objectCategory=person)(objectClass=user)) when name is null + /// + /// filter: (&(displayName=xxx)(objectCategory=person)(objectClass=user)) when displayName is not null + /// filter: (&(objectCategory=person)(objectClass=user)) when displayName is null + /// + /// filter: (&(cn=xxx)(objectCategory=person)(objectClass=user)) when commonName is not null + /// filter: (&(objectCategory=person)(objectClass=user)) when commonName is null + /// + /// + /// + /// + /// + /// + public IList GetUsers(string name = null, string displayName = null, string commonName = null) + { + var conditions = new Dictionary + { + {"objectCategory", "person"}, + {"objectClass", "user"}, + {"name", name}, + {"displayName", displayName}, + {"cn", commonName}, + }; + return Query(_searchBase, conditions); + } + + /// + /// query the specified User. + /// + /// filter: (&(distinguishedName=xxx)(objectCategory=person)(objectClass=user)) when distinguishedName is not null + /// + /// + /// + /// + public LdapUser GetUser(string distinguishedName) + { + distinguishedName = Check.NotNullOrWhiteSpace(distinguishedName, nameof(distinguishedName)); + var conditions = new Dictionary + { + {"objectCategory", "person"}, + {"objectClass", "user"}, + {"distinguishedName", distinguishedName}, + }; + return QueryOne(_searchBase, conditions); + } + + public void AddUserToOrganization(string userName, string password, LdapOrganization parentOrganization) + { + var dn = $"CN={userName},{parentOrganization.DistinguishedName}"; + var mail = $"{userName}@{_ldapOptions.DomainName}"; + sbyte[] encodedBytes = SupportClass.ToSByteArray(Encoding.Unicode.GetBytes($"\"{password}\"")); + + var attributeSet = new LdapAttributeSet + { + new LdapAttribute("instanceType", "4"), + new LdapAttribute("objectCategory", $"CN=Person,CN=Schema,CN=Configuration,{_ldapOptions.DomainDistinguishedName}"), + new LdapAttribute("objectClass", new[] {"top", "person", "organizationalPerson", "user"}), + new LdapAttribute("name", userName), + new LdapAttribute("cn", userName), + new LdapAttribute("sAMAccountName", userName), + new LdapAttribute("userPrincipalName", userName), + new LdapAttribute("sn", userName), + new LdapAttribute("displayName", userName), + new LdapAttribute("unicodePwd", encodedBytes), + new LdapAttribute("userAccountControl", "512"), + new LdapAttribute("mail", mail), + }; + var newEntry = new LdapEntry(dn, attributeSet); + + using (var ldapConnection = GetConnection()) + { + ldapConnection.Add(newEntry); + } + } + + public void AddUserToOrganization(string userName, string password, string parentDistinguishedName) + { + var dn = $"CN={userName},{parentDistinguishedName}"; + var mail = $"{userName}@{_ldapOptions.DomainName}"; + sbyte[] encodedBytes = SupportClass.ToSByteArray(Encoding.Unicode.GetBytes($"\"{password}\"")); + + var attributeSet = new LdapAttributeSet + { + new LdapAttribute("instanceType", "4"), + new LdapAttribute("objectCategory", $"CN=Person,CN=Schema,CN=Configuration,{_ldapOptions.DomainDistinguishedName}"), + new LdapAttribute("objectClass", new[] {"top", "person", "organizationalPerson", "user"}), + new LdapAttribute("name", userName), + new LdapAttribute("cn", userName), + new LdapAttribute("sAMAccountName", userName), + new LdapAttribute("userPrincipalName", userName), + new LdapAttribute("sn", userName), + new LdapAttribute("displayName", userName), + new LdapAttribute("unicodePwd", encodedBytes), + new LdapAttribute("userAccountControl", "512"), + new LdapAttribute("mail", mail), + }; + var newEntry = new LdapEntry(dn, attributeSet); + + using (var ldapConnection = GetConnection()) + { + ldapConnection.Add(newEntry); + } + } + + #endregion + + #region Authenticate + + /// + /// Authenticate + /// + /// E.g administrator@yourdomain.com.cn + /// + /// + public bool Authenticate(string userDomainName, string password) + { + try + { + using (GetConnection(userDomainName, password)) + { + return true; + } + } + catch (Exception ) + { + return false; + } + } + + #endregion + + private ILdapConnection GetConnection(string bindUserName = null, string bindUserPassword = null) + { + // bindUserName/bindUserPassword only be used when authenticate + bindUserName = bindUserName ?? _ldapOptions.Credentials.DomainUserName; + bindUserPassword = bindUserPassword ?? _ldapOptions.Credentials.Password; + + var ldapConnection = new LdapConnection() { SecureSocketLayer = _ldapOptions.UseSsl }; + if (_ldapOptions.UseSsl) + { + ldapConnection.UserDefinedServerCertValidationDelegate += (sender, certificate, chain, sslPolicyErrors) => true; + } + ldapConnection.Connect(_ldapOptions.ServerHost, _ldapOptions.ServerPort); + + if (_ldapOptions.UseSsl) + { + ldapConnection.Bind(LdapConnection.Ldap_V3, bindUserName, bindUserPassword); + } + else + { + ldapConnection.Bind(bindUserName, bindUserPassword); + } + return ldapConnection; + } + + private IList Query(string searchBase, Dictionary conditions) where T : class, ILdapEntry + { + var filter = LdapHelps.BuildFilter(conditions); + + var result = new List(); + + using (var ldapConnection = GetConnection()) + { + var search = ldapConnection.Search(searchBase, LdapConnection.SCOPE_SUB, filter, + _attributes, false, null, null); + + LdapMessage message; + while ((message = search.getResponse()) != null) + { + if (!(message is LdapSearchResult searchResultMessage)) + { + continue; + } + var entry = searchResultMessage.Entry; + if (typeof(T) == typeof(LdapOrganization)) + { + result.Add(new LdapOrganization(entry.getAttributeSet()) as T); + } + + if (typeof(T) == typeof(LdapUser)) + { + result.Add(new LdapUser(entry.getAttributeSet()) as T); + } + } + } + return result; + } + + private T QueryOne(string searchBase, Dictionary conditions) where T : class, ILdapEntry + { + var filter = LdapHelps.BuildFilter(conditions); + + using (var ldapConnection = GetConnection()) + { + var search = ldapConnection.Search(searchBase, LdapConnection.SCOPE_SUB, filter, + _attributes, false, null, null); + + LdapMessage message; + while ((message = search.getResponse()) != null) + { + if (!(message is LdapSearchResult searchResultMessage)) + { + continue; + } + var entry = searchResultMessage.Entry; + if (typeof(T) == typeof(LdapOrganization)) + { + return new LdapOrganization(entry.getAttributeSet()) as T; + } + + if (typeof(T) == typeof(LdapUser)) + { + return new LdapUser(entry.getAttributeSet()) as T; + } + return null; + } + } + return null; + } + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapOptions.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapOptions.cs new file mode 100644 index 0000000000..7e4aacfa0e --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapOptions.cs @@ -0,0 +1,24 @@ +namespace Volo.Abp.Ldap +{ + public class LdapOptions + { + public string ServerHost { get; set; } + + public int ServerPort { get; set; } + + public bool UseSsl { get; set; } + + public string SearchBase { get; set; } + + public string DomainName { get; set; } + + public string DomainDistinguishedName { get; set; } + + public LdapCredentials Credentials { get; set; } + + public LdapOptions() + { + Credentials = new LdapCredentials(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapEntry.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapEntry.cs new file mode 100644 index 0000000000..f15775fc06 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapEntry.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.Ldap.Modeling +{ + public interface ILdapEntry + { + string ObjectCategory { get; set; } + string[] ObjectClass { get; set; } + string Name { get; set; } + string DistinguishedName { get; set; } + string CommonName { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapOrganization.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapOrganization.cs new file mode 100644 index 0000000000..07c11000e8 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapOrganization.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Ldap.Modeling +{ + public interface ILdapOrganization : ILdapEntry + { + string OrganizationUnit { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapUser.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapUser.cs new file mode 100644 index 0000000000..8ef68f6607 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/ILdapUser.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.Ldap.Modeling +{ + public interface ILdapUser : ILdapEntry + { + string SamAccountName { get; set; } + string UserPrincipalName { get; set; } + string DisplayName { get; set; } + string Email { get; set; } + string Phone { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapEntryBase.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapEntryBase.cs new file mode 100644 index 0000000000..6658a983d0 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapEntryBase.cs @@ -0,0 +1,24 @@ +using Novell.Directory.Ldap; + +namespace Volo.Abp.Ldap.Modeling +{ + public abstract class LdapEntryBase : ILdapEntry + { + public string ObjectCategory { get; set; } + public string[] ObjectClass { get; set; } + public string Name { get; set; } + public string CommonName { get; set; } + public string DistinguishedName { get; set; } + + protected LdapEntryBase() { } + + protected LdapEntryBase(LdapAttributeSet attributeSet) + { + ObjectCategory = attributeSet.getAttribute("objectCategory")?.StringValue; + ObjectClass = attributeSet.getAttribute("objectClass")?.StringValueArray; + Name = attributeSet.getAttribute("name")?.StringValue; + CommonName = attributeSet.getAttribute("cn")?.StringValue; + DistinguishedName = attributeSet.getAttribute("distinguishedName")?.StringValue; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapOrganization.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapOrganization.cs new file mode 100644 index 0000000000..e401a2514d --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapOrganization.cs @@ -0,0 +1,17 @@ +using Novell.Directory.Ldap; + +namespace Volo.Abp.Ldap.Modeling +{ + public class LdapOrganization : LdapEntryBase, ILdapOrganization + { + public string OrganizationUnit { get; set; } + + public LdapOrganization() { } + + public LdapOrganization(LdapAttributeSet attributeSet) + : base(attributeSet) + { + OrganizationUnit = attributeSet.getAttribute("ou")?.StringValue; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapUser.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapUser.cs new file mode 100644 index 0000000000..d9f554d512 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Modeling/LdapUser.cs @@ -0,0 +1,25 @@ +using Novell.Directory.Ldap; + +namespace Volo.Abp.Ldap.Modeling +{ + public class LdapUser : LdapEntryBase, ILdapUser + { + public string SamAccountName { get; set; } + public string UserPrincipalName { get; set; } + public string DisplayName { get; set; } + public string Email { get; set; } + public string Phone { get; set; } + + public LdapUser() { } + + public LdapUser( LdapAttributeSet attributeSet) + : base(attributeSet) + { + SamAccountName = attributeSet.getAttribute("sAMAccountName")?.StringValue; + UserPrincipalName = attributeSet.getAttribute("userPrincipalName")?.StringValue; + DisplayName = attributeSet.getAttribute("displayName")?.StringValue; + Email = attributeSet.getAttribute("mail")?.StringValue; + Phone = attributeSet.getAttribute("telephoneNumber")?.StringValue; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/readme.md b/framework/src/Volo.Abp.Ldap/readme.md new file mode 100644 index 0000000000..af86f64e99 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/readme.md @@ -0,0 +1,173 @@ +# Volo.Abp.Ldap + +# Only Authenticate(not read/write AD) + +## Configure + +add section in `appsettings.json` + +### use SSL + +```json +"LDAP": { + "ServerHost": "192.168.101.54", + "ServerPort": 636, + "UseSSL": true +} +``` + +### not use SSL + +```json +"LDAP": { + "ServerHost": "192.168.101.54", + "ServerPort": 389, + "UseSSL": false +} +``` + +## Authenticate + + Injecting `ILdapManager` into a class. For example: + +```csharp +public class TaxAppService : ApplicationService +{ + private readonly ILdapManager _ldapManager; + + public TaxAppService(ILdapManager ldapManager) + { + _ldapManager = ldapManager; + } + + public void Authenticate(string userName, string password) + { + var result = _ldapManager.Authenticate(userName, password); + } +} +``` + +- `userName` must be full domain name. E.g abc@abc.com + +# Read/Write AD + +## Configure + +### use SSL + +```json +"LDAP": { + "ServerHost": "192.168.101.54", + "ServerPort": 636, + "UseSSL": true, + "Credentials": { + "DomainUserName": "administrator@yourdomain.com.cn", + "Password": "yH.20190528" + }, + "SearchBase": "DC=yourdomain,DC=com,DC=cn", + "DomainName": "yourdomain.com.cn", + "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" +} +``` + +### not use SSL + +```json +"LDAP": { + "ServerHost": "192.168.101.54", + "ServerPort": 389, + "UseSSL": false, + "Credentials": { + "DomainUserName": "administrator@yourdomain.com.cn", + "Password": "yH.20190528" + }, + "SearchBase": "DC=yourdomain,DC=com,DC=cn", + "DomainName": "yourdomain.com.cn", + "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" +} +``` + +- `Credentials:DomainUserName` a administrator of AD. + +- `Credentials:Password` the password for the administrator. +- `SearchBase`: where search from AD. +- `DomainName`: name of you domain. no need `www`. +- `DomainDistinguishedName`: distinguished name of root domain. + +## Query Organizations + +```cs +// query all organizations +// filter: (&(objectClass=organizationalUnit)) +_ldapManager.GetOrganizations(); + +// query organizations by name +// filter: (&(name=abc)(objectClass=organizationalUnit)) +_ldapManager.GetOrganizations("abc"); + +``` + +## Query Organization + +```csharp +// query organization by distinguished name +// filter: (&(distinguishedName=abc)(objectClass=organizationalUnit)) +_ldapManager.GetOrganization("abc"); + +``` + +## Add Organization + +```csharp +// use LdapOrganization +_ldapManager.AddSubOrganization("nameA", parentOrganization); + +// or use OrganizationDistinguishedName +_ldapManager.AddSubOrganization("nameA", "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"); +``` + +## Query Users + +```cs +// query all users +// filter: (&(objectCategory=person)(objectClass=user)) +_ldapManager.GetUsers(); + +// query organizations by name +// filter: (&(name=abc)(objectCategory=person)(objectClass=user)) +_ldapManager.GetUsers(name : "abc"); + +// query organizations by displayName +// filter: (&(displayName=abc)(objectCategory=person)(objectClass=user)) +_ldapManager.GetUsers(displayName : "abc"); + +// query organization by commonName +// filter: (&(cn=abc)(objectCategory=person)(objectClass=user)) +_ldapManager.GetUsers(commonName : "abc"); + +``` + +## Query User + +```csharp +// query a user by distinguished name +// filter: (&(distinguishedName=abc)(objectCategory=person)(objectClass=user)) +_ldapManager.GetUser("abc"); + +``` + +## Add User + +```csharp +// use LdapOrganization +_ldapManager.AddUserToOrganization("nameA", "passwordA", parentOrganization); + +// or use OrganizationDistinguishedName +_ldapManager.AddUserToOrganization("nameA", "passwordA", "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"); +``` + +# More see [unit test](../../test/Volo.Abp.Ldap.Tests) + + + +# \ No newline at end of file diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj b/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj new file mode 100644 index 0000000000..e3e1c560c8 --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj @@ -0,0 +1,18 @@ + + + + netcoreapp2.2 + latest + false + + + + + + + + + + + + diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/Authenticate_Tests.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/Authenticate_Tests.cs new file mode 100644 index 0000000000..35f631b8d2 --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/Authenticate_Tests.cs @@ -0,0 +1,70 @@ +using System; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.Ldap +{ + + public class Authenticate_Tests : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + private readonly ILdapManager _ldapManager; + private readonly LdapTestData _testData; + + public Authenticate_Tests() + { + // ReSharper disable once VirtualMemberCallInConstructor + _testData = GetRequiredService(); + _ldapManager = GetRequiredService(); + } + + [Fact(Skip = "need environment AD ")] + public void Authenticate() + { + var result = _ldapManager.Authenticate(_testData.AdministratorDomainName, _testData.AdministratorPassword); + + result.ShouldBeTrue(); + } + + [Fact(Skip = "need environment AD ")] + public void Authenticate_With_Wrong_Password() + { + var result = _ldapManager.Authenticate("NonExistentNameA", "PasswordA"); + + result.ShouldBeFalse(); + } + + [DependsOn(typeof(AbpLdapModule))] + public class TestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + // not use ssl + // "LDAP": { + // "ServerHost": "192.168.101.54", + // "ServerPort": 389, + // "UseSSL": false + // } + + // use ssl + // "LDAP": { + // "ServerHost": "192.168.101.54", + // "ServerPort": 636, + // "UseSSL": true + // } + Configure(settings => + { + settings.ServerHost = "192.168.101.54"; + settings.ServerPort = 636; + settings.UseSsl = true; + }); + } + } + } + +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapHelps_Tests.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapHelps_Tests.cs new file mode 100644 index 0000000000..06d6834992 --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapHelps_Tests.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Ldap +{ + public class LdapHelps_Tests + { + + [Fact] + public void BuildCondition_With_Value() + { + // act + var res = LdapHelps.BuildCondition("objectClass", "testNameA"); + + // assert + res.ShouldBe("(objectClass=testNameA)"); + } + + [Fact] + public void BuildCondition_With_Null_Value() + { + // act + var res = LdapHelps.BuildCondition("objectClass", null); + + // assert + res.ShouldBeEmpty(); + } + + [Fact] + public void BuildCondition_With_Empty_Value() + { + // act + var res = LdapHelps.BuildCondition("objectClass", ""); + + // assert + res.ShouldBeEmpty(); + } + + [Fact] + public void BuildCondition_With_WhiteSpace_Value() + { + // act + var res = LdapHelps.BuildCondition("objectClass", " "); + + // assert + res.ShouldBeEmpty(); + } + + [Fact] + public void BuildFilter_With_Null_Condition() + { + // act + var res = LdapHelps.BuildFilter(null); + + // assert + res.ShouldBe("(&(objectClass=*))"); + } + + [Fact] + public void BuildFilter_With_Empty_Condition() + { + // act + var res = LdapHelps.BuildFilter(new Dictionary()); + + // assert + res.ShouldBe("(&(objectClass=*))"); + } + + [Fact] + public void BuildFilter_With_Condition() + { + // act + var conditions = new Dictionary + { + {"objectClass", "testClassA"}, {"objectCategory", "testCategoryA"}, {"name", null} + }; + var res = LdapHelps.BuildFilter(conditions); + + // assert + res.ShouldBe("(&(objectClass=testClassA)(objectCategory=testCategoryA))"); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs new file mode 100644 index 0000000000..00d9287c4f --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapManager_Tests.cs @@ -0,0 +1,245 @@ +using System; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.Ldap +{ + + public class LdapManager_Tests : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + private readonly ILdapManager _ldapManager; + private readonly LdapTestData _testData; + + public LdapManager_Tests() + { + // ReSharper disable once VirtualMemberCallInConstructor + _testData = GetRequiredService(); + _ldapManager = GetRequiredService(); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganizations_With_Empty_Condition() + { + var result = _ldapManager.GetOrganizations(); + + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == _testData.DomainControllersName); + result.ShouldContain(e => e.DistinguishedName == _testData.DomainControllersDistinguishedName); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganizations_With_Name() + { + var result = _ldapManager.GetOrganizations(_testData.DomainControllersName); + + result.ShouldNotBeNull(); + result.ShouldHaveSingleItem(); + result.ShouldContain(e => e.Name == _testData.DomainControllersName); + result.ShouldContain(e => e.DistinguishedName == _testData.DomainControllersDistinguishedName); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganizations_With_Non_Existent_Name() + { + var result = _ldapManager.GetOrganizations("NonExistentNameA"); + + result.ShouldNotBeNull(); + result.ShouldBeEmpty(); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganization() + { + var result = _ldapManager.GetOrganization(_testData.DomainControllersDistinguishedName); + + result.ShouldNotBeNull(); + result.Name.ShouldBe(_testData.DomainControllersName); + } + + [Fact(Skip = "need environment AD ")] + public void GetOrganization_With_Non_Existent_DistinguishedName() + { + var result = _ldapManager.GetOrganization("NonExistentNameA"); + + result.ShouldBeNull(); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_Empty_Condition() + { + var result = _ldapManager.GetUsers(); + + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == _testData.AdministratorName); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_Name() + { + var result = _ldapManager.GetUsers(name: _testData.AdministratorName); + + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == _testData.AdministratorName); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_Non_Existent_Name() + { + var result = _ldapManager.GetUsers(name: "NonExistentNameA"); + + result.ShouldNotBeNull(); + result.ShouldBeEmpty(); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_CommonName() + { + var result = _ldapManager.GetUsers(commonName: _testData.AdministratorName); + + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == _testData.AdministratorName); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_Non_Existent_CommonName() + { + var result = _ldapManager.GetUsers(commonName: "NonExistentNameA"); + + result.ShouldNotBeNull(); + result.ShouldBeEmpty(); + } + + [Fact(Skip = "need environment AD ")] + public void GetUsers_With_DisplayName() + { + var result = _ldapManager.GetUsers(displayName: _testData.AdministratorName); + + result.ShouldNotBeNull(); + // the administrator in AD. not have display name by default. + result.ShouldBeEmpty(); + } + + [Fact(Skip = "need environment AD ")] + public void GetUser() + { + var result = _ldapManager.GetUser(_testData.AdministratorDistinguishedName); + + result.ShouldNotBeNull(); + result.Name.ShouldBe(_testData.AdministratorName); + } + + [Fact(Skip = "need environment AD ")] + public void GetUser_With_Non_Existent_DistinguishedName() + { + var result = _ldapManager.GetOrganization("NonExistentNameA"); + + result.ShouldBeNull(); + } + + [Fact(Skip = "need environment AD ")] + public void Authenticate() + { + var result = _ldapManager.Authenticate(_testData.AdministratorDomainName, _testData.AdministratorPassword); + + result.ShouldBeTrue(); + } + + [Fact(Skip = "need environment AD ")] + public void Authenticate_With_Wrong_Password() + { + var result = _ldapManager.Authenticate("NonExistentNameA", "PasswordA"); + + result.ShouldBeFalse(); + } + + [Fact(Skip = "need environment AD ")] + public void AddSubOrganization() + { + var parentOrganization = _ldapManager.GetOrganization(_testData.DomainControllersDistinguishedName); + var randomName = $"Test_{DateTime.Now.Ticks}"; + + _ldapManager.AddSubOrganization(randomName, parentOrganization); + + var result = _ldapManager.GetOrganizations(randomName); + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == randomName); + } + + [Fact(Skip = "need environment AD ")] + public void AddSubOrganization_With_DistinguishedName() + { + var randomName = $"Test_{DateTime.Now.Ticks}"; + + _ldapManager.AddSubOrganization(randomName, _testData.DomainControllersDistinguishedName); + + var result = _ldapManager.GetOrganizations(randomName); + result.ShouldNotBeNull(); + result.ShouldContain(e => e.Name == randomName); + } + + [Fact(Skip = "need environment AD ")] + public void AddOrganizationUser() + { + var parentOrganization = _ldapManager.GetOrganization(_testData.DomainControllersDistinguishedName); + var randomName = $"Test_{DateTime.Now:yyMMddHHmmss}"; + _ldapManager.AddUserToOrganization(randomName, _testData.AdministratorPassword, parentOrganization); + + var result = _ldapManager.GetUsers(randomName); + result.ShouldNotBeNull(); + result.ShouldContain(e=>e.Name == randomName); + } + + [DependsOn(typeof(AbpLdapModule))] + public class TestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + // not use ssl + // "LDAP": { + // "ServerHost": "192.168.101.54", + // "ServerPort": 389, + // "UseSSL": false, + // "Credentials": { + // "DomainUserName": "administrator@yourdomain.com.cn", + // "Password": "yH.20190528" + // }, + // "SearchBase": "CN=Users,DC=yourdomain,DC=com,DC=cn", + // "DomainName": "yourdomain.com.cn", + // "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" + // } + + // use ssl + // "LDAP": { + // "ServerHost": "192.168.101.54", + // "ServerPort": 636, + // "UseSSL": true, + // "Credentials": { + // "DomainUserName": "administrator@yourdomain.com.cn", + // "Password": "yH.20190528" + // }, + // "SearchBase": "CN=Users,DC=yourdomain,DC=com,DC=cn", + // "DomainName": "yourdomain.com.cn", + // "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" + // } + Configure(settings => + { + settings.ServerHost = "192.168.101.54"; + settings.ServerPort = 636; + settings.UseSsl = true; + settings.Credentials.DomainUserName = "administrator@yourdomain.com.cn"; + settings.Credentials.Password = "yH.20190528"; + settings.SearchBase = "DC=yourdomain,DC=com,DC=cn"; + settings.DomainName = "yourdomain.com.cn"; + settings.DomainDistinguishedName = "DC=yourdomain,DC=com,DC=cn"; + }); + } + } + } + +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapTestData.cs b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapTestData.cs new file mode 100644 index 0000000000..8224686daa --- /dev/null +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo/Abp/Ldap/LdapTestData.cs @@ -0,0 +1,27 @@ +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Ldap +{ + public class LdapTestData : ISingletonDependency + { + public string AdministratorName { get; } = "Administrator"; + public string AdministratorPassword { get; } = "yH.20190528"; + public string AdministratorDistinguishedName { get; } = "CN=Administrator,CN=Users,DC=yourdomain,DC=com,DC=cn"; + public string AdministratorDomainName { get; } = "Administrator@yourdomain.com.cn"; + + public string DomainControllersName = "Domain Controllers"; + public string DomainControllersDistinguishedName = "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"; + + public string RootDistinguishedName { get; } = "DC=yourdomain,DC=com,DC=cn"; + + public string Organization001Name { get; } = "Test_A"; + + public string Test001Name { get; } = "test001"; + public string Test001Password { get; } = "yH.20190528"; + public string Test001Email { get; } = "test001@yourdomain.com.cn"; + + public string Test002Name { get; } = "test002"; + public string Test002Password { get; } = "yH.20190528"; + public string Test002WrongPassword { get; } = "yH.20190529"; + } +} \ No newline at end of file From c70ab7932b4ab57f69f8d9e142f12d08a6d9acd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 6 Jun 2019 15:08:44 +0300 Subject: [PATCH 02/75] Initial MVC module document. --- docs/en/Startup-Templates/Mvc-Module.md | 88 +++++++++++++++++- docs/en/Startup-Templates/Mvc.md | 10 +- .../issuemanagement-module-solution.png | Bin 0 -> 25772 bytes .../layered-project-dependencies-module.png | Bin 0 -> 38795 bytes 4 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 docs/en/images/issuemanagement-module-solution.png create mode 100644 docs/en/images/layered-project-dependencies-module.png diff --git a/docs/en/Startup-Templates/Mvc-Module.md b/docs/en/Startup-Templates/Mvc-Module.md index b641d78bac..d27c2d3d12 100644 --- a/docs/en/Startup-Templates/Mvc-Module.md +++ b/docs/en/Startup-Templates/Mvc-Module.md @@ -1,6 +1,92 @@ # MVC Module Startup Template -TODO +This template can be used to create a **reusable [application module](../Modules/Index.md)** based on the [module development best practices & conventions](../Best-Practices/Index.md). It is also suitable for creating **microservices** (with or without UI). +## How to Start With? +You can use the [ABP CLI](../CLI.md) to create a new project using this startup template. Alternatively, you can directly create & download from the [Get Started](https://abp.io/get-started) page. CLI approach is used here. +First, install the ABP CLI if you haven't installed before: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +Then use the `abp new` command in an empty folder to create a new solution: + +```bash +abp new Acme.IssueManagement -t mvc-module +``` + +- `Acme.IssueManagement` is the solution name, like *YourCompany.YourProduct*. You can use single level, two-levels or three-levels naming. + +### Without User Interface + +The template comes with a UI by default. You can use `--no-ui` option to not include the UI layer. + +````bash +abp new Acme.IssueManagement -t mvc-module --no-ui +```` + +## Solution Structure + +Based on the options you've specified, you will get a slightly different solution structure. + +### Default Structure + +If you don't specify any option, you will have a solution like shown below: + +![issuemanagement-module-solution](../images/issuemanagement-module-solution.png) + +Projects are organized as `src`, `test` and `host` folders: + +* `src` folder contains the actual module which is layered based on [DDD](../Domain-Driven-Design.md) principles. +* `test` folder contains unit & integration tests. +* `host` folder contains applications with different configurations to demonstrate how to host the module in an application. These are not a part of the module, but useful on development. + +The diagram below shows the layers & project dependencies of the module: + +![layered-project-dependencies-module](../images/layered-project-dependencies-module.png) + +Each section below will explain the related project & its dependencies. + +#### .Domain.Shared Project + +This project contains constants, enums and other objects these are actually a part of the domain layer, but needed to be used by all layers/projects in the solution. + +An `IssueType` enum and an `IssueConts` class (which may have some constant fields for the `Issue` entity, like `MaxTitleLength`) are good candidates for this project. + +- This project has no dependency to other projects in the solution. All other projects depend on this directly or indirectly. + +#### .Domain Project + +This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../Entities.md), [domain services](../Domain-Services.md), [value types](../Value-Types.md), [repository interfaces](../Repositories.md) and other domain objects. + +An `Issue` entity, an `IssueManager` domain service and an `IIssueRepository` interface are good candidates for this project. + +- Depends on the `.Domain.Shared` because it uses constants, enums and other objects defined in that project. + +#### .Application.Contracts Project + +This project mainly contains [application service](../Application-Services.md) **interfaces** and [Data Transfer Objects](../Data-Transfer-Objects.md) (DTO) of the application layer. It does exists to separate interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package. + +An `IIssueAppService` interface and an `IssueCreationDto` class are good candidates for this project. + +- Depends on the `.Domain.Shared` because it may use constants, enums and other shared objects of this project in the application service interfaces and DTOs. + +#### .Application Project + +This project contains the [application service](../Application-Services.md) **implementations** of the interfaces defined in the `.Application.Contracts` project. + +An `IssueAppService` class is a good candidate for this project. + +- Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs. +- Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic. + +#### .EntityFrameworkCore Project + +This is the integration project for the EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project. + +- Depends on the `.Domain` project to be able to reference to entities and repository interfaces. + +> You can delete this project if you don't want to support EF Core for your module. \ No newline at end of file diff --git a/docs/en/Startup-Templates/Mvc.md b/docs/en/Startup-Templates/Mvc.md index 6916a630a3..e61fe5c8fb 100644 --- a/docs/en/Startup-Templates/Mvc.md +++ b/docs/en/Startup-Templates/Mvc.md @@ -61,7 +61,9 @@ If you don't specify any option, you will have a solution like shown below: ![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-v3.png) -Projects are organized in `src` and `test` folders. `src` folder contains the actual application which is layered based on [DDD](../Domain-Driven-Design.md) principles as mentioned before. The diagram below shows the layers & project dependencies of the solution: +Projects are organized in `src` and `test` folders. `src` folder contains the actual application which is layered based on [DDD](../Domain-Driven-Design.md) principles as mentioned before. + +The diagram below shows the layers & project dependencies of the application: ![layered-project-dependencies](../images/layered-project-dependencies.png) @@ -79,7 +81,7 @@ A `BookType` enum and a `BookConts` class (which may have some constant fields f This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../Entities.md), [domain services](../Domain-Services.md), [value types](../Value-Types.md), [repository interfaces](../Repositories.md) and other domain objects. -A `Book` entity, a `BookManager` domain service and a `IBookRepository` interface are good candidates for this project. +A `Book` entity, a `BookManager` domain service and an `IBookRepository` interface are good candidates for this project. * Depends on the `.Domain.Shared` because it uses constants, enums and other objects defined in that project. @@ -87,12 +89,16 @@ A `Book` entity, a `BookManager` domain service and a `IBookRepository` interfac This project mainly contains [application service](../Application-Services.md) **interfaces** and [Data Transfer Objects](../Data-Transfer-Objects.md) (DTO) of the application layer. It does exists to separate interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package. +An `IBookAppService` interface and a `BookCreationDto` class are good candidates for this project. + * Depends on the `.Domain.Shared` because it may use constants, enums and other shared objects of this project in the application service interfaces and DTOs. #### .Application Project This project contains the [application service](../Application-Services.md) **implementations** of the interfaces defined in the `.Application.Contracts` project. +A `BookAppService` class is a good candidate for this project. + * Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs. * Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic. diff --git a/docs/en/images/issuemanagement-module-solution.png b/docs/en/images/issuemanagement-module-solution.png new file mode 100644 index 0000000000000000000000000000000000000000..181924dd90059a8ccc8fc94dbae57a5800244142 GIT binary patch literal 25772 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 Ut5honxQ61EhORp1#+{J=0)zGso&W#< literal 0 HcmV?d00001 diff --git a/docs/en/images/layered-project-dependencies-module.png b/docs/en/images/layered-project-dependencies-module.png new file mode 100644 index 0000000000000000000000000000000000000000..7592f49878353c153f529ba7e6e605fd11dcb2f1 GIT binary patch literal 38795 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 EQBT_1T- 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 D?t*yF literal 0 HcmV?d00001 From b707f2e8533dbbf3b0776ffbca7608c91c81704f Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 6 Jun 2019 22:45:02 +0800 Subject: [PATCH 03/75] fix #1206 Mvc template & BookStore virtual file enhancement. --- .../src/Acme.BookStore.Web/Acme.BookStore.Web.csproj | 9 +++++++++ .../src/Acme.BookStore.Web/BookStoreWebModule.cs | 10 ++++++---- .../MyCompanyName.MyProjectName.Web.csproj | 9 +++++++++ .../MyProjectNameWebModule.cs | 10 ++++++---- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj b/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj index a6e1fb1b77..23c0962bc3 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj +++ b/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj @@ -19,6 +19,15 @@ + + + + + + + + + diff --git a/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs b/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs index bbba8b543c..59154db5a2 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs @@ -105,17 +105,19 @@ namespace Acme.BookStore.Web private void ConfigureVirtualFileSystem(IHostingEnvironment hostingEnvironment) { - if (hostingEnvironment.IsDevelopment()) + Configure(options => { - Configure(options => + options.FileSets.AddEmbedded("Acme.BookStore.Web"); + + if (hostingEnvironment.IsDevelopment()) { options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Domain.Shared", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Domain", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Application.Contracts", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Application", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(hostingEnvironment.ContentRootPath); - }); - } + } + }); } private void ConfigureLocalizationServices() diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index 84ba69f73e..d76fc342a0 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -20,6 +20,15 @@ + + + + + + + + + diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs index 84cacf1d48..0e8cf755fa 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs @@ -109,9 +109,11 @@ namespace MyCompanyName.MyProjectName.Web private void ConfigureVirtualFileSystem(IHostingEnvironment hostingEnvironment) { - if (hostingEnvironment.IsDevelopment()) + Configure(options => { - Configure(options => + options.FileSets.AddEmbedded("MyCompanyName.MyProjectName.Web"); + + if (hostingEnvironment.IsDevelopment()) { options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain.Shared", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); @@ -128,8 +130,8 @@ namespace MyCompanyName.MyProjectName.Web options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}identity{0}src{0}Volo.Abp.Identity.Web", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}account{0}src{0}Volo.Abp.Account.Web", Path.DirectorySeparatorChar))); // - }); - } + } + }); } private void ConfigureLocalizationServices() From 93e8c80bde3fc5e5193bcaf133ca402a700c96cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 6 Jun 2019 18:04:18 +0300 Subject: [PATCH 04/75] Complete the MVC module template. --- docs/en/Startup-Templates/Mvc-Module.md | 92 +++++++++++++++++++++---- docs/en/Startup-Templates/Mvc.md | 19 ++--- 2 files changed, 91 insertions(+), 20 deletions(-) diff --git a/docs/en/Startup-Templates/Mvc-Module.md b/docs/en/Startup-Templates/Mvc-Module.md index d27c2d3d12..96c91b4c4b 100644 --- a/docs/en/Startup-Templates/Mvc-Module.md +++ b/docs/en/Startup-Templates/Mvc-Module.md @@ -30,11 +30,7 @@ abp new Acme.IssueManagement -t mvc-module --no-ui ## Solution Structure -Based on the options you've specified, you will get a slightly different solution structure. - -### Default Structure - -If you don't specify any option, you will have a solution like shown below: +Based on the options you've specified, you will get a slightly different solution structure. If you don't specify any option, you will have a solution like shown below: ![issuemanagement-module-solution](../images/issuemanagement-module-solution.png) @@ -50,7 +46,7 @@ The diagram below shows the layers & project dependencies of the module: Each section below will explain the related project & its dependencies. -#### .Domain.Shared Project +### .Domain.Shared Project This project contains constants, enums and other objects these are actually a part of the domain layer, but needed to be used by all layers/projects in the solution. @@ -58,7 +54,7 @@ An `IssueType` enum and an `IssueConts` class (which may have some constant fiel - This project has no dependency to other projects in the solution. All other projects depend on this directly or indirectly. -#### .Domain Project +### .Domain Project This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../Entities.md), [domain services](../Domain-Services.md), [value types](../Value-Types.md), [repository interfaces](../Repositories.md) and other domain objects. @@ -66,7 +62,7 @@ An `Issue` entity, an `IssueManager` domain service and an `IIssueRepository` in - Depends on the `.Domain.Shared` because it uses constants, enums and other objects defined in that project. -#### .Application.Contracts Project +### .Application.Contracts Project This project mainly contains [application service](../Application-Services.md) **interfaces** and [Data Transfer Objects](../Data-Transfer-Objects.md) (DTO) of the application layer. It does exists to separate interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package. @@ -74,7 +70,7 @@ An `IIssueAppService` interface and an `IssueCreationDto` class are good candida - Depends on the `.Domain.Shared` because it may use constants, enums and other shared objects of this project in the application service interfaces and DTOs. -#### .Application Project +### .Application Project This project contains the [application service](../Application-Services.md) **implementations** of the interfaces defined in the `.Application.Contracts` project. @@ -83,10 +79,82 @@ An `IssueAppService` class is a good candidate for this project. - Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs. - Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic. -#### .EntityFrameworkCore Project +### .EntityFrameworkCore Project -This is the integration project for the EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project. +This is the integration project for EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project. - Depends on the `.Domain` project to be able to reference to entities and repository interfaces. -> You can delete this project if you don't want to support EF Core for your module. \ No newline at end of file +> You can delete this project if you don't want to support EF Core for your module. + +### .MongoDB Project + +This is the integration project for MongoDB. + +- Depends on the `.Domain` project to be able to reference to entities and repository interfaces. + +> You can delete this project if you don't want to support MongoDB for your module. + +### Test Projects + +The solution has multiple test projects, one for each layer: + +- `.Domain.Tests` is used to test the domain layer. +- `.Application.Tests` is used to test the application layer. +- `.EntityFrameworkCore.Tests` is used to test EF Core configuration and custom repositories. +- `.MongoDB.Tests` is used to test EF Core configuration and custom repositories. +- `.TestBase` is a base (shared) project for all tests. + +In addition, `.HttpApi.Client.ConsoleTestApp` is a console application (not an automated test project) which demonstrate the usage of HTTP APIs from a Dotnet application. + +Test projects are prepared for integration testing; + +- It is fully integrated to ABP framework and all services in your application. +- It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library. +- Authorization is disabled, so any application service can be easily used in tests. + +You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all initialization process). + +> Domain & Application tests are using EF Core. If you remove EF Core integration or you want to use MongoDB for testing these layers, you should manually change project references & module dependencies. + +### Host Projects + +The solution has a few host applications to run your module on development. Host applications are used to run your module in a fully configured application. It is useful on development. Host applications includes some other modules in addition to the module being developed: + +* + +Host applications support two types of scenarios. + +#### Single (Unified) Application Scenario + +If your module has a UI, then `.Web.Unified` application is used to host the UI and API on a single point. It has its own `appsettings.json` file (that includes the database connection string) and EF Core database migrations. + +For the `.Web.Unified` application, there is a single database, named `YourProjectName_Unified` (like *IssueManagement_Unified* for this sample). + +> If you've selected the `--no-ui` option, this project will not be in your solution. + +##### How to Run? + +Set it as the startup project, run `Update-Database` command for the EF Core from Package Manager Console and run your application. Default username is `admin` and password is `1q2w3E*`. + +#### Separated Deployment & Databases Scenario + +In this scenario, there are three applications; + +* `.IdentityServer` application is an authentication server used by other applications. It has its own `appsettings.json` that contains database connection and other configurations. +* `.HttpApi.Host` hosts the HTTP API of the module. It has its own `appsettings.json` that contains database connections and other configurations. +* `.Web.Host` host the UI of the module. This project contains an `appsettings.json` file, but it does not have a connection string because it never connects to the database. Instead, it mainly contains endpoint of the remote API server and the authentication server. + +The diagram below shows the relation of the applications: + +![tiered-solution-applications](../images/tiered-solution-applications.png) + +`.Web.Host` project uses OpenId Connect Authentication to get identity and access tokens for the current user from the `.IdentityServer`. Then uses the access token to call the `.HttpApi.Host`. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user. + +##### How to Run? + +You should run the application with the given order: + +- First, run the `.IdentityServer` since other applications depends on it. +- Then run the `.HttpApi.Host` since it is used by the `.Web.Host` application. +- Finally, you can run the `.Web.Host` project and login to the application using `admin` as the username and `1q2w3E*` as the password. \ No newline at end of file diff --git a/docs/en/Startup-Templates/Mvc.md b/docs/en/Startup-Templates/Mvc.md index e61fe5c8fb..cdaa689db2 100644 --- a/docs/en/Startup-Templates/Mvc.md +++ b/docs/en/Startup-Templates/Mvc.md @@ -187,7 +187,7 @@ The solution has multiple test projects, one for each layer: In addition, `.HttpApi.Client.ConsoleTestApp` is a console application (not an automated test project) which demonstrate the usage of HTTP APIs from a Dotnet application. -Test projects are prepared integration testing; +Test projects are prepared for integration testing; * It is fully integrated to ABP framework and all services in your application. * It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library. @@ -224,9 +224,9 @@ As different from the default structure, two new projects come into play: `.Iden #### .IdentityServer Project -This project is used as an authentication server for other projects. `.Web` project uses OpenId Connect Authentication to get identity and access tokens for the current user. Then uses the access token to call the HTTP API server. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user. +This project is used as an authentication server for other projects. `.Web` project uses OpenId Connect Authentication to get identity and access tokens for the current user from the IdentityServer. Then uses the access token to call the HTTP API server. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user. -![bookstore-visual-studio-solution-v3](../images/tiered-solution-applications.png) +![tiered-solution-applications](../images/tiered-solution-applications.png) ABP uses the open source [IdentityServer4](https://identityserver.io/) framework for the authentication between applications. See [IdentityServer4 documentation](http://docs.identityserver.io) for details about the IdentityServer4 and OpenID Connect protocol. @@ -234,9 +234,7 @@ It has its own `appsettings.json` that contains database connection and other co #### .HttpApi.Host Project -This project is an application that hosts the API of the solution. - -It has its own `appsettings.json` that contains database connection and other configurations. +This project is an application that hosts the API of the solution. It has its own `appsettings.json` that contains database connection and other configurations. #### .Web Project @@ -253,5 +251,10 @@ This project contains an `appsettings.json` file, but this time it does not have You should run the application with the given order: * First, run the `.IdentityServer` since other applications depends on it. -* Then run the `.HttpApi.Server` since it is used by the `.Web` application. -* Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password). \ No newline at end of file +* Then run the `.HttpApi.Host` since it is used by the `.Web` application. +* Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password). + +## What's Next? + +- See [Getting Started With the ASP.NET Core MVC Template](../Getting-Started-AspNetCore-MVC-Template.md) to create a new solution and run it for this template. +- See the [ASP.NET Core MVC Tutorial](../Tutorials/AspNetCore-Mvc/Part-I.md) to learn how to develop applications using this template. \ No newline at end of file From 659fd056068c8419b93dcdaba2b834aec29191eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 6 Jun 2019 18:04:31 +0300 Subject: [PATCH 05/75] Rename tests to test. --- templates/mvc-module/MyCompanyName.MyProjectName.sln | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/mvc-module/MyCompanyName.MyProjectName.sln b/templates/mvc-module/MyCompanyName.MyProjectName.sln index 9ca4ac6631..ea7d59fe2c 100644 --- a/templates/mvc-module/MyCompanyName.MyProjectName.sln +++ b/templates/mvc-module/MyCompanyName.MyProjectName.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.2026 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29001.49 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCompanyName.MyProjectName.Domain.Shared", "src\MyCompanyName.MyProjectName.Domain.Shared\MyCompanyName.MyProjectName.Domain.Shared.csproj", "{D64C1577-4929-4B60-939E-96DE1534891A}" EndProject @@ -13,7 +13,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCompanyName.MyProjectName EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{649A3FFA-182F-4E56-9717-E6A9A2BEC545}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "host", "host", "{E400416D-2895-4512-9D17-90681EEC7E0A}" EndProject From 475a0acfdac226dc0882b13503ace014a2ec2f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 6 Jun 2019 18:16:11 +0300 Subject: [PATCH 06/75] Show documentation URL of the template after project creation. --- .../Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs | 4 ++++ .../Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs | 11 +++++++++++ .../Cli/ProjectBuilding/Templates/Mvc/MvcTemplate.cs | 2 +- .../Templates/MvcModule/MvcModuleTemplate.cs | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs index 4041dc8d7a..3809646ecc 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs @@ -6,10 +6,14 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building { public abstract class TemplateInfo { + [NotNull] public string Name { get; } public DatabaseProvider DefaultDatabaseProvider { get; } + [CanBeNull] + public string DocumentUrl { get; set; } + protected TemplateInfo( [NotNull] string name, DatabaseProvider defaultDatabaseProvider = DatabaseProvider.NotSpecified) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs index 64aa02ee6e..574dd32a3d 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs @@ -1,5 +1,7 @@ using System; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.DependencyInjection; @@ -7,6 +9,8 @@ namespace Volo.Abp.Cli.ProjectBuilding { public class ProjectBuilder : IProjectBuilder, ITransientDependency { + public ILogger Logger { get; set; } + protected ITemplateStore TemplateStore { get; } protected ITemplateInfoProvider TemplateInfoProvider { get; } @@ -14,6 +18,8 @@ namespace Volo.Abp.Cli.ProjectBuilding { TemplateStore = templateStore; TemplateInfoProvider = templateInfoProvider; + + Logger = NullLogger.Instance; } public async Task BuildAsync(ProjectBuildArgs args) @@ -44,6 +50,11 @@ namespace Volo.Abp.Cli.ProjectBuilding ProjectBuildPipelineBuilder.Build(context).Execute(context); + if (!templateInfo.DocumentUrl.IsNullOrEmpty()) + { + Logger.LogInformation("Check the documentation of this template: " + templateInfo.DocumentUrl); + } + return new ProjectBuildResult(context.Result.ZipContent, args.SolutionName.ProjectName); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Mvc/MvcTemplate.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Mvc/MvcTemplate.cs index 069c5fbf03..5df8167fad 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Mvc/MvcTemplate.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Mvc/MvcTemplate.cs @@ -14,7 +14,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Mvc public MvcTemplate() : base(TemplateName, DatabaseProvider.EntityFrameworkCore) { - + DocumentUrl = "https://docs.abp.io/en/abp/latest/Startup-Templates/Mvc"; } public override IEnumerable GetCustomSteps(ProjectBuildContext context) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModule/MvcModuleTemplate.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModule/MvcModuleTemplate.cs index e3258ec8a6..e12f97a638 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModule/MvcModuleTemplate.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MvcModule/MvcModuleTemplate.cs @@ -14,7 +14,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.MvcModule public MvcModuleTemplate() : base(TemplateName) { - + DocumentUrl = "https://docs.abp.io/en/abp/latest/Startup-Templates/Mvc-Module"; } public override IEnumerable GetCustomSteps(ProjectBuildContext context) From 5208062d5dd4770413e8720e9cc47c6c6c543e0c Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 6 Jun 2019 22:45:02 +0800 Subject: [PATCH 07/75] Revert "fix #1206 Mvc template & BookStore virtual file enhancement. " This reverts commit b707f2e8533dbbf3b0776ffbca7608c91c81704f. --- .../src/Acme.BookStore.Web/Acme.BookStore.Web.csproj | 9 --------- .../src/Acme.BookStore.Web/BookStoreWebModule.cs | 10 ++++------ .../MyCompanyName.MyProjectName.Web.csproj | 9 --------- .../MyProjectNameWebModule.cs | 10 ++++------ 4 files changed, 8 insertions(+), 30 deletions(-) diff --git a/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj b/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj index 23c0962bc3..a6e1fb1b77 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj +++ b/samples/BookStore/src/Acme.BookStore.Web/Acme.BookStore.Web.csproj @@ -19,15 +19,6 @@ - - - - - - - - - diff --git a/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs b/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs index 59154db5a2..bbba8b543c 100644 --- a/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs +++ b/samples/BookStore/src/Acme.BookStore.Web/BookStoreWebModule.cs @@ -105,19 +105,17 @@ namespace Acme.BookStore.Web private void ConfigureVirtualFileSystem(IHostingEnvironment hostingEnvironment) { - Configure(options => + if (hostingEnvironment.IsDevelopment()) { - options.FileSets.AddEmbedded("Acme.BookStore.Web"); - - if (hostingEnvironment.IsDevelopment()) + Configure(options => { options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Domain.Shared", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Domain", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Application.Contracts", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}Acme.BookStore.Application", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(hostingEnvironment.ContentRootPath); - } - }); + }); + } } private void ConfigureLocalizationServices() diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index d76fc342a0..84ba69f73e 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -20,15 +20,6 @@ - - - - - - - - - diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs index 0e8cf755fa..84cacf1d48 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs @@ -109,11 +109,9 @@ namespace MyCompanyName.MyProjectName.Web private void ConfigureVirtualFileSystem(IHostingEnvironment hostingEnvironment) { - Configure(options => + if (hostingEnvironment.IsDevelopment()) { - options.FileSets.AddEmbedded("MyCompanyName.MyProjectName.Web"); - - if (hostingEnvironment.IsDevelopment()) + Configure(options => { options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain.Shared", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); @@ -130,8 +128,8 @@ namespace MyCompanyName.MyProjectName.Web options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}identity{0}src{0}Volo.Abp.Identity.Web", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}account{0}src{0}Volo.Abp.Account.Web", Path.DirectorySeparatorChar))); // - } - }); + }); + } } private void ConfigureLocalizationServices() From f7584a10aa28ad130e10b4d14797bc2ae966b34e Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Fri, 7 Jun 2019 11:24:19 +0300 Subject: [PATCH 08/75] Update Index.cshtml.cs --- modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs index ccb8cce083..ca28c0ef8f 100644 --- a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs @@ -1,3 +1,4 @@ +using System; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Options; @@ -17,7 +18,12 @@ namespace VoloDocs.Web.Pages public IActionResult OnGet() { //TODO: Create HomeController & Index instead of Page. Otherwise, we have an empty Index.cshtml file. - return Redirect("./documents"); + if (!_urlOptions.RoutePrefix.IsNullOrWhiteSpace()) + { + return Redirect("./" + _urlOptions.GetFormattedRoutePrefix()); + } + + return Page(); } } } \ No newline at end of file From 7fd47fa9f7e459177c167328621889a96dae82dd Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Fri, 7 Jun 2019 16:30:26 +0300 Subject: [PATCH 09/75] ICrudAppService with different Get/GetList DTO models Resolves https://github.com/abpframework/abp/issues/1027 --- .../Services/AsyncCrudAppService.cs | 44 ++++++++++++------- .../Application/Services/CrudAppService.cs | 41 +++++++++++------ .../Services/CrudAppServiceBase.cs | 21 ++++++--- .../Services/IAsyncCrudAppService.cs | 18 +++++--- .../Application/Services/ICrudAppService.cs | 18 +++++--- 5 files changed, 97 insertions(+), 45 deletions(-) diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs index 151212925a..249c892b6e 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs @@ -45,28 +45,40 @@ namespace Volo.Abp.Application.Services } public abstract class AsyncCrudAppService - : CrudAppServiceBase, - IAsyncCrudAppService + : AsyncCrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto + { + protected AsyncCrudAppService(IRepository repository) + : base(repository) + { + } + } + + public abstract class AsyncCrudAppService + : CrudAppServiceBase, + IAsyncCrudAppService where TEntity : class, IEntity - where TEntityDto : IEntityDto + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto { public IAsyncQueryableExecuter AsyncQueryableExecuter { get; set; } protected AsyncCrudAppService(IRepository repository) - :base(repository) + : base(repository) { AsyncQueryableExecuter = DefaultAsyncQueryableExecuter.Instance; } - public virtual async Task GetAsync(TKey id) + public virtual async Task GetAsync(TKey id) { await CheckGetPolicyAsync(); var entity = await GetEntityByIdAsync(id); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } - public virtual async Task> GetListAsync(TGetListInput input) + public virtual async Task> GetListAsync(TGetListInput input) { await CheckGetListPolicyAsync(); @@ -79,29 +91,29 @@ namespace Volo.Abp.Application.Services var entities = await AsyncQueryableExecuter.ToListAsync(query); - return new PagedResultDto( + return new PagedResultDto( totalCount, - entities.Select(MapToEntityDto).ToList() + entities.Select(MapToGetListOutputDto).ToList() ); } - public virtual async Task CreateAsync(TCreateInput input) + public virtual async Task CreateAsync(TCreateInput input) { await CheckCreatePolicyAsync(); var entity = MapToEntity(input); - - if(entity is IMultiTenant && !HasTenantIdProperty(entity)) + + if (entity is IMultiTenant && !HasTenantIdProperty(entity)) { TryToSetTenantId(entity); } - + await Repository.InsertAsync(entity, autoSave: true); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } - public virtual async Task UpdateAsync(TKey id, TUpdateInput input) + public virtual async Task UpdateAsync(TKey id, TUpdateInput input) { await CheckUpdatePolicyAsync(); @@ -110,7 +122,7 @@ namespace Volo.Abp.Application.Services MapToEntity(input, entity); await Repository.UpdateAsync(entity, autoSave: true); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } public virtual async Task DeleteAsync(TKey id) 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 2595bc6edd..7b79823e80 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 @@ -44,8 +44,7 @@ namespace Volo.Abp.Application.Services } public abstract class CrudAppService - : CrudAppServiceBase, - ICrudAppService + : CrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { @@ -54,16 +53,30 @@ namespace Volo.Abp.Application.Services { } + } - public virtual TEntityDto Get(TKey id) + public abstract class CrudAppService + : CrudAppServiceBase, + ICrudAppService + where TEntity : class, IEntity + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto + { + protected CrudAppService(IRepository repository) + : base(repository) + { + + } + + public virtual TGetOutputDto Get(TKey id) { CheckGetPolicy(); var entity = GetEntityById(id); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } - public virtual PagedResultDto GetList(TGetListInput input) + public virtual PagedResultDto GetList(TGetListInput input) { CheckGetListPolicy(); @@ -76,29 +89,29 @@ namespace Volo.Abp.Application.Services var entities = query.ToList(); - return new PagedResultDto( + return new PagedResultDto( totalCount, - entities.Select(MapToEntityDto).ToList() + entities.Select(MapToGetListOutputDto).ToList() ); } - public virtual TEntityDto Create(TCreateInput input) + public virtual TGetOutputDto Create(TCreateInput input) { CheckCreatePolicy(); var entity = MapToEntity(input); - - if(entity is IMultiTenant && !HasTenantIdProperty(entity)) + + if (entity is IMultiTenant && !HasTenantIdProperty(entity)) { TryToSetTenantId(entity); } - + Repository.Insert(entity, autoSave: true); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } - public virtual TEntityDto Update(TKey id, TUpdateInput input) + public virtual TGetOutputDto Update(TKey id, TUpdateInput input) { CheckUpdatePolicy(); @@ -106,7 +119,7 @@ namespace Volo.Abp.Application.Services MapToEntity(input, entity); Repository.Update(entity, autoSave: true); - return MapToEntityDto(entity); + return MapToGetOutputDto(entity); } public virtual void Delete(TKey id) 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 b678362c53..e9c6610202 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 @@ -13,10 +13,11 @@ 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 : + public abstract class CrudAppServiceBase : ApplicationService where TEntity : class, IEntity - where TEntityDto : IEntityDto + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto { protected IRepository Repository { get; } @@ -100,13 +101,23 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to . + /// Maps to . /// It uses by default. /// It can be overrided for custom mapping. /// - protected virtual TEntityDto MapToEntityDto(TEntity entity) + protected virtual TGetOutputDto MapToGetOutputDto(TEntity entity) { - return ObjectMapper.Map(entity); + return ObjectMapper.Map(entity); + } + + /// + /// Maps to . + /// It uses by default. + /// It can be overrided for custom mapping. + /// + protected virtual TGetListOutputDto MapToGetListOutputDto(TEntity entity) + { + return ObjectMapper.Map(entity); } /// diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs index 4f97c49ae0..e3e18f4873 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs @@ -25,16 +25,24 @@ namespace Volo.Abp.Application.Services } public interface IAsyncCrudAppService - : IApplicationService + : IAsyncCrudAppService where TEntityDto : IEntityDto { - Task GetAsync(TKey id); - Task> GetListAsync(TGetListInput input); + } + + public interface IAsyncCrudAppService + : IApplicationService + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto + { + Task GetAsync(TKey id); + + Task> GetListAsync(TGetListInput input); - Task CreateAsync(TCreateInput input); + Task CreateAsync(TCreateInput input); - Task UpdateAsync(TKey id, TUpdateInput input); + Task UpdateAsync(TKey id, TUpdateInput input); Task DeleteAsync(TKey id); } diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs index 7e8b96b9f8..2f3b770849 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs @@ -24,16 +24,24 @@ namespace Volo.Abp.Application.Services } public interface ICrudAppService - : IApplicationService + : ICrudAppService where TEntityDto : IEntityDto { - TEntityDto Get(TKey id); - PagedResultDto GetList(TGetListInput input); + } + + public interface ICrudAppService + : IApplicationService + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto + { + TGetOutputDto Get(TKey id); + + PagedResultDto GetList(TGetListInput input); - TEntityDto Create(TCreateInput input); + TGetOutputDto Create(TCreateInput input); - TEntityDto Update(TKey id, TUpdateInput input); + TGetOutputDto Update(TKey id, TUpdateInput input); void Delete(TKey id); } From 2276f5b39a2cea574a96492f8818dc992082c6d2 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Mon, 10 Jun 2019 11:56:59 +0300 Subject: [PATCH 10/75] Update IAsyncCrudAppService.cs --- .../Volo/Abp/Application/Services/IAsyncCrudAppService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs index e3e18f4873..8f07cb2412 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IAsyncCrudAppService.cs @@ -25,7 +25,7 @@ namespace Volo.Abp.Application.Services } public interface IAsyncCrudAppService - : IAsyncCrudAppService + : IAsyncCrudAppService where TEntityDto : IEntityDto { From c368ab63193fb8bb2240c2308f830b9bdc03b7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Mon, 10 Jun 2019 14:33:07 +0300 Subject: [PATCH 11/75] Update README.md --- README.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f6304ad5b3..f9b2d5a3ea 100644 --- a/README.md +++ b/README.md @@ -22,22 +22,15 @@ See the documentation. #### Pre Requirements -- Visual Studio 2017 15.9.0+ +- Visual Studio 2019 16.1.0+ #### Framework -Framework solution is located under the `framework` folder. It has no external dependency. Just open `Volo.Abp.sln` by Visual Studio and start the development. +Framework solution is located under the `framework` folder. It has no external dependency. #### Modules/Templates -[Modules](modules/) and [Templates](templates/) have their own solutions and have **local references** to the framework. Unfortunately, Visual Studio has some problems with local references to projects those are out of the solution. As a workaround, you should follow the steps below in order to start developing a module/template: - -- Disable "*Automatically check for missing packages during build in Visual Studio*" in the Visual Studio options. - -![disable-package-restore-visual-studio](docs/en/images/disable-package-restore-visual-studio.png) - -- When you open a solution, first run `dotnet restore` in the root folder of the solution. -- When you change a dependency of a project (or any of the dependencies of your projects change their dependencies), run `dotnet restore` again. +[Modules](modules/) and [Templates](templates/) have their own solutions and have **local references** to the framework and each other. ### Contribution From 0ef2b9e6436f2d926c9dff14d1da289e4e345050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Mon, 10 Jun 2019 14:34:45 +0300 Subject: [PATCH 12/75] Update README.md --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index f9b2d5a3ea..ee043bdb62 100644 --- a/README.md +++ b/README.md @@ -8,16 +8,12 @@ See the official [web site (abp.io)](https://abp.io/) for more information. ### Status -This project is in **very early preview** stage and it's not suggested to use it in a real project. +This project is in **preview** stage and it's not suggested to use it in production yet. ### Documentation See the documentation. -### How to Build - -- Run the `build-all.ps1`. It will build all the solutions in this repository. - ### Development #### Pre Requirements From 4b1fe8f2e146cc814faf776c8d54221f09aab10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Mon, 10 Jun 2019 14:38:09 +0300 Subject: [PATCH 13/75] Remove unused image. --- .../disable-package-restore-visual-studio.png | Bin 24425 -> 0 bytes .../disable-package-restore-visual-studio.png | Bin 24425 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/en/images/disable-package-restore-visual-studio.png delete mode 100644 docs/zh-Hans/images/disable-package-restore-visual-studio.png diff --git a/docs/en/images/disable-package-restore-visual-studio.png b/docs/en/images/disable-package-restore-visual-studio.png deleted file mode 100644 index 5d2343dc3f3e42f07ff7b36ad971fd8cbb24b1fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24425 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≧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 H^3A^h*tD_u diff --git a/docs/zh-Hans/images/disable-package-restore-visual-studio.png b/docs/zh-Hans/images/disable-package-restore-visual-studio.png deleted file mode 100644 index 5d2343dc3f3e42f07ff7b36ad971fd8cbb24b1fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24425 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≧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 H^3A^h*tD_u From 018d9fe0fd4d10c2643ad099b452d5da631eaf1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Mon, 10 Jun 2019 14:44:58 +0300 Subject: [PATCH 14/75] Override MapToGetListOutputDto to use MapToGetOutputDto by default. --- .../Abp/Application/Services/AsyncCrudAppService.cs | 6 ++++++ .../Volo/Abp/Application/Services/CrudAppService.cs | 5 +++++ .../Abp/Application/Services/CrudAppServiceBase.cs | 10 +++++----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs index 249c892b6e..7bc76d9923 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs @@ -52,6 +52,12 @@ namespace Volo.Abp.Application.Services protected AsyncCrudAppService(IRepository repository) : base(repository) { + + } + + protected override TEntityDto MapToGetListOutputDto(TEntity entity) + { + return MapToGetOutputDto(entity); } } 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 7b79823e80..1d43ff084d 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 @@ -53,6 +53,11 @@ namespace Volo.Abp.Application.Services { } + + protected override TEntityDto MapToGetListOutputDto(TEntity entity) + { + return MapToGetOutputDto(entity); + } } public abstract class CrudAppService 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 e9c6610202..21c19a9a4a 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 @@ -103,7 +103,7 @@ namespace Volo.Abp.Application.Services /// /// Maps to . /// It uses by default. - /// It can be overrided for custom mapping. + /// It can be overriden for custom mapping. /// protected virtual TGetOutputDto MapToGetOutputDto(TEntity entity) { @@ -113,7 +113,7 @@ namespace Volo.Abp.Application.Services /// /// Maps to . /// It uses by default. - /// It can be overrided for custom mapping. + /// It can be overriden for custom mapping. /// protected virtual TGetListOutputDto MapToGetListOutputDto(TEntity entity) { @@ -121,9 +121,9 @@ namespace Volo.Abp.Application.Services } /// - /// Maps to to create a new entity. + /// Maps to to create a new entity. /// It uses by default. - /// It can be overrided for custom mapping. + /// It can be overriden for custom mapping. /// protected virtual TEntity MapToEntity(TCreateInput createInput) { @@ -151,7 +151,7 @@ namespace Volo.Abp.Application.Services /// /// Maps to to update the entity. /// It uses by default. - /// It can be overrided for custom mapping. + /// It can be overriden for custom mapping. /// protected virtual void MapToEntity(TUpdateInput updateInput, TEntity entity) { From 090954c8197dd6608ba28bab29d0355e7ba029c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Mon, 10 Jun 2019 14:53:05 +0300 Subject: [PATCH 15/75] Fix SSL casing. --- framework/src/Volo.Abp.Ldap/readme.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/framework/src/Volo.Abp.Ldap/readme.md b/framework/src/Volo.Abp.Ldap/readme.md index af86f64e99..dd9b84087d 100644 --- a/framework/src/Volo.Abp.Ldap/readme.md +++ b/framework/src/Volo.Abp.Ldap/readme.md @@ -12,7 +12,7 @@ add section in `appsettings.json` "LDAP": { "ServerHost": "192.168.101.54", "ServerPort": 636, - "UseSSL": true + "UseSsl": true } ``` @@ -22,7 +22,7 @@ add section in `appsettings.json` "LDAP": { "ServerHost": "192.168.101.54", "ServerPort": 389, - "UseSSL": false + "UseSsl": false } ``` @@ -59,7 +59,7 @@ public class TaxAppService : ApplicationService "LDAP": { "ServerHost": "192.168.101.54", "ServerPort": 636, - "UseSSL": true, + "UseSsl": true, "Credentials": { "DomainUserName": "administrator@yourdomain.com.cn", "Password": "yH.20190528" @@ -76,7 +76,7 @@ public class TaxAppService : ApplicationService "LDAP": { "ServerHost": "192.168.101.54", "ServerPort": 389, - "UseSSL": false, + "UseSsl": false, "Credentials": { "DomainUserName": "administrator@yourdomain.com.cn", "Password": "yH.20190528" @@ -166,8 +166,6 @@ _ldapManager.AddUserToOrganization("nameA", "passwordA", parentOrganization); _ldapManager.AddUserToOrganization("nameA", "passwordA", "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"); ``` -# More see [unit test](../../test/Volo.Abp.Ldap.Tests) +# More - - -# \ No newline at end of file +See [unit test](../../test/Volo.Abp.Ldap.Tests) \ No newline at end of file From e195ed75207150e4c1e62970963cbc8772008ed1 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 10:14:02 +0700 Subject: [PATCH 16/75] Support vietnamese language --- .../Mvc/UI/MultiTenancy/Localization/vi.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json new file mode 100644 index 0000000000..975e1b4590 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json @@ -0,0 +1,11 @@ +{ + "culture": "vi", + "texts": { + "GivenTenantIsNotAvailable": "Người thuê không có sẵn: {0}", + "Tenant": "Người thuê", + "Switch": "Chuyển đổi", + "Name": "Tên", + "SwitchTenantHint": "Để trống trường tên để chuyển sang phía máy chủ.", + "NotSelected": "Không được chọn" + } +} From 1b03ca7ffd89a80736158e2da25edc370b4736a2 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 10:17:44 +0700 Subject: [PATCH 17/75] Vietnam translations --- .../Localization/Resources/AbpUi/vi.json | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json new file mode 100644 index 0000000000..21a466ccda --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json @@ -0,0 +1,51 @@ +{ + "culture": "vi", + "texts": { + "InternalServerErrorMessage": "Có một lỗi nội bộ xảy ra trong quá trình thực hiện yêu cầu của bạn!", + "ValidationErrorMessage": "Yêu cầu của bạn không hợp lệ!", + "ValidationNarrativeErrorMessageTitle": "Các lỗi sau đây đã được phát hiện trong quá trình xác nhận", + "DefaultErrorMessage": "Một lỗi đã xảy ra", + "DefaultErrorMessageDetail": "Chi tiết lỗi không được gửi bởi máy chủ", + "DefaultErrorMessage401": "Bạn chưa được xác thực", + "DefaultErrorMessage401Detail": "Bạn cần đăng nhập để thực hiện thao tác này.", + "DefaultErrorMessage403": "Bạn không được phép!", + "DefaultErrorMessage403Detail": "Bạn không được phép thực hiện thao tác này!", + "DefaultErrorMessage404": "Tài nguyên không tìm thấy!", + "DefaultErrorMessage404Detail": "Tài nguyên được yêu cầu không được tìm thấy trên máy chủ!", + "EntityNotFoundErrorMessage": "Không có thực thể nào {0} với id = {1}!", + "Error": "Lỗi", + "AreYouSure": "Bạn có chắc không ?", + "Cancel": "Hủy bỏ", + "Yes": "Đồng ý", + "No": "Không", + "Close": "Đóng", + "Save": "Lưu", + "SavingWithThreeDot": "Đang lưu...", + "Actions": "Hành động", + "Delete": "Xóa", + "Edit": "Sửa", + "Refresh": "Làm mới", + "ProcessingWithThreeDot": "Đang xử lý...", + "LoadingWithThreeDot": "Đang tải...", + "Welcome": "Chào mừng bạn", + "Login": "Đăng nhập", + "Register": "Đăng ký", + "Logout": "Đăng xuất", + "Submit": "Gửi", + "Back": "Quay lại", + "PagerSearch": "Tìm kiếm", + "PagerNext": "Trang kế", + "PagerPrevious": "Trang trước", + "PagerFirst": "Trang đầu", + "PagerLast": "Trang cuối", + "PagerInfo": "Hiển thị từ _START_ đến _END_ trong _TOTAL_ mục", + "PagerInfoEmpty": "Hiển thị từ 0 đến 0 trong 0 mục", + "PagerInfoFiltered": "(được lọc từ tổng số _MAX_ mục)", + "NoDataAvailableInDatatable": "Không có dữ liệu trong bảng", + "PagerShowMenuEntries": "Hiển thị _MENU_ mục", + "DatatableActionDropdownDefaultText": "Hành động", + "ChangePassword": "Đổi mật khẩu", + "PersonalInfo": "Hồ sơ của tôi", + "AreYouSureYouWantToCancelEditingWarningMessage": "Bạn có những thay đổi chưa được lưu" + } +} From 84329938b67b7cd8e904863a22ac762fc11a1c43 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 11:33:03 +0700 Subject: [PATCH 18/75] Vietnamese tranlations --- .../Resources/AbpValidation/vi.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/vi.json diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/vi.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/vi.json new file mode 100644 index 0000000000..2d9c0c55f5 --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/vi.json @@ -0,0 +1,19 @@ +{ + "culture": "vi", + "texts": { + "'{0}' and '{1}' do not match.": "'{0}' và '{1}' không khớp.", + "The {0} field is not a valid credit card number.": "Trường {0} không phải là một số thẻ tín dụng hợp lệ.", + "{0} is not valid.": "{0} không hợp lệ.", + "The {0} field is not a valid e-mail address.": "Trường {0} không phải là một địa chỉ email hợp lệ.", + "The {0} field only accepts files with the following extensions: {1}": "Trường {0} chỉ chấp nhận các tập tin có phần mở rộng như sau: {1}", + "The field {0} must be a string or array type with a maximum length of '{1}'.": "Trường {0} phải là một chuỗi hoặc một mảng với độ dài tối đa là '{1}'.", + "The {0} field is not a valid phone number.": "Trường {0} không phải là một số điện thoại hợp lệ", + "The field {0} must be between {1} and {2}.": "Trường {0} phải ở giữa {1} and {2}.", + "The field {0} must match the regular expression '{1}'.": "Trường {0} phải khớp với biểu thức chính quy '{1}'.", + "The {0} field is required.": "Trường {0} là bắt buộc.", + "The field {0} must be a string with a maximum length of {1}.": "Trường {0} phải là một chuỗi với độ dài tối đa là {1}.", + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Trường {0} phải là một chuỗi với độ dài tối thiểu {2} và tối đa là {1}.", + "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "Trường {0} không phải là một http, https, hoặc ftp URL đủ điều kiện hợp lệ.", + "The field {0} is invalid.": "Trường {0} không có hiệu lực" + } +} From 0f928a43ba351a49670fb78d7a7e2653001f6bb3 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 11:38:25 +0700 Subject: [PATCH 19/75] vietnamese tranlation --- .../Resources/AbpAccount/Web/vi.json | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/vi.json diff --git a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/vi.json b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/vi.json new file mode 100644 index 0000000000..56d436c1cd --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/vi.json @@ -0,0 +1,21 @@ +{ + "culture": "vi", + "texts": { + "UserName": "Tên đăng nhập", + "EmailAddress": "Địa chỉ email", + "UserNameOrEmailAddress": "Tên đăng nhập hoặc địa chỉ email", + "Password": "Mật khẩu", + "RememberMe": "Ghi nhớ", + "UseAnotherServiceToLogin": "Sử dụng dịch vụ khác để đăng nhập", + "UserLockedOutMessage": "Tài khoản người dùng đã bị khóa do các nỗ lực đăng nhập không hợp lệ. Xin vui lòng chờ một lúc và thử lại.", + "InvalidUserNameOrPassword": "Sai tên tài khoản hoặc mật khẩu!", + "LoginIsNotAllowed": "Bạn không được phép đăng nhập! Bạn cần xác nhận email/số điện thoại của bạn.", + "SelfRegistrationDisabledMessage": "Tự đăng ký người dùng bị vô hiệu hóa cho ứng dụng này. Liên hệ với quản trị viên ứng dụng để đăng ký người dùng mới.", + "Login": "Đăng nhập", + "Cancel": "Hủy bỏ", + "Register": "Đăng ký", + "InvalidLoginRequest": "Yêu cầu đăng nhập không hợp lệ", + "ThereAreNoLoginSchemesConfiguredForThisClient": "Không có chương trình đăng nhập được cấu hình cho khách hàng này.", + "LogInUsingYourProviderAccount": "Đăng nhập bằng tài khoản {0} của bạn" + } +} From d413ed4f72ffba05e1bf80a550b34926e2435a28 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 11:43:27 +0700 Subject: [PATCH 20/75] vietnam translation --- .../Volo/Docs/Localization/Domain/vi.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json new file mode 100644 index 0000000000..7c845de612 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json @@ -0,0 +1,18 @@ +{ + "culture": "vi", + "texts": { + "Documents": "Tài liệu", + "BackToWebsite": "Quay lại trang web", + "Contributors": "Người đóng góp", + "ShareOn": "Chia sẻ", + "Version": "Phiên bản", + "Edit": "Sửa", + "Delete": "Xóa", + "InThisDocument": "Trong tài liệu này", + "GoToTop": "Chuyển về đầu trang", + "Projects": "Dự án", + "NoProjectWarning": "Chưa có dự án nào!", + "DocumentNotFound": "Rất tiếc, tài liệu được yêu cầu không tìm thấy!", + "NavigationDocumentNotFound": "Phiên bản này không có tài liệu điều hướng!" + } +} From dbf317169b569aa7ba0d3b71f885ac2058d1df97 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 11:51:18 +0700 Subject: [PATCH 21/75] vietnamese translation --- .../Resources/Blogging/Web/vi.json | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/vi.json diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/vi.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/vi.json new file mode 100644 index 0000000000..1405337271 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/vi.json @@ -0,0 +1,47 @@ +{ + "culture": "vi", + "texts": { + "Menu:Blogs": "Blogs", + "Menu:BlogManagement": "Quản lý Blog", + "Title": "Tiêu đề", + "Delete": "Xóa", + "Reply": "Trả lời", + "ReplyTo": "Trả lời {0}", + "ContinueReading": "Tiếp tục đọc", + "DaysAgo": "{0} ngày trước", + "YearsAgo": "{0} năm trước", + "MonthsAgo": "{0} tháng trước", + "WeeksAgo": "{0} tuần trước", + "MinutesAgo": "{0} phút trước", + "SecondsAgo": "{0} giây trước", + "HoursAgo": "{0} giờ trước", + "Now": "bây giờ", + "Content": "Nội dung", + "SeeAll": "Xem tất cả", + "PopularTags": "Thẻ phổ biến", + "WiewsWithCount": "{0} lượt xem", + "LastPosts": "Bài viết cuối", + "LeaveComment": "Để lại bình luận", + "TagsInThisArticle": "Từ khóa trong bài viết này", + "Posts": "Bài viết", + "Edit": "Sửa", + "BLOG": "BLOG", + "CommentDeletionWarningMessage": "Bình luận sẽ bị xóa.", + "PostDeletionWarningMessage": "Bài viết sẽ bị xóa.", + "BlogDeletionWarningMessage": "Blog sẽ bị xóa.", + "AreYouSure": "Bạn chắc chứ?", + "CommentWithCount": "{0} bình luận", + "Comment": "Bình luận", + "ShareOnTwitter": "Chia sẻ Twitter", + "CoverImage": "Ảnh bìa", + "CreateANewPost": "Tạo một bài viết mới", + "CreateANewBlog": "Tạo một Blog mới", + "WhatIsNew": "Cái gì mới?", + "Name": "Tên", + "ShortName": "Tên rút gọn", + "CreationTime": "Thời gian tạo", + "Description": "Mô tả", + "Blogs": "Blogs", + "Tags": "Thẻ" + } +} From 352ca6348d9a575cb321e053438318f9e7e1f202 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 11:57:39 +0700 Subject: [PATCH 22/75] vn tranlation --- .../Blogging/ApplicationContracts/vi.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/vi.json diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/vi.json b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/vi.json new file mode 100644 index 0000000000..a32ee04bb9 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/vi.json @@ -0,0 +1,14 @@ +{ + "culture": "vi", + "texts": { + "Permission:Blogging": "Blog", + "Permission:Blogs": "Blogs", + "Permission:Posts": "Bài viết", + "Permission:Tags": "Thẻ", + "Permission:Comments": "Bình luận", + "Permission:Management": "Quản lý", + "Permission:Edit": "Sửa", + "Permission:Create": "Tạo", + "Permission:Delete": "Xóa" + } +} From d3224f3b443e9d749582294bba0de10c846e6c09 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 12:05:07 +0700 Subject: [PATCH 23/75] vi translation --- .../Resources/AbpIdentity/vi.json | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/vi.json diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/vi.json b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/vi.json new file mode 100644 index 0000000000..b43484b0c8 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/vi.json @@ -0,0 +1,39 @@ +{ + "culture": "vi", + "texts": { + "Menu:IdentityManagement": "Quản lý danh tính", + "Users": "Người dùng", + "NewUser": "Tạo người dùng mới", + "UserName": "Tên đăng nhập", + "EmailAddress": "Địa chỉ email", + "PhoneNumber": "Số điện thoại", + "UserInformations": "Thông tin người dùng", + "DisplayName:IsDefault": "Mặc định", + "DisplayName:IsStatic": "Cố định", + "DisplayName:IsPublic": "Công khai", + "Roles": "Vai trò", + "Password": "Mật khẩu", + "PersonalInfo": "Thông tin của tôi", + "PersonalSettings": "Thiết lập cá nhân", + "UserDeletionConfirmationMessage": "Người '{0}' sẽ bị xóa. Bạn có xác nhận điều này không?", + "RoleDeletionConfirmationMessage": "vai trò '{0}' sẽ bị xóa. Bạn có xác nhận điều này không?", + "DisplayName:RoleName": "Tên vai trò", + "DisplayName:UserName": "Tên người dùng", + "DisplayName:Name": "Tên", + "DisplayName:Surname": "Họ", + "DisplayName:Password": "mật khẩu", + "DisplayName:Email": "Địa chỉ email", + "DisplayName:PhoneNumber": "Số điện thoại", + "DisplayName:TwoFactorEnabled": "Xác thực hai yếu tố", + "DisplayName:LockoutEnabled": "Khóa tài khoản sau những lần đăng nhập thất bại", + "NewRole": "Vai trò mới", + "RoleName": "Tên vai trò", + "CreationTime": "Thời gian tạo", + "Permissions": "Quyền", + "DisplayName:CurrentPassword": "Mật khẩu hiện tại", + "DisplayName:NewPassword": "Mật khẩu mới", + "DisplayName:NewPasswordConfirm": "Xác nhận mật khẩu", + "PasswordChangedMessage": "Mật khẩu của bạn đã được thay đổi thành công.", + "PersonalSettingsSavedMessage": "Thiết lập của bạn đã được lưu lại thành công." + } +} From 601fbe10b7ac488aa44815d4a5785d06f0c77f5d Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 12:13:11 +0700 Subject: [PATCH 24/75] vi translation --- .../Abp/Identity/Localization/Domain/vi.json | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/vi.json diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/vi.json b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/vi.json new file mode 100644 index 0000000000..7546865cfc --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/vi.json @@ -0,0 +1,33 @@ +{ + "culture": "vi", + "texts": { + "Identity.DefaultError": "Một thất bại chưa biết đã xảy ra.", + "Identity.ConcurrencyFailure": "Thất bại đồng thời lạc quan, đối tượng đã được sửa đổi.", + "Identity.DuplicateEmail": "Email '{0}' đã được sử dụng.", + "Identity.DuplicateRoleName": "Tên vài trò '{0}' đã được sử dụng.", + "Identity.DuplicateUserName": "User name '{0}' đã được sử dụng.", + "Identity.InvalidEmail": "Email '{0}' Không hợp lệ.", + "Identity.InvalidPasswordHasherCompatibilityMode": "PasswordHasherCompatibilityMode được cung cấp không hợp lệ.", + "Identity.InvalidPasswordHasherIterationCount": "Số lần lặp phải là số nguyên dương.", + "Identity.InvalidRoleName": "Tên người dùng '{0}' Không hợp lệ.", + "Identity.InvalidToken": "Token không hợp lệ.", + "Identity.InvalidUserName": "Tên người dùng '{0}' không hợp lệ, chỉ có thể chứa chữ cái hoặc chữ số.", + "Identity.LoginAlreadyAssociated": "Một người dùng có thông tin đăng nhập này đã tồn tại.", + "Identity.PasswordMismatch": "Mật khẩu không đúng.", + "Identity.PasswordRequiresDigit": "Mật khẩu phải có ít nhất một chữ số ('0'-'9').", + "Identity.PasswordRequiresLower": "Mật khẩu phải có ít nhất một chữ thường ('a'-'z').", + "Identity.PasswordRequiresNonAlphanumeric": "Mật khẩu phải có ít nhất một ký tự không phải là chữ và số.", + "Identity.PasswordRequiresUpper": "Mật khẩu phải có ít nhất một chữ hoa ('A'-'Z').", + "Identity.PasswordTooShort": "Mật khẩu phải ít nhất {0} kí tự.", + "Identity.RoleNotFound": "Vai trò {0} không tồn tại.", + "Identity.UserAlreadyHasPassword": "Người dùng đã có một mật khẩu.", + "Identity.UserAlreadyInRole": "Người dùng đã có vai trò '{0}'.", + "Identity.UserLockedOut": "Người dùng bị khóa.", + "Identity.UserLockoutNotEnabled": "Khóa không được kích hoạt cho người dùng này.", + "Identity.UserNameNotFound": "Người dùng {0} không tồn tại.", + "Identity.UserNotInRole": "Người dùng không có vai trò '{0}'.", + "Identity.PasswordConfirmationFailed": "Mật khẩu không khớp với mật khẩu xác nhận.", + "Identity.StaticRoleRenamingErrorMessage": "Vai trò này là cố định không được phép đổi tên.", + "Identity.StaticRoleDeletionErrorMessage": "Vai trò này là cố định không được phép xóa." + } +} From 9cc52c9c3ae7dc78771922c7d92c0200ec71ad90 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 12:16:24 +0700 Subject: [PATCH 25/75] vi translation --- .../Localization/ApplicationContracts/vi.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/vi.json diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/vi.json b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/vi.json new file mode 100644 index 0000000000..e9576d3ea9 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/vi.json @@ -0,0 +1,14 @@ +{ + "culture": "vi", + "texts": { + "Volo.Abp.Identity:010001": "Bạn không thể xóa tài khoản của riêng bạn!", + "Permission:IdentityManagement": "Quản lý danh tính", + "Permission:RoleManagement": "Quản lý vai trò", + "Permission:Create": "Tạo", + "Permission:Edit": "Sửa", + "Permission:Delete": "Xóa", + "Permission:ChangePermissions": "Thay đổi quyền", + "Permission:UserManagement": "Quản lý người dùng", + "Permission:UserLookup": "Tra cứu người dùng" + } +} From 95f592c7d61d5dcab1d76220ba3d325ebc50ad89 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 12:18:46 +0700 Subject: [PATCH 26/75] vi translation --- .../Resources/AbpPermissionManagement/vi.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/vi.json diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/vi.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/vi.json new file mode 100644 index 0000000000..9364bcf588 --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/vi.json @@ -0,0 +1,10 @@ +{ + "culture": "vi", + "texts": { + "Permissions": "Quyền", + "OnlyProviderPermissons": "Chỉ nhà cung cấp này", + "All": "Tất cả", + "SelectAllInAllTabs": "Cấp tất cả các quyền", + "SelectAllInThisTab": "Chọn tất cả" + } +} From 13520d4b0af0ba3c14bec786b4d9df5d1929dc21 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 12:22:32 +0700 Subject: [PATCH 27/75] vi translation --- .../Resources/AbpTenantManagement/Web/vi.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/vi.json diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/vi.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/vi.json new file mode 100644 index 0000000000..1818cbdffd --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/vi.json @@ -0,0 +1,14 @@ +{ + "culture": "vi", + "texts": { + "Menu:TenantManagement": "Quản lý người thuê", + "Tenants": "Người thuê", + "NewTenant": "Người thuê mới", + "TenantName": "Tên người thuê", + "DisplayName:TenantName": "Tên người thuê", + "TenantDeletionConfirmationMessage": "Người thuê '{0}' sẽ bị xóa. Bạn có xác nhận không?", + "ConnectionStrings": "Chuỗi kết nối", + "DisplayName:DefaultConnectionString": "Chuỗi kết nối mặc định", + "DisplayName:UseSharedDatabase": "Sử dụng cơ sở dữ liệu dùng chung" + } +} From 749fb4afe10063cd80e6e29392e1f0d22d137a8f Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 12:24:26 +0700 Subject: [PATCH 28/75] vi translation --- .../Localization/ApplicationContracts/vi.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/vi.json diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/vi.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/vi.json new file mode 100644 index 0000000000..3518883435 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/vi.json @@ -0,0 +1,11 @@ +{ + "culture": "vi", + "texts": { + "Permission:TenantManagement": "Quản lý khách thuê", + "Permission:Create": "Tạo", + "Permission:Edit": "Sửa", + "Permission:Delete": "Xóa", + "Permission:ManageConnectionStrings": "Quản lý chuỗi kết nối", + "Permission:ManageFeatures": "Quản lý các tính năng" + } +} From 2af3fe55fa1a44e64e2f264b9b5d1c5e871ca488 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 12:27:18 +0700 Subject: [PATCH 29/75] vi translation --- .../Localization/MyProjectName/vi.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/vi.json diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/vi.json b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/vi.json new file mode 100644 index 0000000000..c115a35726 --- /dev/null +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/vi.json @@ -0,0 +1,8 @@ +{ + "culture": "vi", + "texts": { + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} From 7a7887be7d0a72cdbf61148f95fdb913a8e147d0 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 11 Jun 2019 09:40:41 +0300 Subject: [PATCH 30/75] docs module: changing language now effects the current culture resolves https://github.com/abpframework/abp/issues/1217 --- .../Pages/Documents/Project/Index.cshtml.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index 83a1f62f27..5de65507a9 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -1,11 +1,14 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Localization; using Volo.Docs.Documents; using Volo.Docs.HtmlConverting; using Volo.Docs.Models; @@ -72,6 +75,11 @@ namespace Volo.Docs.Pages.Documents.Project { DocumentsUrlPrefix = _options.GetFormattedRoutePrefix(); + if (IsDocumentCultureDifferentThanCurrent()) + { + return ReloadPageWithCulture(); + } + await SetProjectAsync(); await SetProjectsAsync(); await SetVersionAsync(); @@ -94,6 +102,24 @@ namespace Volo.Docs.Pages.Documents.Project return Page(); } + private bool IsDocumentCultureDifferentThanCurrent() + { + var currentCulture = CultureInfo.CurrentCulture; + CultureInfo newCulture; + + try + { + newCulture = CultureInfo.GetCultureInfo(LanguageCode); + + return currentCulture.Name != newCulture.Name; + } + catch (CultureNotFoundException) + { + return false; + } + + } + private bool IsDefaultDocument() { return DocumentName == Project.DefaultDocumentName; @@ -120,6 +146,15 @@ namespace Volo.Docs.Pages.Documents.Project return LanguageConfig.Languages.Any(l => l.Code == LanguageCode); } + private IActionResult ReloadPageWithCulture() + { + var languageCodeWithSlashAtTheEnd = string.IsNullOrWhiteSpace(LanguageCode) ? "" : LanguageCode + "/"; + var returnUrl = "/" + DocumentsUrlPrefix + languageCodeWithSlashAtTheEnd + ProjectName + "/" + Version + "/" + + DocumentName; + + return Redirect("/Abp/Languages/Switch?culture=" + LanguageCode + "&uiCulture=" + LanguageCode + "&returnUrl=" + returnUrl); + } + private IActionResult RedirectToDefaultLanguage() { return RedirectToPage(new From 1e7cf34aeb11f167d9389e2a00ceb42bbcd1352d Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 11 Jun 2019 09:42:11 +0300 Subject: [PATCH 31/75] Update Index.cshtml.cs https://github.com/abpframework/abp/issues/1217 --- .../src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index 5de65507a9..74459fe8a4 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -148,8 +148,7 @@ namespace Volo.Docs.Pages.Documents.Project private IActionResult ReloadPageWithCulture() { - var languageCodeWithSlashAtTheEnd = string.IsNullOrWhiteSpace(LanguageCode) ? "" : LanguageCode + "/"; - var returnUrl = "/" + DocumentsUrlPrefix + languageCodeWithSlashAtTheEnd + ProjectName + "/" + Version + "/" + + var returnUrl = "/" + DocumentsUrlPrefix + LanguageCode + "/" + ProjectName + "/" + Version + "/" + DocumentName; return Redirect("/Abp/Languages/Switch?culture=" + LanguageCode + "&uiCulture=" + LanguageCode + "&returnUrl=" + returnUrl); From 2ce5a1c7581c5479e8c56330f6dabbaac7066270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 10:14:00 +0300 Subject: [PATCH 32/75] Add FakeCurrentPrincipalAccessor for tests. --- .../Security/FakeCurrentPrincipalAccessor.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 templates/mvc/test/MyCompanyName.MyProjectName.TestBase/Security/FakeCurrentPrincipalAccessor.cs diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/Security/FakeCurrentPrincipalAccessor.cs new file mode 100644 index 0000000000..ef00c20a24 --- /dev/null +++ b/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/Security/FakeCurrentPrincipalAccessor.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace MyCompanyName.MyProjectName.Security +{ + [Dependency(ReplaceServices = true)] + public class FakeCurrentPrincipalAccessor : ICurrentPrincipalAccessor, ISingletonDependency + { + public ClaimsPrincipal Principal => GetPrincipal(); + private ClaimsPrincipal _principal; + + private ClaimsPrincipal GetPrincipal() + { + if (_principal == null) + { + lock (this) + { + if (_principal == null) + { + _principal = new ClaimsPrincipal( + new ClaimsIdentity( + new List + { + new Claim(AbpClaimTypes.UserId,"2e701e62-0953-4dd3-910b-dc6cc93ccb0d"), + new Claim(AbpClaimTypes.UserName,"admin"), + new Claim(AbpClaimTypes.Email,"admin@abp.io") + } + ) + ); + } + } + } + + return _principal; + } + } +} \ No newline at end of file From 6dbd74ca1f947d1bf5745ecbdd4be8626676dc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 10:14:15 +0300 Subject: [PATCH 33/75] Refactor and comment for base classes. --- .../MyProjectNameAppService.cs | 18 ++++++++++++++++++ .../Controllers/MyProjectNameController.cs | 2 ++ .../MyProjectNameWebModule.cs | 5 +++-- .../MyProjectNameWebModule.cs | 10 +++++----- .../Pages/Index.cshtml | 2 +- .../Pages/Index.cshtml.cs | 2 +- ...ectNamePageBase.cs => MyProjectNamePage.cs} | 5 ++++- ...eModelBase.cs => MyProjectNamePageModel.cs} | 6 ++++-- 8 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs rename templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/{MyProjectNamePageBase.cs => MyProjectNamePage.cs} (56%) rename templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/{MyProjectNamePageModelBase.cs => MyProjectNamePageModel.cs} (59%) diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs new file mode 100644 index 0000000000..8cf7cca603 --- /dev/null +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MyCompanyName.MyProjectName.Localization; +using Volo.Abp.Application.Services; + +namespace MyCompanyName.MyProjectName +{ + /* Inherit your application services from this class. + */ + public abstract class MyProjectNameAppService : ApplicationService + { + protected MyProjectNameAppService() + { + LocalizationResource = typeof(MyProjectNameResource); + } + } +} diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi/Controllers/MyProjectNameController.cs b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi/Controllers/MyProjectNameController.cs index c80e008681..7fff0ecbc5 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi/Controllers/MyProjectNameController.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi/Controllers/MyProjectNameController.cs @@ -3,6 +3,8 @@ using Volo.Abp.AspNetCore.Mvc; namespace MyCompanyName.MyProjectName.Controllers { + /* Inherit your controllers from this class. + */ public abstract class MyProjectNameController : AbpController { protected MyProjectNameController() diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs index 7eba8ff7c8..17df5f5df5 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs @@ -145,8 +145,6 @@ namespace MyCompanyName.MyProjectName.Web { Configure(options => { - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); // options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.UI", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI", Path.DirectorySeparatorChar))); @@ -156,6 +154,9 @@ namespace MyCompanyName.MyProjectName.Web options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}permission-management{0}src{0}Volo.Abp.PermissionManagement.Web", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}identity{0}src{0}Volo.Abp.Identity.Web", Path.DirectorySeparatorChar))); // + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(hostingEnvironment.ContentRootPath); }); } } diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs index 84cacf1d48..77da95f24a 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs @@ -113,11 +113,6 @@ namespace MyCompanyName.MyProjectName.Web { Configure(options => { - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain.Shared", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(hostingEnvironment.ContentRootPath); // options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.UI", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI", Path.DirectorySeparatorChar))); @@ -128,6 +123,11 @@ namespace MyCompanyName.MyProjectName.Web options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}identity{0}src{0}Volo.Abp.Identity.Web", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}account{0}src{0}Volo.Abp.Account.Web", Path.DirectorySeparatorChar))); // + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain.Shared", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Application", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(hostingEnvironment.ContentRootPath); }); } } diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml index 2565dc8267..9324a9891a 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml @@ -1,5 +1,5 @@ @page -@inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePageBase +@inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePage @model MyCompanyName.MyProjectName.Web.Pages.IndexModel @section styles { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml.cs index f8d2476c5b..6a89e42f63 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/Index.cshtml.cs @@ -1,6 +1,6 @@ namespace MyCompanyName.MyProjectName.Web.Pages { - public class IndexModel : MyProjectNamePageModelBase + public class IndexModel : MyProjectNamePageModel { public void OnGet() { diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageBase.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs similarity index 56% rename from templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageBase.cs rename to templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs index 217c70d491..5fe044221d 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageBase.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs @@ -5,7 +5,10 @@ using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; namespace MyCompanyName.MyProjectName.Web.Pages { - public abstract class MyProjectNamePageBase : AbpPage + /* Inherit your UI Pages from this class. To do that, add this line to your Pages (.cshtml files under the Page folder): + * @inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePage + */ + public abstract class MyProjectNamePage : AbpPage { [RazorInject] public IHtmlLocalizer L { get; set; } diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModelBase.cs b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs similarity index 59% rename from templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModelBase.cs rename to templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs index afd22b08c4..d0b9c04a45 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModelBase.cs +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs @@ -3,9 +3,11 @@ using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; namespace MyCompanyName.MyProjectName.Web.Pages { - public abstract class MyProjectNamePageModelBase : AbpPageModel + /* Inherit your PageModel classes from this class. + */ + public abstract class MyProjectNamePageModel : AbpPageModel { - protected MyProjectNamePageModelBase() + protected MyProjectNamePageModel() { LocalizationResourceType = typeof(MyProjectNameResource); } From fbbef8fc2b37aff89569e5b1898b2307730e5800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 10:18:31 +0300 Subject: [PATCH 34/75] Upgrade to the latest NuGet packages. --- .../MyCompanyName.MyProjectName.HttpApi.Host.csproj | 2 +- .../MyCompanyName.MyProjectName.IdentityServer.csproj | 2 +- .../MyCompanyName.MyProjectName.Web.Host.csproj | 2 +- .../MyCompanyName.MyProjectName.Application.Tests.csproj | 2 +- .../MyCompanyName.MyProjectName.Domain.Tests.csproj | 2 +- ...CompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj | 2 +- .../MyCompanyName.MyProjectName.MongoDB.Tests.csproj | 4 ++-- .../MyCompanyName.MyProjectName.TestBase.csproj | 4 ++-- .../MyCompanyName.MyProjectName.Web.Tests.csproj | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index e719e8aeb5..d68c13bc6b 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -15,7 +15,7 @@ - + diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj index cd21488394..8c18d8a43e 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj @@ -26,7 +26,7 @@ - + diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index 8390830f55..4d9d970ace 100644 --- a/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -20,7 +20,7 @@ - + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj index a6f18a84b2..a9845fe4b3 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj index 0cc541e353..24e65fa533 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj index 46e07869da..6b5a5e757c 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index 0ae2555849..7fba41965c 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj index 37db2e4cbd..1b0f53db9c 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj b/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj index 1f93e615d3..f3b0d21c93 100644 --- a/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj +++ b/templates/mvc/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj @@ -14,7 +14,7 @@ - + From 6b54622f9ab79ce4478360d5badd672d3e908e84 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:33:05 +0700 Subject: [PATCH 35/75] vi translation --- .../Volo/Abp/Ui/Navigation/Localization/Resource/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/vi.json diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/vi.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/vi.json new file mode 100644 index 0000000000..c5bf1c5ccd --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "Menu:Administration": "Quản trị" + } +} From 5c99373d5fd8da6102f3ce155ce82f215b181dc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 10:33:13 +0300 Subject: [PATCH 36/75] Upgrade to latest NuGet packages. --- .../Volo.Abp.AspNetCore.Mvc.UI.csproj | 2 +- framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj | 2 +- framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj | 2 +- framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj | 2 +- .../Volo.Abp.EntityFrameworkCore.PostgreSql.csproj | 2 +- .../Volo.Abp.FluentValidation.csproj | 2 +- framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj | 2 +- .../src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj | 2 +- framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj | 2 +- framework/test/AbpTestBase/AbpTestBase.csproj | 4 ++-- .../Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj | 2 +- .../Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj | 2 +- .../Volo.Abp.AspNetCore.Mvc.Tests.csproj | 2 +- .../Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj | 2 +- .../Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj | 2 +- .../Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj | 2 +- .../Volo.Abp.AspNetCore.Tests.csproj | 2 +- .../Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj | 2 +- .../Volo.Abp.Authorization.Tests.csproj | 2 +- .../Volo.Abp.AutoMapper.Tests.csproj | 2 +- .../test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj | 2 +- .../Volo.Abp.BackgroundJobs.Tests.csproj | 2 +- .../test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj | 2 +- .../Volo.Abp.Castle.Core.Tests.csproj | 2 +- .../Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj | 2 +- framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj | 2 +- framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj | 2 +- framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj | 2 +- .../Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj | 2 +- .../Volo.Abp.EntityFrameworkCore.Tests.csproj | 2 +- .../Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj | 2 +- .../Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj | 2 +- .../Volo.Abp.FluentValidation.Tests.csproj | 2 +- .../Volo.Abp.Http.Client.Tests.csproj | 2 +- framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj | 2 +- .../Volo.Abp.Localization.Tests.csproj | 2 +- .../Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj | 2 +- .../test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj | 4 ++-- .../Volo.Abp.MultiTenancy.Tests.csproj | 2 +- .../Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj | 2 +- .../Volo.Abp.Serialization.Tests.csproj | 2 +- .../Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj | 2 +- .../Volo.Abp.Specifications.Tests.csproj | 2 +- .../test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj | 2 +- framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj | 2 +- .../Volo.Abp.UI.Navigation.Tests.csproj | 2 +- framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj | 2 +- .../Volo.Abp.Validation.Tests.csproj | 2 +- .../Volo.Abp.VirtualFileSystem.Tests.csproj | 2 +- 49 files changed, 51 insertions(+), 51 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj index 47ed3724bd..9911b60b5c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj @@ -11,7 +11,7 @@ - + diff --git a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj index 029669c348..2d003f1d48 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -18,7 +18,7 @@ - + \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj index 708c296880..e181af68ac 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj +++ b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj index e5355a19c1..509a438e0f 100644 --- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj +++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj index ccdccb5197..bc148b42c5 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj b/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj index fe8a6a4192..f92af19e56 100644 --- a/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj +++ b/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj index e4b9db1c7b..82a980f1cf 100644 --- a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj +++ b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj index e608961fff..fa2bddfcc6 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj +++ b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj index 9492e6fbf3..0610e45bfd 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj +++ b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/AbpTestBase/AbpTestBase.csproj b/framework/test/AbpTestBase/AbpTestBase.csproj index 4a25e99676..3aeaf7bd7d 100644 --- a/framework/test/AbpTestBase/AbpTestBase.csproj +++ b/framework/test/AbpTestBase/AbpTestBase.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj index 806e426f82..b76e89b5d6 100644 --- a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj index b0d3baaad9..4142fa7f39 100644 --- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj index bd0a8c1ca0..ea9514a9cb 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj @@ -21,7 +21,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj index a25b7d7d8f..93b64b0632 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj @@ -20,7 +20,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj index 74c0285f34..2404de7777 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj index d32284ed87..2d0ddd9412 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj index 9c7544a2f6..e1d676335a 100644 --- a/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj b/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj index cb099c5168..4034493fc7 100644 --- a/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj +++ b/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj index 88925bb67d..40c4907756 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj index 9eb89d4af9..e2f7ed2cfd 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj @@ -14,7 +14,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj b/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj index c92d40f8be..6c1a23c66f 100644 --- a/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj +++ b/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj index 7fa0474264..fea03fb2cf 100644 --- a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj +++ b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj @@ -16,7 +16,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj b/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj index 2b4696092c..3fd378b759 100644 --- a/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj +++ b/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj b/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj index c5a45236c2..35b9edf31f 100644 --- a/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj +++ b/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj @@ -14,7 +14,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj b/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj index bb2664cdc1..0fae5b99d4 100644 --- a/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj +++ b/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj b/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj index bd58cb0d71..119ef18d83 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj +++ b/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj b/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj index 13c9cb2ef3..7862e4e0ef 100644 --- a/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj +++ b/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj b/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj index ad4141f96f..802d8a53b0 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj index ca155ab951..d8b058f05a 100644 --- a/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj @@ -21,7 +21,7 @@ - + diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj index 3f32baa6aa..87cf70501a 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj @@ -21,7 +21,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj b/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj index e810d5ef76..ac8c0ef36f 100644 --- a/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj +++ b/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj index ece1f124d5..02c7475eb0 100644 --- a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj +++ b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj b/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj index b0bc864896..999d06d67c 100644 --- a/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj +++ b/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj b/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj index 4997863830..aff0575607 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj b/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj index e3e1c560c8..c221b309c4 100644 --- a/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj +++ b/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj @@ -8,7 +8,7 @@ - + diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj b/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj index 98a01e2fc7..1decc345f4 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj +++ b/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj b/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj index 062cfaf730..1d83b1e54f 100644 --- a/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj +++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj @@ -16,7 +16,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj index 5ca5401bac..a99a675193 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj @@ -19,8 +19,8 @@ - - + + \ No newline at end of file diff --git a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj index 631ad1ed81..16c27a26a6 100644 --- a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj +++ b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj b/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj index 5339246c52..46b4c9e952 100644 --- a/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj +++ b/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj b/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj index 99db6083c2..a7325c95c0 100644 --- a/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj +++ b/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj b/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj index 1e9bd3f4a0..76f2d05afa 100644 --- a/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj +++ b/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj b/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj index 6f2cbe09f8..e3f35153f9 100644 --- a/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj +++ b/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj b/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj index 3985910708..51b60b693f 100644 --- a/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj +++ b/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj b/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj index 4e7b58ee84..3da0bcd7ce 100644 --- a/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj +++ b/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj index 10318fbf90..4fa8929ed4 100644 --- a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj +++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj b/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj index f3dede4b21..574891cc27 100644 --- a/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj +++ b/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj b/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj index 60308b96ae..7fb87036e2 100644 --- a/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj +++ b/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj index 895b8231ce..d69c461c29 100644 --- a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj +++ b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj @@ -18,7 +18,7 @@ - + From 04770332c03ad51695c14058602a2bfc75ac2953 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:34:28 +0700 Subject: [PATCH 37/75] vi translation --- .../Volo/Abp/AspNetCore/Mvc/Localization/Resource/vi.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/vi.json diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/vi.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/vi.json new file mode 100644 index 0000000000..046b7893f3 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/vi.json @@ -0,0 +1,7 @@ +{ + "culture": "vi", + "texts": { + "BirthDate": "Ngày sinh", + "Value1": "Giá trị thứ nhất" + } +} From 5241eb8063c2ac8638f5dfc76f018a70e7a9bc8b Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:35:08 +0700 Subject: [PATCH 38/75] vi translation --- .../Volo/Abp/Emailing/Localization/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/vi.json diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/vi.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/vi.json new file mode 100644 index 0000000000..8261599d78 --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "hello": "xin chào" + } +} From 213b5cc2da80aa6de51b6cbeee2c6af0fe1d750a Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:36:57 +0700 Subject: [PATCH 39/75] vi translation --- .../Localization/TestResources/Base/CountryNames/vi.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/vi.json diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/vi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/vi.json new file mode 100644 index 0000000000..a429f8295b --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/vi.json @@ -0,0 +1,7 @@ +{ + "culture": "vi", + "texts": { + "USA": "Nước Mỹ", + "Brazil": "Brazil" + } +} From 8275258c82b56732fb69c2587cd735eae923c2cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 10:39:15 +0300 Subject: [PATCH 40/75] Fix order of ReplaceEmbeddedByPhysical statements. --- .../MyProjectNameWebHostModule.cs | 5 +++-- .../MyProjectNameWebUnifiedModule.cs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs index 8cbb8fa01a..ea15dd040b 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs @@ -150,8 +150,6 @@ namespace MyCompanyName.MyProjectName { Configure(options => { - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); // options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.UI", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI", Path.DirectorySeparatorChar))); @@ -161,6 +159,9 @@ namespace MyCompanyName.MyProjectName options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}permission-management{0}src{0}Volo.Abp.PermissionManagement.Web", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}identity{0}src{0}Volo.Abp.Identity.Web", Path.DirectorySeparatorChar))); // + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Web", Path.DirectorySeparatorChar))); }); } } diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs index 85e77ff406..76ae5ef988 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs @@ -69,10 +69,10 @@ namespace MyCompanyName.MyProjectName { Configure(options => { - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain.Shared", Path.DirectorySeparatorChar))); - options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application", Path.DirectorySeparatorChar))); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Web", Path.DirectorySeparatorChar))); }); } From ad1b85e5e0c2d01885c461073bb2132588ba113e Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:40:44 +0700 Subject: [PATCH 41/75] vi translation --- .../Abp/Localization/TestResources/Base/Validation/vi.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/vi.json diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/vi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/vi.json new file mode 100644 index 0000000000..583eebab13 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/vi.json @@ -0,0 +1,7 @@ +{ + "culture": "vi", + "texts": { + "ThisFieldIsRequired": "Trường này là bắt buộc", + "MaxLenghtErrorMessage": "Trường này có thể có tối đa là '{0}' kí tự" + } +} From 83e25d0af75afcff811745a305c894a750a90264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 10:42:22 +0300 Subject: [PATCH 42/75] Upgrade mvc-module template to the latest NuGet packages. --- .../MyCompanyName.MyProjectName.HttpApi.Host.csproj | 2 +- .../MyCompanyName.MyProjectName.IdentityServer.csproj | 2 +- .../MyCompanyName.MyProjectName.Web.Host.csproj | 2 +- .../MyCompanyName.MyProjectName.Application.Tests.csproj | 2 +- .../MyCompanyName.MyProjectName.Domain.Tests.csproj | 2 +- ...MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj | 2 +- .../MyCompanyName.MyProjectName.MongoDB.Tests.csproj | 2 +- .../MyCompanyName.MyProjectName.TestBase.csproj | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index 9e51bd05cf..d6436852b6 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -14,7 +14,7 @@ - + diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj b/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj index b1d532024c..cdf7bcb65e 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj @@ -12,7 +12,7 @@ - + diff --git a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index 8a5fb3e236..dd7ba84dbd 100644 --- a/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/mvc-module/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -14,7 +14,7 @@ - + diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj index bfefdfcbfd..22898fcde0 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj index 68328a77a1..2b2fd34bea 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj index 7a05b65e55..3b0c247ddf 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index e71954d6a3..8ddb93bfdc 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/mvc-module/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj b/templates/mvc-module/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj index 1481ea0ad4..4e2b8b1ed4 100644 --- a/templates/mvc-module/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj +++ b/templates/mvc-module/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj @@ -8,7 +8,7 @@ - + From 6e0b468efad10481e291fdfd2cc34764da17a134 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:42:37 +0700 Subject: [PATCH 43/75] vi translation --- .../Abp/Localization/TestResources/Source/vi.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/vi.json diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/vi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/vi.json new file mode 100644 index 0000000000..6f5bff743c --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/vi.json @@ -0,0 +1,11 @@ +{ + "culture": "vi", + "texts": { + "Hello {0}.": "Xin chào {0}.", + "Car": "Car", + "CarPlural": "Cars", + "MaxLenghtErrorMessage": "Kích thước trường này có tối đa '{0}' kí tự", + "Universe": "Vũ trụ", + "FortyTwo": "Bốn mươi hai" + } +} From 09b1e13f407758535fc96c53080a6c8ad4beb88c Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:43:30 +0700 Subject: [PATCH 44/75] vi translation --- .../Volo/Abp/Localization/TestResources/SourceExt/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/vi.json diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/vi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/vi.json new file mode 100644 index 0000000000..d4d350246f --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "SeeYou": "Hẹn gặp lại" + } +} From 84b8e003079a52273dacf23f338f88ccd31b7e2c Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:45:08 +0700 Subject: [PATCH 45/75] vi translation --- .../Localization/MyProjectName/Web/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/vi.json diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/vi.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} From f4fb3cd9392eead42931d675d9a599bf6c017eb3 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:45:46 +0700 Subject: [PATCH 46/75] vi translation --- .../Localization/MyProjectName/DomainShared/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/vi.json diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/vi.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} From f2b466c044c0d8f5e13a520fa30b65b18298aa74 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:46:31 +0700 Subject: [PATCH 47/75] vi translation --- .../Localization/MyProjectName/ApplicationContracts/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/vi.json diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/vi.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/vi.json new file mode 100644 index 0000000000..a60afc038e --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "Permission:MyProjectName": "TenDuAnCuaBan" + } +} From 4c423a7b7555ccbfb66bf1e357f5170bf22cb9ef Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:48:27 +0700 Subject: [PATCH 48/75] vi translation --- .../Resources/ProductManagement/vi.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json new file mode 100644 index 0000000000..6b51506813 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/vi.json @@ -0,0 +1,16 @@ +{ + "culture": "vi", + "texts": { + "Menu:ProductManagement": "Quản lý sản phẩm", + "Menu:Products": "Sản phẩm", + "ProductManagement": "Quản lý sản phẩm", + "CreateANewProduct": "Tạo một sản phẩm mới", + "Products": "Sản phẩm", + "StockCount": "Số chứng khoán", + "Code": "Mã", + "Name": "Tên", + "Price": "Giá", + "ImageName": "Tên ảnh", + "ProductDeletionWarningMessage": "Bạn có chắc chắn muốn xóa sản phẩm này?" + } +} From 687603d7a591f39877534f49c0c24f41b6fb5776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 10:56:03 +0300 Subject: [PATCH 49/75] Update background-jobs module NuGet packages. --- .../Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj | 2 +- .../Volo.Abp.BackgroundJobs.Domain.Tests.csproj | 2 +- .../Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj | 2 +- .../Volo.Abp.BackgroundJobs.TestBase.csproj | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj index 8134b0c512..515f5d37f6 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj @@ -6,7 +6,7 @@ - + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj index a8ff824305..66ef602232 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj index 722d94f88e..7fd7558b02 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj index 1f4db1af41..ce6e3b7c1b 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj @@ -14,8 +14,8 @@ - - + + From 272981691ae64a1587ac9b45822a15f4a804b755 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 14:59:49 +0700 Subject: [PATCH 50/75] vi translation --- .../ProductManagement/Localization/Domain/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi.json diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} From 7c2e13db65dbf6b1dc0bfa7a90bb275452a4e0ae Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:01:20 +0700 Subject: [PATCH 51/75] vi translation --- .../ProductManagement/Localization/Domain/vi | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/vi @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} From 6f9ab80d370050e41761d1002132da7acbbe03d7 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:02:38 +0700 Subject: [PATCH 52/75] vi translation --- .../Localization/ApplicationContracts/vi.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/vi.json diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/vi.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/vi.json new file mode 100644 index 0000000000..97cca61fd2 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/vi.json @@ -0,0 +1,10 @@ +{ + "culture": "vi", + "texts": { + "Permission:ProductManagement": "Quản lý sản phẩm", + "Permission:Products": "Sản phẩm", + "Permission:Edit": "Sửa", + "Permission:Delete": "Xóa", + "Permission:Create": "Tạo" + } +} From 72cd5b8cfa0472ea98a353cb3256d3d13c56595e Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:05:44 +0700 Subject: [PATCH 53/75] vi translation --- .../Localization/DashboardDemo/vi.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/vi.json diff --git a/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/vi.json b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/vi.json new file mode 100644 index 0000000000..c629274a1b --- /dev/null +++ b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/vi.json @@ -0,0 +1,10 @@ +{ + "culture": "vi", + "texts": { + "Menu:Home": "Trang chủ", + "Welcome": "Xin chào bạn", + "RolesInApplication": "Vai trò trong ứng dụng", + "UserCount": "Số lượng người dùng", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là mẫu khởi động dự án dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} From b421f915c15b1ba6d6e3209a8aee110a1dbf328a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 11:15:05 +0300 Subject: [PATCH 54/75] Module template refactor. --- .../Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj | 4 ++-- ...ServiceBase.cs => MyProjectNameAppService.cs} | 4 ++-- .../Samples/SampleAppService.cs | 2 +- ...trollerBase.cs => MyProjectNameController.cs} | 4 ++-- .../Samples/SampleController.cs | 2 +- .../Pages/MyProjectName/Index.cshtml | 7 +++++++ .../Pages/MyProjectName/Index.cshtml.cs | 16 ++++++++++++++++ .../Pages/MyProjectNamePage.cs | 16 ++++++++++++++++ .../Pages/MyProjectNamePageModel.cs | 15 +++++++++++++++ 9 files changed, 62 insertions(+), 8 deletions(-) rename templates/mvc-module/src/MyCompanyName.MyProjectName.Application/{MyProjectNameAppServiceBase.cs => MyProjectNameAppService.cs} (65%) rename templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/{MyProjectNameControllerBase.cs => MyProjectNameController.cs} (66%) create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml.cs create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj index f3fb433d10..e999356678 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppServiceBase.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs similarity index 65% rename from templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppServiceBase.cs rename to templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs index e54468cb79..31bfbeb0de 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppServiceBase.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/MyProjectNameAppService.cs @@ -3,9 +3,9 @@ using Volo.Abp.Application.Services; namespace MyCompanyName.MyProjectName { - public abstract class MyProjectNameAppServiceBase : ApplicationService + public abstract class MyProjectNameAppService : ApplicationService { - protected MyProjectNameAppServiceBase() + protected MyProjectNameAppService() { LocalizationResource = typeof(MyProjectNameResource); } diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/Samples/SampleAppService.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/Samples/SampleAppService.cs index d193c3f895..f34b7771bd 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/Samples/SampleAppService.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application/Samples/SampleAppService.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Authorization; namespace MyCompanyName.MyProjectName.Samples { - public class SampleAppService : MyProjectNameAppServiceBase, ISampleAppService + public class SampleAppService : MyProjectNameAppService, ISampleAppService { public Task GetAsync() { diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameControllerBase.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameController.cs similarity index 66% rename from templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameControllerBase.cs rename to templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameController.cs index f447b65456..1dd9a6c8b2 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameControllerBase.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/MyProjectNameController.cs @@ -3,9 +3,9 @@ using Volo.Abp.AspNetCore.Mvc; namespace MyCompanyName.MyProjectName { - public class MyProjectNameControllerBase : AbpController + public abstract class MyProjectNameController : AbpController { - public MyProjectNameControllerBase() + protected MyProjectNameController() { LocalizationResource = typeof(MyProjectNameResource); } diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/Samples/SampleController.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/Samples/SampleController.cs index 7c4de3b65e..1bf34c32c4 100644 --- a/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/Samples/SampleController.cs +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.HttpApi/Samples/SampleController.cs @@ -7,7 +7,7 @@ namespace MyCompanyName.MyProjectName.Samples { [RemoteService] [Route("api/MyProjectName/sample")] - public class SampleController : MyProjectNameControllerBase, ISampleAppService + public class SampleController : MyProjectNameController, ISampleAppService { private readonly ISampleAppService _sampleAppService; diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml new file mode 100644 index 0000000000..0ef7562269 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml @@ -0,0 +1,7 @@ +@page +@inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePage +@model MyCompanyName.MyProjectName.Web.Pages.MyProjectName.IndexModel +@{ +} +

MyProjectName

+

A sample page for the MyProjectName module.

\ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml.cs new file mode 100644 index 0000000000..a9c43a1c88 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectName/Index.cshtml.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace MyCompanyName.MyProjectName.Web.Pages.MyProjectName +{ + public class IndexModel : PageModel + { + public void OnGet() + { + } + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs new file mode 100644 index 0000000000..5fe044221d --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePage.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Mvc.Localization; +using Microsoft.AspNetCore.Mvc.Razor.Internal; +using MyCompanyName.MyProjectName.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace MyCompanyName.MyProjectName.Web.Pages +{ + /* Inherit your UI Pages from this class. To do that, add this line to your Pages (.cshtml files under the Page folder): + * @inherits MyCompanyName.MyProjectName.Web.Pages.MyProjectNamePage + */ + public abstract class MyProjectNamePage : AbpPage + { + [RazorInject] + public IHtmlLocalizer L { get; set; } + } +} diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs new file mode 100644 index 0000000000..d0b9c04a45 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Pages/MyProjectNamePageModel.cs @@ -0,0 +1,15 @@ +using MyCompanyName.MyProjectName.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace MyCompanyName.MyProjectName.Web.Pages +{ + /* Inherit your PageModel classes from this class. + */ + public abstract class MyProjectNamePageModel : AbpPageModel + { + protected MyProjectNamePageModel() + { + LocalizationResourceType = typeof(MyProjectNameResource); + } + } +} \ No newline at end of file From 8b1702543903a56c99527f54ee7da6ab6828aea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 11:33:34 +0300 Subject: [PATCH 55/75] Set _createdMappingsBefore before the initialization. --- .../Volo/Abp/AutoMapper/AbpAutoMapperModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs index 2e8c10bad0..0c31fa31ce 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -59,14 +59,14 @@ namespace Volo.Abp.AutoMapper //We should prevent duplicate mapping in an application, since Mapper is static. if (!_createdMappingsBefore) { + _createdMappingsBefore = true; + Mapper.Initialize(mapperConfigurationExpression => { ConfigureAll(new AbpAutoMapperConfigurationContext(mapperConfigurationExpression, scope.ServiceProvider)); }); ValidateAll(Mapper.Configuration); - - _createdMappingsBefore = true; } scope.ServiceProvider.GetRequiredService().Mapper = Mapper.Instance; From 40f737754fd6806a225b9b7081feb7ce7daba984 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:39:51 +0700 Subject: [PATCH 56/75] vi translation --- .../Localization/BookStore/vi.json | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json diff --git a/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json new file mode 100644 index 0000000000..3aad66a64a --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json @@ -0,0 +1,20 @@ +{ + "culture": "vi", + "texts": { + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án mẫu dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io.", + "Menu:BookStore": "Cửa hàng sách", + "Menu:Books": "Sách", + "Name": "Tên", + "Type": "Loại", + "PublishDate": "Ngày xuất bản", + "Price": "Giá", + "CreationTime": "Thời gian tạo", + "NewBook": "Sách mới", + "Books": "Sách", + "Update": "Cập nhật", + "BookDeletionConfirmationMessage": "Bạn có chắc chắn xóa sách {0}?", + "SuccessfullyDeleted": "Xóa thành công." + } +} From 67982244d3db65a433000fd609f41138d1e87140 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:41:06 +0700 Subject: [PATCH 57/75] vi translation --- .../Localization/Resources/AbpSettingManagement/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/vi.json diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/vi.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/vi.json new file mode 100644 index 0000000000..9da742c377 --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "Settings": "Cài đặt" + } +} From 4340e214cfd26928bb2d5452630ff3f9cdbfe5b5 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:42:37 +0700 Subject: [PATCH 58/75] vi translation --- .../Localization/Resources/FeatureManagement/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/vi.json diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/vi.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/vi.json new file mode 100644 index 0000000000..f8eda1da21 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + "Features": "Tính năng" + } +} From aa2a33387a845b659f523918411acc6bc7167039 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:43:14 +0700 Subject: [PATCH 59/75] vi translation --- .../Volo/Abp/FeatureManagement/Localization/Domain/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/vi.json diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/vi.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} From a31e3b4fbe4aa02add338fc429d9cc7eaeb5ce36 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:43:56 +0700 Subject: [PATCH 60/75] vi translation --- .../Localization/ApplicationContracts/vi.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/vi.json diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/vi.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/vi.json new file mode 100644 index 0000000000..d8eb5f3c75 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/vi.json @@ -0,0 +1,6 @@ +{ + "culture": "vi", + "texts": { + + } +} From b9e5ba4995b79cc2e7ca9b6b7a2593adf9166f42 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:49:35 +0700 Subject: [PATCH 61/75] vi translation --- .../Localization/Resources/Docs/Web/vi.json | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/vi.json diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/vi.json b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/vi.json new file mode 100644 index 0000000000..d39b27f295 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/vi.json @@ -0,0 +1,27 @@ +{ + "culture": "vi", + "texts": { + "Menu:DocumentManagement": "Tài liệu", + "Menu:ProjectManagement": "Dự án", + "CreateANewProject": "Tạo dự án mới", + "Edit": "Sửa", + "Create": "Tạo", + "Projects": "Dự án", + "Name": "Tên", + "ShortName": "Tên rút gọn", + "DocumentStoreType": "DocumentStoreType", + "Format": "Định dạng", + "ShortNameInfoText": "Sẽ được sử dụng cho URL duy nhất..", + "DisplayName:Name": "Tên", + "DisplayName:ShortName": "Tên rút gọn", + "DisplayName:Format": "Định dạng", + "DisplayName:DefaultDocumentName": "Tên tài liệu mặc định", + "DisplayName:NavigationDocumentName": "Tên tài liệu điều hướng", + "DisplayName:MinimumVersion": "Phiên bản tối thiểu", + "DisplayName:MainWebsiteUrl": "URL trang web chính", + "DisplayName:LatestVersionBranchName": "Tên nhánh phiên bản mới nhất", + "DisplayName:GitHubRootUrl": "URL gốc của GitHub", + "DisplayName:GitHubAccessToken": "GitHub access token", + "DisplayName:GitHubUserAgent": "GitHub user agent" + } +} From 4d4465cc1dd7671ba521821852b255080aeb9d90 Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:51:42 +0700 Subject: [PATCH 62/75] vi translation --- .../Resources/Docs/ApplicationContracts/vi.sjon | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.sjon diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.sjon b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.sjon new file mode 100644 index 0000000000..0697ddf6e8 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.sjon @@ -0,0 +1,10 @@ +{ + "culture": "vi", + "texts": { + "Permission:DocumentManagement": "Quản lý tài liệu", + "Permission:Projects": "Dự án", + "Permission:Edit": "Sửa", + "Permission:Delete": "Xóa", + "Permission:Create": "Tạo" + } +} From 02ca332eeb41ab2fdf53c23492b2f3e817ab416e Mon Sep 17 00:00:00 2001 From: nguyendev Date: Tue, 11 Jun 2019 15:53:17 +0700 Subject: [PATCH 63/75] vi translation --- .../Localization/Resources/VoloDocs/Web/vi.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/vi.json diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/vi.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/vi.json new file mode 100644 index 0000000000..46afd97fd0 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/vi.json @@ -0,0 +1,9 @@ +{ + "culture": "vi", + "texts": { + "WelcomeVoloDocs": "Chào mừng đến với VoloDocs!", + "NoProjectWarning": "Không có dự án nào!", + "CreateYourFirstProject": "Nhấn vào đây để bắt đầu dự án đầu tiên của bạn", + "NoProject": "Không có dự án!" + } +} From 06c4a5d022b83c8ad5500eb325c4ff9f861ce608 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 11 Jun 2019 13:37:13 +0300 Subject: [PATCH 64/75] resolves https://github.com/abpframework/abp/issues/1261 --- modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs | 2 +- .../Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs | 2 +- modules/docs/src/Volo.Docs.Web/DocsUrlOptions.cs | 4 ++-- .../Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs | 2 +- .../docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs | 2 +- .../src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs index ca28c0ef8f..ec66947dd7 100644 --- a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs @@ -20,7 +20,7 @@ namespace VoloDocs.Web.Pages //TODO: Create HomeController & Index instead of Page. Otherwise, we have an empty Index.cshtml file. if (!_urlOptions.RoutePrefix.IsNullOrWhiteSpace()) { - return Redirect("./" + _urlOptions.GetFormattedRoutePrefix()); + return Redirect("." + _urlOptions.GetFormattedRoutePrefix()); } return Page(); diff --git a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs index 709614a230..edc7bfb24d 100644 --- a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs +++ b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs @@ -144,7 +144,7 @@ namespace Volo.Docs.Areas.Documents.TagHelpers var prefix = _urlOptions.GetFormattedRoutePrefix(); - return "/" + prefix + LanguageCode + "/" + ProjectName + "/" + Version + "/" + pathWithoutFileExtension; + return prefix + LanguageCode + "/" + ProjectName + "/" + Version + "/" + pathWithoutFileExtension; } private string RemoveFileExtensionFromPath(string path) diff --git a/modules/docs/src/Volo.Docs.Web/DocsUrlOptions.cs b/modules/docs/src/Volo.Docs.Web/DocsUrlOptions.cs index 283b343965..4c72a7bcbb 100644 --- a/modules/docs/src/Volo.Docs.Web/DocsUrlOptions.cs +++ b/modules/docs/src/Volo.Docs.Web/DocsUrlOptions.cs @@ -13,10 +13,10 @@ namespace Volo.Docs { if (string.IsNullOrWhiteSpace(RoutePrefix)) { - return ""; + return "/"; } - return RoutePrefix.Trim('/').EnsureEndsWith('/'); + return RoutePrefix.EnsureEndsWith('/').EnsureStartsWith('/'); } } } diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs index 5bf88664ef..426a42d59d 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs @@ -23,7 +23,7 @@ namespace Volo.Docs.Markdown _urlOptions = urlOptions.Value; } - private const string MdLinkFormat = "[{0}](/{1}{2}/{3}/{4}{5}/{6})"; + private const string MdLinkFormat = "[{0}]({1}{2}/{3}/{4}{5}/{6})"; private const string MarkdownLinkRegExp = @"\[(.*)\]\((.*\.md)\)"; private const string AnchorLinkRegExp = @"]+href=\""(.*?)\""[^>]*>(.*)?"; diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs index 186a9122db..25083571b4 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs @@ -33,7 +33,7 @@ namespace Volo.Docs.Pages.Documents if (listResult.Items.Count == 1) { - return Redirect("./" + DocumentsUrlPrefix + listResult.Items[0].ShortName); + return Redirect("." + DocumentsUrlPrefix + listResult.Items[0].ShortName); } Projects = listResult.Items; diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index 74459fe8a4..94fec82c09 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -148,7 +148,7 @@ namespace Volo.Docs.Pages.Documents.Project private IActionResult ReloadPageWithCulture() { - var returnUrl = "/" + DocumentsUrlPrefix + LanguageCode + "/" + ProjectName + "/" + Version + "/" + + var returnUrl = DocumentsUrlPrefix + LanguageCode + "/" + ProjectName + "/" + Version + "/" + DocumentName; return Redirect("/Abp/Languages/Switch?culture=" + LanguageCode + "&uiCulture=" + LanguageCode + "&returnUrl=" + returnUrl); @@ -351,7 +351,7 @@ namespace Volo.Docs.Pages.Documents.Project LanguageSelectListItems.Add( new SelectListItem( language.DisplayName, - "/" + DocumentsUrlPrefix + language.Code + "/" + Project.ShortName + "/" + Version + "/" + DocumentName, + DocumentsUrlPrefix + language.Code + "/" + Project.ShortName + "/" + Version + "/" + DocumentName, language.Code == LanguageCode ) ); From 5616ffa8a6275ecae5f17cdd9c03bdc3fbfbe2ad Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 11 Jun 2019 13:43:48 +0300 Subject: [PATCH 65/75] Fix: broken edit link on docs --- .../Volo/Docs/GitHub/Documents/GithubDocumentStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs index d0bdccac54..c2eb1bb24d 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs @@ -37,7 +37,7 @@ namespace Volo.Docs.GitHub.Documents var rawDocumentUrl = rawRootUrl + documentName; var commitHistoryUrl = project.GetGitHubUrlForCommitHistory() + documentName; var isNavigationDocument = documentName == project.NavigationDocumentName; - var editLink = rootUrl.ReplaceFirst("/tree/", "/blob/") + documentName; + var editLink = rootUrl.ReplaceFirst("/tree/", "/blob/") + languageCode + "/" + documentName; var localDirectory = ""; var fileName = documentName; From 824de4c615c1d4d1d7f07d6ec1e8d0cb3a303c72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 14:03:23 +0300 Subject: [PATCH 66/75] Ignore all .vs folders --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 545de1cc28..1b1e3d8201 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ bld/ [Ll]og/ # Visual Studio 2015 cache/options directory -.vs/ +**/.vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ From 74ea58cb386c4f8cd6c7c0e6f99c36083098f6cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 Jun 2019 19:20:08 +0300 Subject: [PATCH 67/75] Created empty docs. --- docs/en/AspNetCore/Auto-API-Controllers.md | 2 +- docs/en/JavaScript/Dynamic-JavaScript-API-Clients.md | 3 +++ docs/en/Value-Objects.md | 3 +++ docs/en/Value-Types.md | 3 --- 4 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 docs/en/JavaScript/Dynamic-JavaScript-API-Clients.md create mode 100644 docs/en/Value-Objects.md delete mode 100644 docs/en/Value-Types.md diff --git a/docs/en/AspNetCore/Auto-API-Controllers.md b/docs/en/AspNetCore/Auto-API-Controllers.md index d08f13003e..77819c48c9 100644 --- a/docs/en/AspNetCore/Auto-API-Controllers.md +++ b/docs/en/AspNetCore/Auto-API-Controllers.md @@ -2,7 +2,7 @@ Once you create an [application service](../Application-Services.md), you generally want to create an API controller to expose this service as an HTTP (REST) API endpoint. A typical API controller does nothing but redirects method calls to the application service and configures the REST API using attributes like [HttpGet], [HttpPost], [Route]... etc. -ABP can **automagically** configures your application services as MVC API Controllers by convention. Most of time you don't care about its detailed configuration, but it's possible fully customize it. +ABP can **automagically** configure your application services as API Controllers by convention. Most of time you don't care about its detailed configuration, but it's possible to fully customize it. ## Configuration diff --git a/docs/en/JavaScript/Dynamic-JavaScript-API-Clients.md b/docs/en/JavaScript/Dynamic-JavaScript-API-Clients.md new file mode 100644 index 0000000000..539d3ac15a --- /dev/null +++ b/docs/en/JavaScript/Dynamic-JavaScript-API-Clients.md @@ -0,0 +1,3 @@ +## Dynamic JavaScript API Clients + +TODO \ No newline at end of file diff --git a/docs/en/Value-Objects.md b/docs/en/Value-Objects.md new file mode 100644 index 0000000000..0c6c8d4424 --- /dev/null +++ b/docs/en/Value-Objects.md @@ -0,0 +1,3 @@ +## Value Objects + +TODO \ No newline at end of file diff --git a/docs/en/Value-Types.md b/docs/en/Value-Types.md deleted file mode 100644 index a0e340063c..0000000000 --- a/docs/en/Value-Types.md +++ /dev/null @@ -1,3 +0,0 @@ -## Value Types - -TODO \ No newline at end of file From c1e0e980439a57c837271373080951c0d1fdb2f0 Mon Sep 17 00:00:00 2001 From: Tomasz Lewandowski Date: Tue, 11 Jun 2019 18:54:55 +0200 Subject: [PATCH 68/75] Polish translations --- .../Mvc/UI/MultiTenancy/Localization/pl.json | 11 ++++ .../Resources/AbpValidation/pl.json | 20 ++++++++ .../Navigation/Localization/Resource/pl.json | 6 +++ .../Localization/Resources/AbpUi/pl.json | 51 +++++++++++++++++++ .../Mvc/Localization/Resource/pl.json | 7 +++ .../Volo/Abp/Emailing/Localization/pl.json | 6 +++ .../TestResources/Base/CountryNames/pl.json | 7 +++ .../TestResources/Base/Validation/pl.json | 7 +++ .../Localization/TestResources/Source/pl.json | 11 ++++ .../TestResources/SourceExt/pl.json | 6 +++ .../Resources/AbpAccount/Web/pl.json | 21 ++++++++ .../Blogging/ApplicationContracts/pl.json | 14 +++++ .../Resources/Blogging/Web/pl.json | 47 +++++++++++++++++ .../Resources/VoloDocs/Web/pl.json | 9 ++++ .../Docs/ApplicationContracts/pl.json | 10 ++++ .../Localization/Resources/Docs/Web/pl.json | 27 ++++++++++ .../Volo/Docs/Localization/Domain/pl.json | 18 +++++++ .../Localization/ApplicationContracts/pl.json | 6 +++ .../Localization/Domain/pl.json | 6 +++ .../Resources/FeatureManagement/pl.json | 6 +++ .../Localization/ApplicationContracts/pl.json | 14 +++++ .../Abp/Identity/Localization/Domain/pl.json | 33 ++++++++++++ .../Resources/AbpIdentity/pl.json | 39 ++++++++++++++ .../Resources/AbpPermissionManagement/pl.json | 10 ++++ .../Resources/AbpSettingManagement/pl.json | 6 +++ .../Localization/ApplicationContracts/pl.json | 11 ++++ .../Resources/AbpTenantManagement/Web/pl.json | 14 +++++ .../Localization/BookStore/pl.json | 20 ++++++++ .../Localization/DashboardDemo/pl.json | 10 ++++ .../Localization/ApplicationContracts/pl.json | 10 ++++ .../Localization/Domain/pl.json | 6 +++ .../Resources/ProductManagement/pl.json | 16 ++++++ .../ApplicationContracts/pl.json | 6 +++ .../MyProjectName/DomainShared/pl.json | 6 +++ .../Localization/MyProjectName/Web/pl.json | 6 +++ .../Localization/MyProjectName/pl.json | 8 +++ 36 files changed, 511 insertions(+) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl.json create mode 100644 framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pl.json create mode 100644 framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pl.json create mode 100644 framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl.json create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pl.json create mode 100644 framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pl.json create mode 100644 framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pl.json create mode 100644 framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pl.json create mode 100644 framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pl.json create mode 100644 framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/pl.json create mode 100644 modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pl.json create mode 100644 modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pl.json create mode 100644 modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pl.json create mode 100644 modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pl.json create mode 100644 modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl.json create mode 100644 modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pl.json create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl.json create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pl.json create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pl.json create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pl.json create mode 100644 modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pl.json create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/pl.json create mode 100644 modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/pl.json create mode 100644 modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pl.json create mode 100644 modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pl.json create mode 100644 modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pl.json create mode 100644 modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/pl.json create mode 100644 samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json create mode 100644 samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/pl.json create mode 100644 samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/pl.json create mode 100644 samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/pl.json create mode 100644 samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl.json create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pl.json create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pl.json create mode 100644 templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pl.json create mode 100644 templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/pl.json diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl.json new file mode 100644 index 0000000000..8509b7d02b --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl.json @@ -0,0 +1,11 @@ +{ + "culture": "pl", + "texts": { + "GivenTenantIsNotAvailable": "Podany tenant jest niedostępny: {0}", + "Tenant": "Tenant", + "Switch": "zmień", + "Name": "Nazwa", + "SwitchTenantHint": "Pozostaw pole nazwy puste, aby przełączyć się na stronę hosta.", + "NotSelected": "Nie wybrano" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pl.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pl.json new file mode 100644 index 0000000000..eef572eb13 --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pl.json @@ -0,0 +1,20 @@ +{ + "culture": "pl", + "texts": { + "'{0}' and '{1}' do not match.": "'{0}' i '{1}' nie są takie same.", + "The {0} field is not a valid credit card number.": "Pole {0} nie jest poprawnym numerem karty kredytowej.", + "{0} is not valid.": "{0} jest niepoprawne.", + "The {0} field is not a valid e-mail address.": "Pole {0} nie jest poprawnym adresem e-mail.", + "The {0} field only accepts files with the following extensions: {1}": "Polr {0} przyjmuje pliki tylko z następującymi rozszerzeniami: {1}", + "The field {0} must be a string or array type with a maximum length of '{1}'.": "Pole {0} musi być łańcuchem znaków lub talicą o maksymalnej długości '{1}'.", + "The field {0} must be a string or array type with a minimum length of '{1}'.": "Pole {0} musi być łańcuchem znaków lub talicą o minimalnej długości '{1}'.", + "The {0} field is not a valid phone number.": "Pole {0} nie jest poprawnym numerem telefonu.", + "The field {0} must be between {1} and {2}.": "Pole {0} musi być pomiędzy {1} i {2}.", + "The field {0} must match the regular expression '{1}'.": "Pole {0} musi pasować do wyrażenia regularnego '{1}'.", + "The {0} field is required.": "Pole {0} jest wymagane.", + "The field {0} must be a string with a maximum length of {1}.": "Pole {0} musi być łańcuchem znaków o maksymalnej długości {1}.", + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Pole {0} musi być łańcuchem znaków o minimalnej długości {2} i maksymalnej długości {1}.", + "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "Pole {0} nie jest prawidłowym, w pełni kwalifikowanym adresem URL http, https lub ftp.", + "The field {0} is invalid.": "Pole {0} jest niepoprawne." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pl.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pl.json new file mode 100644 index 0000000000..557d01eb31 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "Menu:Administration": "Administracja" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl.json new file mode 100644 index 0000000000..5f369760a1 --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl.json @@ -0,0 +1,51 @@ +{ + "culture": "pl", + "texts": { + "InternalServerErrorMessage": "Błąd wewnętrzny serwera podczas przetwarzania żądania!", + "ValidationErrorMessage": "Twoje żądanie jest niepoprawnie!", + "ValidationNarrativeErrorMessageTitle": "Wykryto następujące błędy podczas walidacji.", + "DefaultErrorMessage": "Wystąpił błąd!", + "DefaultErrorMessageDetail": "Treść błędu nie została wysłana z serwera.", + "DefaultErrorMessage401": "Nie jesteś zalogowany!", + "DefaultErrorMessage401Detail": "Musisz się zalogować, aby wykonać tą operację.", + "DefaultErrorMessage403": "Nie jesteś zautentykowany!", + "DefaultErrorMessage403Detail": "Nie masz uprawnień do wykonania tej operacji!", + "DefaultErrorMessage404": "Nie znaleziono zasobu!", + "DefaultErrorMessage404Detail": "Nie znaleziono zasobu z żądania na serwerze!", + "EntityNotFoundErrorMessage": "Nie istnieje encja {0} z id = {1}!", + "Error": "Błąd", + "AreYouSure": "Czy jesteś pewien?", + "Cancel": "Anuluj", + "Yes": "Tak", + "No": "Nie", + "Close": "Zamknij", + "Save": "Zapisz", + "SavingWithThreeDot": "Zapisywanie...", + "Actions": "Akcje", + "Delete": "Usuń", + "Edit": "Edytuj", + "Refresh": "Odśwież", + "ProcessingWithThreeDot": "Procesowanie...", + "LoadingWithThreeDot": "Ładowanie...", + "Welcome": "Witaj", + "Login": "Zaloguj", + "Register": "Zarejestruj", + "Logout": "Wyloguj", + "Submit": "Wyślij", + "Back": "Cofnij", + "PagerSearch": "Szukaj", + "PagerNext": "Następna", + "PagerPrevious": "Poprzednia", + "PagerFirst": "Pierwsza", + "PagerLast": "Ostatnia", + "PagerInfo": "Pokaż od _START_ do _END_ z _TOTAL_ rekordów", + "PagerInfoEmpty": "Pokaż od 0 do 0 z 0 rekordów", + "PagerInfoFiltered": "(filtruj od _MAX_ wszystkich rekordów)", + "NoDataAvailableInDatatable": "Nie znaleziono danych w tabeli", + "PagerShowMenuEntries": "Pokaż _MENU_ rekordów", + "DatatableActionDropdownDefaultText": "Akcje", + "ChangePassword": "Zmień hasło", + "PersonalInfo": "Mój profil", + "AreYouSureYouWantToCancelEditingWarningMessage": "Masz niezapisane zmiany." + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pl.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pl.json new file mode 100644 index 0000000000..c794c9c123 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pl.json @@ -0,0 +1,7 @@ +{ + "culture": "pl", + "texts": { + "BirthDate": "Data urodzenia", + "Value1": "Wartość jeden" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pl.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pl.json new file mode 100644 index 0000000000..6dd6654aa1 --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "hello": "witaj" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pl.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pl.json new file mode 100644 index 0000000000..5e343cf2f9 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pl.json @@ -0,0 +1,7 @@ +{ + "culture": "pl", + "texts": { + "USA": "Stany Zjednoczone Ameryki", + "Brazil": "Brazylia" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pl.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pl.json new file mode 100644 index 0000000000..1d0bfdf66a --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pl.json @@ -0,0 +1,7 @@ +{ + "culture": "pl", + "texts": { + "ThisFieldIsRequired": "To pole jest wymagane", + "MaxLenghtErrorMessage": "To pole może mieć maksymalnie '{0}' znaków" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pl.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pl.json new file mode 100644 index 0000000000..d014bc7b30 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pl.json @@ -0,0 +1,11 @@ +{ + "culture": "pl", + "texts": { + "Hello {0}.": "Witaj {0}.", + "Car": "Samochód", + "CarPlural": "Samochody", + "MaxLenghtErrorMessage": "To pole może mieć maksymalnie '{0}' znaków", + "Universe": "Wszechświat", + "FortyTwo": "Czterdzieści dwa" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/pl.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/pl.json new file mode 100644 index 0000000000..2935790010 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "SeeYou": "Do zobaczenia" + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pl.json b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pl.json new file mode 100644 index 0000000000..b661af8050 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/pl.json @@ -0,0 +1,21 @@ +{ + "culture": "pl", + "texts": { + "UserName": "Nazwa użytkownika", + "EmailAddress": "Adres email", + "UserNameOrEmailAddress": "Nazwa użytkownia lub adres email", + "Password": "Hasło", + "RememberMe": "Zapamiętaj mnie", + "UseAnotherServiceToLogin": "Użyj innej usługi do zalogowania się", + "UserLockedOutMessage": "Konto użytkownika zostało zablokowane po nieudanych próbach zalogowania. Odczekaj chwilę i spróbuj ponownie.", + "InvalidUserNameOrPassword": "Niepoprawna nazwa użytkownika lub hasło!", + "LoginIsNotAllowed": "Nie jesteś uprawniony do logowania! Musisz potwierdzić swój email/numer telefonu.", + "SelfRegistrationDisabledMessage": "Rejestracja użytkowników jest wyłączona dla tej aplikacji. Skontaktuj się z administratorem aplikacji w celu rejestracji nowego użytkownika.", + "Login": "Zaloguj", + "Cancel": "Anuluj", + "Register": "Zarejestruj", + "InvalidLoginRequest": "Logowanie nieudane", + "ThereAreNoLoginSchemesConfiguredForThisClient": "Nie istnieje skonfigurany schemat logowania dla użytkownika.", + "LogInUsingYourProviderAccount": "Zaloguj używając konta {0}" + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pl.json b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pl.json new file mode 100644 index 0000000000..8806854643 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pl.json @@ -0,0 +1,14 @@ +{ + "culture": "pl", + "texts": { + "Permission:Blogging": "Blog", + "Permission:Blogs": "Blogi", + "Permission:Posts": "Posty", + "Permission:Tags": "Tagi", + "Permission:Comments": "Komentarze", + "Permission:Management": "Zarządzanie", + "Permission:Edit": "Edytuj", + "Permission:Create": "Utwórz", + "Permission:Delete": "Usuń" + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pl.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pl.json new file mode 100644 index 0000000000..15e0c7eb0d --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pl.json @@ -0,0 +1,47 @@ +{ + "culture": "pl", + "texts": { + "Menu:Blogs": "Blogi", + "Menu:BlogManagement": "Zarządzanie blogiem", + "Title": "Tytuł", + "Delete": "Usuń", + "Reply": "Odpowiedz", + "ReplyTo": "Odpowiedz {0}", + "ContinueReading": "Kontynuuj czytanie", + "DaysAgo": "{0} dni temu", + "YearsAgo": "{0} lat temu", + "MonthsAgo": "{0} miesięcy temu", + "WeeksAgo": "{0} tygodni temu", + "MinutesAgo": "{0} minut temu", + "SecondsAgo": "{0} sekund temu", + "HoursAgo": "{0} godzin temu", + "Now": "teraz", + "Content": "Treść", + "SeeAll": "Zobacz wszystko", + "PopularTags": "Popularne tagi", + "WiewsWithCount": "{0} wyświetleń", + "LastPosts": "Ostatnie wpisy", + "LeaveComment": "Zostaw komentarz", + "TagsInThisArticle": "Tagi w tym artykule", + "Posts": "Wpisy", + "Edit": "Edytuj", + "BLOG": "BLOG", + "CommentDeletionWarningMessage": "Komentarz zostanie usunięty.", + "PostDeletionWarningMessage": "Wpis zostanie usunięty.", + "BlogDeletionWarningMessage": "Blog zostanie usunięty.", + "AreYouSure": "Czy jesteś pewien?", + "CommentWithCount": "{0} komentarzy", + "Comment": "Komentarz", + "ShareOnTwitter": "Udostępnij na Twitter", + "CoverImage": "Obraz okładki", + "CreateANewPost": "Utwórz nowy wpis", + "CreateANewBlog": "Utwórz nowy blog", + "WhatIsNew": "Co nowego?", + "Name": "Nazwa", + "ShortName": "Krótka nazwa", + "CreationTime": "Data utworzenia", + "Description": "Opis", + "Blogs": "Blogi", + "Tags": "Tagi" + } +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pl.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pl.json new file mode 100644 index 0000000000..f131f9e139 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/pl.json @@ -0,0 +1,9 @@ +{ + "culture": "pl", + "texts": { + "WelcomeVoloDocs": "Witaj w VoloDocs!", + "NoProjectWarning": "Nie ma jeszcze zdefiniowanego projektu!", + "CreateYourFirstProject": "Kliknij, aby rozpocząć swój pierwszy projekt", + "NoProject": "Brak projektu!" + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl.json new file mode 100644 index 0000000000..e03a79585d --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl.json @@ -0,0 +1,10 @@ +{ + "culture": "pl", + "texts": { + "Permission:DocumentManagement": "Zarządzanie dokumentacją", + "Permission:Projects": "Projekty", + "Permission:Edit": "Edytuj", + "Permission:Delete": "Usuń", + "Permission:Create": "Utwórz" + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pl.json b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pl.json new file mode 100644 index 0000000000..414d4a684f --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/pl.json @@ -0,0 +1,27 @@ +{ + "culture": "pl", + "texts": { + "Menu:DocumentManagement": "Dokumenty", + "Menu:ProjectManagement": "Projekty", + "CreateANewProject": "Utwórz nowy projet", + "Edit": "Edytuj", + "Create": "Utwórz", + "Projects": "Projekty", + "Name": "Nazwa", + "ShortName": "Krótka nazwa", + "DocumentStoreType": "Typ zapisu dokumentu", + "Format": "Format", + "ShortNameInfoText": "Zostanie użyty do unikalnego URL.", + "DisplayName:Name": "Nazwa", + "DisplayName:ShortName": "Krótka nazwa", + "DisplayName:Format": "Format", + "DisplayName:DefaultDocumentName": "Domyślna nazwa dokumentu", + "DisplayName:NavigationDocumentName": "Nawigacyjna nazwa dokumentu", + "DisplayName:MinimumVersion": "Minimalna wersja", + "DisplayName:MainWebsiteUrl": "Adres strony głównej", + "DisplayName:LatestVersionBranchName": "Nazwa brancha ostatniej wersji", + "DisplayName:GitHubRootUrl": "Adres URL do GitHub'a", + "DisplayName:GitHubAccessToken": "GitHub access token", + "DisplayName:GitHubUserAgent": "GitHub user agent" + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl.json new file mode 100644 index 0000000000..5ba3dd6c10 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl.json @@ -0,0 +1,18 @@ +{ + "culture": "pl", + "texts": { + "Documents": "Dokumenty", + "BackToWebsite": "Powrót do strony", + "Contributors": "Współtwórcy", + "ShareOn": "Udostępnij", + "Version": "Wersja", + "Edit": "Edytuj", + "Delete": "Usuń", + "InThisDocument": "W tym dokumencie", + "GoToTop": "Idź do góry", + "Projects": "Projekt(y)", + "NoProjectWarning": "Projekt nie istnieje!", + "DocumentNotFound": "Oops, żądany dokument nie istnieje!", + "NavigationDocumentNotFound": "Ta wersja nie posiada tego dokumentu!" + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pl.json new file mode 100644 index 0000000000..d714a0d499 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "Features": "Funkcje" + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pl.json b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pl.json new file mode 100644 index 0000000000..4ebaa0c660 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pl.json @@ -0,0 +1,14 @@ +{ + "culture": "pl", + "texts": { + "Volo.Abp.Identity:010001": "Nie możesz usunąć swojego własnego konta!", + "Permission:IdentityManagement": "Zarządzanie tożsamością", + "Permission:RoleManagement": "Zarządanie rolami", + "Permission:Create": "Utwórz", + "Permission:Edit": "Edytuj", + "Permission:Delete": "Usuń", + "Permission:ChangePermissions": "Zmień uprawnienia", + "Permission:UserManagement": "Zarządzanie użytkownikami", + "Permission:UserLookup": "Wyszukiwanie użytkownika" + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/pl.json b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/pl.json new file mode 100644 index 0000000000..7a1011ef96 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/pl.json @@ -0,0 +1,33 @@ +{ + "culture": "pl", + "texts": { + "Identity.DefaultError": "Wystąpił niespodziewany błąd.", + "Identity.ConcurrencyFailure": "Optymistyczny błąd współbierzności, obiekt został zmodyfikowany.", + "Identity.DuplicateEmail": "Email '{0}' już istnieje.", + "Identity.DuplicateRoleName": "Rola '{0}' już istnieje.", + "Identity.DuplicateUserName": "Nazwa użytkownika '{0}' już istnieje.", + "Identity.InvalidEmail": "Email '{0}' jest niepoprawny.", + "Identity.InvalidPasswordHasherCompatibilityMode": "Dostawca PasswordHasherCompatibilityMode jest niepoprawny.", + "Identity.InvalidPasswordHasherIterationCount": "Wartość iteracji musi być większa od zera.", + "Identity.InvalidRoleName": "Rola '{0}' jest niepoprawna.", + "Identity.InvalidToken": "Niepoprawny token.", + "Identity.InvalidUserName": "Nazwa użytkownika '{0}' jest niepoprawna, może zawierać tylko litery i cyfry.", + "Identity.LoginAlreadyAssociated": "Użytkownik o tym loginie już istnieje.", + "Identity.PasswordMismatch": "Niepoprawne hasło.", + "Identity.PasswordRequiresDigit": "Hasło musi zawierać przynajmniej jedną cyfrę ('0'-'9').", + "Identity.PasswordRequiresLower": "Hasło musi zawierać przynajmniej jedną małą literę ('a'-'z').", + "Identity.PasswordRequiresNonAlphanumeric": "Hasło musi zawierać przynajmniej jeden znak alfanumeryczny.", + "Identity.PasswordRequiresUpper": "Hasło musi zawierać przynajmniej jedną wielką literę ('A'-'Z').", + "Identity.PasswordTooShort": "Hasło musi zawierać przynajmnie {0} znaków.", + "Identity.RoleNotFound": "Rola {0} nie istnieje.", + "Identity.UserAlreadyHasPassword": "Użytkownik ma już ustawione hasło.", + "Identity.UserAlreadyInRole": "Użytkownik jest już przypisany do roli '{0}'.", + "Identity.UserLockedOut": "Użytkownik jest zablokowany.", + "Identity.UserLockoutNotEnabled": "Blokada nie jest włączona dla tego użytkownika.", + "Identity.UserNameNotFound": "Użytkownik {0} nie istnieje.", + "Identity.UserNotInRole": "Użytkownik nie posiada roli '{0}'.", + "Identity.PasswordConfirmationFailed": "Podane hasła różnią się od siebie.", + "Identity.StaticRoleRenamingErrorMessage": "Statyczna rola nie może mieć zmienionej nazwy.", + "Identity.StaticRoleDeletionErrorMessage": "Statyczna rola nie może zostać usunięta." + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/pl.json b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/pl.json new file mode 100644 index 0000000000..922e20b042 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/pl.json @@ -0,0 +1,39 @@ +{ + "culture": "pl", + "texts": { + "Menu:IdentityManagement": "Zarządzanie tożsamością", + "Users": "Użytkownicy", + "NewUser": "Nowy użytkownik", + "UserName": "Nazwa użytkownika", + "EmailAddress": "Adres email", + "PhoneNumber": "Numer telefonu", + "UserInformations": "Notyfikacje użytkownika", + "DisplayName:IsDefault": "Domyślny", + "DisplayName:IsStatic": "Statyczny", + "DisplayName:IsPublic": "Publiczny", + "Roles": "Role", + "Password": "Hasło", + "PersonalInfo": "Mój profil", + "PersonalSettings": "Ustawienia personalne", + "UserDeletionConfirmationMessage": "Użytkownik '{0}' zostanie usunięty. Czy na pewno?", + "RoleDeletionConfirmationMessage": "Rola '{0}' zostanie usunięta. Czy na pewno?", + "DisplayName:RoleName": "Nazwa roli", + "DisplayName:UserName": "Nazwa użytkownika", + "DisplayName:Name": "Imię", + "DisplayName:Surname": "Nazwisko", + "DisplayName:Password": "Hasło", + "DisplayName:Email": "Adres email", + "DisplayName:PhoneNumber": "Numer telefonu", + "DisplayName:TwoFactorEnabled": "Dwustopniowa weryfikacja", + "DisplayName:LockoutEnabled": "Blokowanie konta po nieudanych próbach zalogowania", + "NewRole": "Nowa rola", + "RoleName": "Nazwa roli", + "CreationTime": "Data utworzenia", + "Permissions": "Uprawnienia", + "DisplayName:CurrentPassword": "Aktualne hasło", + "DisplayName:NewPassword": "Nowe hasło", + "DisplayName:NewPasswordConfirm": "Powtierdź nowe hasło", + "PasswordChangedMessage": "Twoje hasło zostało zmienione pomyślnie.", + "PersonalSettingsSavedMessage": "Twoje personalne ustawienia zostały zapisane pomyślnie." + } +} \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pl.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pl.json new file mode 100644 index 0000000000..e1043feea7 --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pl.json @@ -0,0 +1,10 @@ +{ + "culture": "pl", + "texts": { + "Permissions": "Uprawnienia", + "OnlyProviderPermissons": "Tylko ten dostawca", + "All": "Wszystkie", + "SelectAllInAllTabs": "Udziel wszystkich uprawnień", + "SelectAllInThisTab": "Zaznacz wszystkie" + } +} \ No newline at end of file diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pl.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pl.json new file mode 100644 index 0000000000..4aa474d82b --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "Settings": "Ustawienia" + } +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pl.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pl.json new file mode 100644 index 0000000000..500b784dfd --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pl.json @@ -0,0 +1,11 @@ +{ + "culture": "pl", + "texts": { + "Permission:TenantManagement": "Zarządzanie tenantami", + "Permission:Create": "Utwórz", + "Permission:Edit": "Edytuj", + "Permission:Delete": "Usuń", + "Permission:ManageConnectionStrings": "Zarządzaj connection string'ami", + "Permission:ManageFeatures": "Zarządzaj fukcjami" + } +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/pl.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/pl.json new file mode 100644 index 0000000000..537d235293 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/pl.json @@ -0,0 +1,14 @@ +{ + "culture": "pl", + "texts": { + "Menu:TenantManagement": "Zarządzanie tenantami", + "Tenants": "Tenanty", + "NewTenant": "Nowy tenant", + "TenantName": "Nazwa tenantu", + "DisplayName:TenantName": "Nazwa tenantu", + "TenantDeletionConfirmationMessage": "Tenant '{0}' zostanie usunięty. Czy na pewno?", + "ConnectionStrings": "Connection Strings", + "DisplayName:DefaultConnectionString": "Domyślny Connection String", + "DisplayName:UseSharedDatabase": "Użyj współdzielonej bazy danych" + } +} \ No newline at end of file diff --git a/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json new file mode 100644 index 0000000000..a018dc2126 --- /dev/null +++ b/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json @@ -0,0 +1,20 @@ +{ + "culture": "pl", + "texts": { + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io.", + "Menu:BookStore": "Sklep z ksiąkami", + "Menu:Books": "Ksiąki", + "Name": "Nazwa", + "Type": "Typ", + "PublishDate": "Data publikacji", + "Price": "Cena", + "CreationTime": "Data utworzenia", + "NewBook": "Nowa ksiąka", + "Books": "Ksiąki", + "Update": "Aktualizuj", + "BookDeletionConfirmationMessage": "Czy jesteś pewien, że chcesz usunąć {0}?", + "SuccessfullyDeleted": "Usunięto pomyślnie." + } +} \ No newline at end of file diff --git a/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/pl.json b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/pl.json new file mode 100644 index 0000000000..f1a26b3f9f --- /dev/null +++ b/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/pl.json @@ -0,0 +1,10 @@ +{ + "culture": "pl", + "texts": { + "Menu:Home": "Home", + "Welcome": "Witaj", + "RolesInApplication": "Role w aplikacji", + "UserCount": "Ilość użytkowników", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} \ No newline at end of file diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/pl.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/pl.json new file mode 100644 index 0000000000..9181e35186 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/pl.json @@ -0,0 +1,10 @@ +{ + "culture": "pl", + "texts": { + "Permission:ProductManagement": "Zarządzanie produktami", + "Permission:Products": "Produkty", + "Permission:Edit": "Edytuj", + "Permission:Delete": "Usuń", + "Permission:Create": "Utwórz" + } +} \ No newline at end of file diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/pl.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl.json b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl.json new file mode 100644 index 0000000000..5828dd8942 --- /dev/null +++ b/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/pl.json @@ -0,0 +1,16 @@ +{ + "culture": "pl", + "texts": { + "Menu:ProductManagement": "Zarządzanie produktami", + "Menu:Products": "Produkty", + "ProductManagement": "Zarządzanie produktami", + "CreateANewProduct": "Utwórz nowy produkt", + "Products": "Produkty", + "StockCount": "Ilość na magazynie", + "Code": "Kod", + "Name": "Nazwa", + "Price": "Cena", + "ImageName": "Nazwa obrazka", + "ProductDeletionWarningMessage": "Czy jesteś pewien, że chcesz usunąć ten produkt?" + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pl.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pl.json new file mode 100644 index 0000000000..3b93a2b580 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + "Permission:MyProjectName": "MyProjectName" + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pl.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pl.json b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pl.json new file mode 100644 index 0000000000..2ea227cbf3 --- /dev/null +++ b/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/pl.json @@ -0,0 +1,6 @@ +{ + "culture": "pl", + "texts": { + + } +} \ No newline at end of file diff --git a/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/pl.json b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/pl.json new file mode 100644 index 0000000000..815bbcc83f --- /dev/null +++ b/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/pl.json @@ -0,0 +1,8 @@ +{ + "culture": "pl", + "texts": { + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} \ No newline at end of file From 19d9e3dd0f0530129d031fd583576497a772fd6c Mon Sep 17 00:00:00 2001 From: Xeevis Date: Wed, 12 Jun 2019 00:41:07 +0200 Subject: [PATCH 69/75] Add Czech localization for documentation --- docs/cs/Index.md | 30 +++++ docs/cs/docs-nav.json | 292 ++++++++++++++++++++++++++++++++++++++++++ docs/docs-langs.json | 5 + 3 files changed, 327 insertions(+) create mode 100644 docs/cs/Index.md create mode 100644 docs/cs/docs-nav.json diff --git a/docs/cs/Index.md b/docs/cs/Index.md new file mode 100644 index 0000000000..3a86344660 --- /dev/null +++ b/docs/cs/Index.md @@ -0,0 +1,30 @@ +# ABP dokumentace + +ABP je **open source aplikační framework** se zaměřením na vývoj webových aplikací založených na ASP.NET Core, zároveň ho však lze využít i k vývoji jiných typů aplikací. + +K procházení dokumentace využijte navigační nabídky vlevo. + +## Stav projektu + +ABP je **novou generací** open source frameworku [ASP.NET Boilerplate](https://aspnetboilerplate.com/). V současné době je v ranné fázi a není připraven k ostrému nasazení. Na dokumentaci se stále pracuje a ještě zdaleka není dokončena. + +Pro aplikace na krátkodobé a ostré nasazení je doporučeno použít [ASP.NET Boilerplate](https://aspnetboilerplate.com/) framework, který je bohatý na funkce, vyspělý, aktivně udržovaný a aktuální. + +## Začínáme + +Nejsnazší cestou jak začít nový projekt s ABP je užití startovací šablony: + +* [ASP.NET Core MVC Šablona](Getting-Started-AspNetCore-MVC-Template.md) + +Pokud chcete začít od nuly (s prázdným projektem) tak manuálně nainstalujte ABP Framework s pomocí následujících tutoriálů: + +* [Konzolová Aplikace](Getting-Started-Console-Application.md) +* [ASP.NET Core Web Aplikace](Getting-Started-AspNetCore-Application.md) + +## Zdrojový kód + +ABP je hostovaný na GitHub. Zobrazit [zdrojový kód](https://github.com/abpframework/abp). + +## Chcete přispět? + +ABP je komunitně řízený open source projekt. Podívejte se na [průvodce pro přispěvatele](Contribution/Index.md) pokud chcete být součástí tohoto projektu. diff --git a/docs/cs/docs-nav.json b/docs/cs/docs-nav.json new file mode 100644 index 0000000000..4b976b4812 --- /dev/null +++ b/docs/cs/docs-nav.json @@ -0,0 +1,292 @@ +{ + "items": [ + { + "text": "Začínáme", + "items": [ + { + "text": "Ze startovacích šablon", + "items": [ + { + "text": "ASP.NET Core MVC", + "path": "Getting-Started-AspNetCore-MVC-Template.md" + } + ] + }, + { + "text": "Z prázdných projektů", + "items": [ + { + "text": "S ASP.NET Core Web aplikací", + "path": "Getting-Started-AspNetCore-Application.md" + }, + { + "text": "S konzolovou aplikací", + "path": "Getting-Started-Console-Application.md" + } + ] + } + ] + }, + { + "text": "Tutoriály", + "items": [ + { + "text": "Vývoj aplikace", + "items": [ + { + "text": "S ASP.NET Core MVC", + "path": "Tutorials/AspNetCore-Mvc/Part-I.md" + } + ] + } + ] + }, + { + "text": "CLI", + "path": "CLI.md" + }, + { + "text": "Základy", + "items": [ + { + "text": "Vkládání závislostí", + "path": "Dependency-Injection.md", + "items": [ + { + "text": "AutoFac integrace", + "path": "Autofac-Integration.md" + } + ] + }, + { + "text": "Virtuální systém souborů", + "path": "Virtual-File-System.md" + }, + { + "text": "Lokalizace", + "path": "Localization.md" + }, + { + "text": "Zpracování výjimek", + "path": "Exception-Handling.md" + }, + { + "text": "Validace" + }, + { + "text": "Autorizace" + }, + { + "text": "Ukládání do mezipaměti" + }, + { + "text": "Audit" + }, + { + "text": "Správa nastavení" + } + ] + }, + { + "text": "Události", + "items": [ + { + "text": "Event bus (místní)" + }, + { + "text": "Distribuovaný event bus", + "items": [ + { + "text": "RabbitMQ integrace" + } + ] + } + ] + }, + { + "text": "Služby", + "items": [ + { + "text": "Serializace objektu" + }, + { + "text": "Serializace JSON" + }, + { + "text": "Emailování" + }, + { + "text": "GUIDy" + }, + { + "text": "Vláknování" + }, + { + "text": "Časování" + } + ] + }, + { + "text": "Multitenance", + "path": "Multi-Tenancy.md" + }, + { + "text": "Vývoj modulů", + "items": [ + { + "text": "Základy", + "path": "Module-Development-Basics.md" + }, + { + "text": "Zásuvné moduly" + }, + { + "text": "Nejlepší praktiky", + "path": "Best-Practices/Index.md" + } + ] + }, + { + "text": "Domain driven design", + "path": "Domain-Driven-Design.md", + "items": [ + { + "text": "Doménová vrstva", + "items": [ + { + "text": "Entity & agregované kořeny", + "path": "Entities.md" + }, + { + "text": "Hodnotové objekty" + }, + { + "text": "Repozitáře", + "path": "Repositories.md" + }, + { + "text": "Doménové služby" + }, + { + "text": "Specifikace" + } + ] + }, + { + "text": "Aplikační vrstva", + "items": [ + { + "text": "Aplikační služby", + "path": "Application-Services.md" + }, + { + "text": "Objekty přenosu dat" + }, + { + "text": "Jednotka práce" + } + ] + } + ] + }, + { + "text": "ASP.NET Core", + "items": [ + { + "text": "API", + "items": [ + { + "text": "Automatické API řadiče", + "path": "AspNetCore/Auto-API-Controllers.md" + }, + { + "text": "Dynamičtí C# API klienti", + "path": "AspNetCore/Dynamic-CSharp-API-Clients.md" + } + ] + }, + { + "text": "Uživatelské rozhraní", + "items": [ + { + "text": "Správa klientských balíčků", + "path": "AspNetCore/Client-Side-Package-Management.md" + }, + { + "text": "Svazování & minifikace", + "path": "AspNetCore/Bundling-Minification.md" + }, + { + "text": "Tag pomocníci", + "path": "Tag-Helpers.md" + }, + { + "text": "Motivy", + "path": "AspNetCore/Theming.md" + } + ] + } + ] + }, + { + "text": "Přístup k datům", + "items": [ + { + "text": "Entity Framework Core integrace", + "path": "Entity-Framework-Core.md" + }, + { + "text": "MongoDB integrace", + "path": "MongoDB.md" + } + ] + }, + { + "text": "Pozadí", + "items": [ + { + "text": "Úkony na pozadí", + "path": "Background-Jobs.md", + "items": [ + { + "text": "Hangfire integrace", + "path": "Background-Jobs-Hangfire.md" + }, + { + "text": "RabbitMQ integrace", + "path": "Background-Jobs-RabbitMq.md" + } + ] + } + ] + }, + { + "text": "Vzorky", + "items": [ + { + "text": "Mikroslužby demo", + "path": "Samples/Microservice-Demo.md" + } + ] + }, + { + "text": "Moduly aplikace", + "path": "Modules/Index.md" + }, + { + "text": "Architektura mikroslužby", + "path": "Microservice-Architecture.md" + }, + { + "text": "Testování" + }, + { + "text": "Noční sestavení", + "path": "Nightly-Builds.md" + }, + { + "text": "Průvodce pro přispěvatele", + "path": "Contribution/Index.md" + } + ] +} \ No newline at end of file diff --git a/docs/docs-langs.json b/docs/docs-langs.json index 851c67d605..012c7e6ef0 100644 --- a/docs/docs-langs.json +++ b/docs/docs-langs.json @@ -1,5 +1,10 @@ { "Languages":[ + { + "DisplayName" : "Čeština", + "Code" : "cs", + "IsDefault": false + }, { "DisplayName" : "English", "Code" : "en", From bc07b824deda64fb429f0de559557db88a5bc717 Mon Sep 17 00:00:00 2001 From: Xeevis Date: Wed, 12 Jun 2019 00:58:45 +0200 Subject: [PATCH 70/75] Localize warning about missing document --- .../Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json | 3 ++- .../Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json | 3 ++- .../src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json index ec882e6538..4c21318fdb 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json @@ -13,6 +13,7 @@ "Projects": "Projekt(y)", "NoProjectWarning": "Zatím zde není žádný projekt!", "DocumentNotFound": "Ups, vyžádaný dokument neexistuje!", - "NavigationDocumentNotFound": "Tato verze nemá navigační dokument!" + "NavigationDocumentNotFound": "Tato verze nemá navigační dokument!", + "DocumentNotFoundInSelectedLanguage": "Tento dokument není dostupný ve vybraném jazyce. Zobrazen dokument ve výchozím jazyce." } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json index 31d3835a3a..f399b8f151 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json @@ -13,6 +13,7 @@ "Projects": "Project(s)", "NoProjectWarning": "There are no projects yet!", "DocumentNotFound": "Oops, the requested document was not found!", - "NavigationDocumentNotFound": "This version does not have a navigation document!" + "NavigationDocumentNotFound": "This version does not have a navigation document!", + "DocumentNotFoundInSelectedLanguage": "Document in the language you wanted is not found. Document in the default language is shown." } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index a7fc072011..6fd1a21797 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -192,8 +192,8 @@
@if (Model.DocumentLanguageIsDifferent) { - - Document in the language you wanted is not found. Document in the default language is shown. + + @L["DocumentNotFoundInSelectedLanguage"] } @Html.Raw(Model.Document.Content) From 18eb2a57d53af2da4043bb869d291631c1a6ef6a Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 12 Jun 2019 09:44:51 +0800 Subject: [PATCH 71/75] Supplement other localized translations. --- .../Volo/Docs/Localization/Domain/es.json | 12 ++++++++---- .../Volo/Docs/Localization/Domain/pt-BR.json | 3 ++- .../Volo/Docs/Localization/Domain/tr.json | 3 ++- .../Volo/Docs/Localization/Domain/vi.json | 5 +++-- .../Volo/Docs/Localization/Domain/zh-Hans.json | 5 +++-- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json index 94a3eec1bd..700143ad76 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json @@ -3,13 +3,17 @@ "texts": { "Documents": "Documentos", "BackToWebsite": "Regresar al sitio", - "Version": "Versin", + "Contributors": "Contribuidores", + "ShareOn": "Compartilhar no", + "Version": "Versão", "Edit": "Editar", + "Delete": "Excluir", "InThisDocument": "En este documento", "GoToTop": "Subir", "Projects": "Proyecto(s)", - "NoProjectWarning": "Aun no hay proyectos!", - "DocumentNotFound": "Oops, no se encontr el documento solicitado!", - "NavigationDocumentNotFound": "Esta versin no tiene un documento de navegacin!" + "NoProjectWarning": "Não há projetos ainda!", + "DocumentNotFound": "Ups! O documento solicitado não foi encontrado!", + "NavigationDocumentNotFound": "Esta versão não possui um documento de navegação!", + "DocumentNotFoundInSelectedLanguage": "Documento no idioma desejado não foi encontrado. Documento no idioma padrão é mostrado." } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json index 38fa49de3d..0d1157d4c3 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json @@ -13,6 +13,7 @@ "Projects": "Projeto(s)", "NoProjectWarning": "Ainda não há projetos!", "DocumentNotFound": "Oops, o documento solicitado não foi encontrado", - "NavigationDocumentNotFound": "Esta versão não possui um documento de navegação!" + "NavigationDocumentNotFound": "Esta versão não possui um documento de navegação!", + "DocumentNotFoundInSelectedLanguage": "Documento no idioma desejado não foi encontrado. Documento no idioma padrão é mostrado." } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json index da39c6cce3..3f15a43046 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json @@ -13,6 +13,7 @@ "Projects": "Proje(ler)", "NoProjectWarning": "Hiç proje yok!", "DocumentNotFound": "Aradığınız döküman bulunamadı!", - "NavigationDocumentNotFound": "Bu döküman için menü bulunamadı!" + "NavigationDocumentNotFound": "Bu döküman için menü bulunamadı!", + "DocumentNotFoundInSelectedLanguage": "İstediğiniz dilde belge bulunamadı. Varsayılan dilde belge gösterilir." } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json index 7c845de612..6f10e6469c 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json @@ -13,6 +13,7 @@ "Projects": "Dự án", "NoProjectWarning": "Chưa có dự án nào!", "DocumentNotFound": "Rất tiếc, tài liệu được yêu cầu không tìm thấy!", - "NavigationDocumentNotFound": "Phiên bản này không có tài liệu điều hướng!" + "NavigationDocumentNotFound": "Phiên bản này không có tài liệu điều hướng!", + "DocumentNotFoundInSelectedLanguage": "Tài liệu bằng ngôn ngữ bạn muốn không được tìm thấy. Tài liệu trong ngôn ngữ mặc định được hiển thị." } -} +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json index f085265abf..43eb83334c 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json @@ -13,6 +13,7 @@ "Projects": "项目", "NoProjectWarning": "还没有项目!", "DocumentNotFound": "找不到请求的文档!", - "NavigationDocumentNotFound": "这个版本没有导航文件!" + "NavigationDocumentNotFound": "这个版本没有导航文件!", + "DocumentNotFoundInSelectedLanguage": "本文档不适用于所选语言, 将以默认语言显示文档." } -} +} \ No newline at end of file From b2550a091b3b9ccc06210f7450bbb97e2f7a95ab Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 12 Jun 2019 10:15:39 +0800 Subject: [PATCH 72/75] Created empty docs. --- docs/zh-Hans/AspNetCore/Auto-API-Controllers.md | 2 +- docs/zh-Hans/Dynamic-JavaScript-API-Clients.md | 3 +++ docs/zh-Hans/Value-Objects.md | 3 +++ docs/zh-Hans/Value-Types.md | 3 --- 4 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 docs/zh-Hans/Dynamic-JavaScript-API-Clients.md create mode 100644 docs/zh-Hans/Value-Objects.md delete mode 100644 docs/zh-Hans/Value-Types.md diff --git a/docs/zh-Hans/AspNetCore/Auto-API-Controllers.md b/docs/zh-Hans/AspNetCore/Auto-API-Controllers.md index f31b4d67cb..93ac124913 100644 --- a/docs/zh-Hans/AspNetCore/Auto-API-Controllers.md +++ b/docs/zh-Hans/AspNetCore/Auto-API-Controllers.md @@ -2,7 +2,7 @@ 创建[应用程序服务](Application-Services.md)后, 通常需要创建API控制器以将此服务公开为HTTP(REST)API端点. 典型的API控制器除了将方法调用重定向到应用程序服务并使用[HttpGet],[HttpPost],[Route]等属性配置REST API之外什么都不做. -ABP可以按照惯例 **自动** 将你的应用程序服务配置为MVC API控制器. 大多数时候你不关心它的详细配置,但它可以完全被自定义. +ABP可以按照惯例 **自动** 将你的应用程序服务配置为API控制器. 大多数时候你不关心它的详细配置,但它可以完全被自定义. ## 配置 diff --git a/docs/zh-Hans/Dynamic-JavaScript-API-Clients.md b/docs/zh-Hans/Dynamic-JavaScript-API-Clients.md new file mode 100644 index 0000000000..b7ca9a6965 --- /dev/null +++ b/docs/zh-Hans/Dynamic-JavaScript-API-Clients.md @@ -0,0 +1,3 @@ +## Dynamic JavaScript API Clients + + TODO \ No newline at end of file diff --git a/docs/zh-Hans/Value-Objects.md b/docs/zh-Hans/Value-Objects.md new file mode 100644 index 0000000000..6735074fd4 --- /dev/null +++ b/docs/zh-Hans/Value-Objects.md @@ -0,0 +1,3 @@ +## Value Objects + + TODO \ No newline at end of file diff --git a/docs/zh-Hans/Value-Types.md b/docs/zh-Hans/Value-Types.md deleted file mode 100644 index a0e340063c..0000000000 --- a/docs/zh-Hans/Value-Types.md +++ /dev/null @@ -1,3 +0,0 @@ -## Value Types - -TODO \ No newline at end of file From e9af3639213768f2ff38ceff37994a5a1cf034f5 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Wed, 12 Jun 2019 11:14:04 +0300 Subject: [PATCH 73/75] add freeze-ui package --- .../FreezeUi/FreezeUiScriptContributor.cs | 16 +++++++ .../FreezeUi/FreezeUiStyleContributor.cs | 16 +++++++ .../SharedThemeGlobalScriptContributor.cs | 7 ++- .../SharedThemeGlobalStyleContributor.cs | 4 +- .../freeze-ui/abp-freeze-ui.js | 46 +++++++++++++++++++ npm/packs/freeze-ui/abp.resourcemapping.js | 6 +++ npm/packs/freeze-ui/lib/freeze-ui.min.css | 1 + npm/packs/freeze-ui/lib/freeze-ui.min.js | 1 + npm/packs/freeze-ui/package.json | 11 +++++ 9 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiScriptContributor.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiStyleContributor.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/freeze-ui/abp-freeze-ui.js create mode 100644 npm/packs/freeze-ui/abp.resourcemapping.js create mode 100644 npm/packs/freeze-ui/lib/freeze-ui.min.css create mode 100644 npm/packs/freeze-ui/lib/freeze-ui.min.js create mode 100644 npm/packs/freeze-ui/package.json diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiScriptContributor.cs new file mode 100644 index 0000000000..ffdd786250 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiScriptContributor.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.Core; +using Volo.Abp.Modularity; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.FreezeUi +{ + [DependsOn(typeof(CoreScriptContributor))] + public class FreezeUiScriptContributor : BundleContributor + { + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.AddIfNotContains("/libs/freeze-ui/freeze-ui.min.css"); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiStyleContributor.cs new file mode 100644 index 0000000000..96f4996663 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/FreezeUi/FreezeUiStyleContributor.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap; +using Volo.Abp.Modularity; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.FreezeUi +{ + [DependsOn(typeof(BootstrapStyleContributor))] + public class FreezeUiStyleContributor : BundleContributor + { + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.AddIfNotContains("/libs/freeze-ui/freeze-ui.min.css"); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs index 10354b37d0..8271c0e05a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs @@ -3,6 +3,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.Anchor; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Clipboard; using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs4; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.FreezeUi; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryForm; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidationUnobtrusive; @@ -27,7 +28,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling typeof(DatatablesNetBs4ScriptContributor), typeof(SweetalertScriptContributor), typeof(ToastrScriptBundleContributor), - typeof(TimeagoScriptContributor))] + typeof(TimeagoScriptContributor), + typeof(FreezeUiScriptContributor))] public class SharedThemeGlobalScriptContributor : BundleContributor { public override void ConfigureBundle(BundleConfigurationContext context) @@ -40,7 +42,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling "/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert/abp-sweetalert.js", - "/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js" + "/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js", + "/libs/abp/aspnetcore-mvc-ui-theme-shared/freeze-ui/abp-freeze-ui.js" }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs index 3402b92e99..7fb8181373 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs @@ -2,6 +2,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs4; using Volo.Abp.AspNetCore.Mvc.UI.Packages.FontAwesome; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.FreezeUi; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; using Volo.Abp.Modularity; @@ -13,7 +14,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling typeof(FontAwesomeStyleContributor), typeof(ToastrStyleBundleContributor), typeof(Select2StyleContributor), - typeof(DatatablesNetBs4StyleContributor) + typeof(DatatablesNetBs4StyleContributor), + typeof(FreezeUiStyleContributor) )] public class SharedThemeGlobalStyleContributor : BundleContributor { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/freeze-ui/abp-freeze-ui.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/freeze-ui/abp-freeze-ui.js new file mode 100644 index 0000000000..309765a482 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/freeze-ui/abp-freeze-ui.js @@ -0,0 +1,46 @@ +var abp = abp || {}; +(function ($) { + if (!window.FreezeUI || !$) { + return; + } + + /* MESSAGE **************************************************/ + /*Package from https://alexradulescu.github.io/freeze-ui/*/ + + abp.ui = abp.ui || {}; + + /* UI BLOCK */ + + abp.ui.block = function (elm) { + if (elm) { + window.FreezeUI({ selector: elm }); + } else { + window.FreezeUI(); + } + }; + + abp.ui.unblock = function () { + window.UnFreezeUI(); + }; + + /* UI BUSY */ + + abp.ui.setBusy = function (element, text, freezeDelay) { + var opt = { text : text ? text : ' ' }; + + if (element) { + opt.element = element; + } + + if (freezeDelay) { + opt.freezeDelay = freezeDelay; + } + + window.FreezeUI(opt); + }; + + abp.ui.clearBusy = function () { + window.UnFreezeUI(); + }; + +})(jQuery); \ No newline at end of file diff --git a/npm/packs/freeze-ui/abp.resourcemapping.js b/npm/packs/freeze-ui/abp.resourcemapping.js new file mode 100644 index 0000000000..b027f07c88 --- /dev/null +++ b/npm/packs/freeze-ui/abp.resourcemapping.js @@ -0,0 +1,6 @@ +module.exports = { + mappings: { + "@node_modules/@abp/freeze-ui/lib/freeze-ui.min.js": "@libs/freeze-ui/", + "@node_modules/@abp/freeze-ui/lib/freeze-ui.min.css": "@libs/freeze-ui/" + } +} \ No newline at end of file diff --git a/npm/packs/freeze-ui/lib/freeze-ui.min.css b/npm/packs/freeze-ui/lib/freeze-ui.min.css new file mode 100644 index 0000000000..0f85b42513 --- /dev/null +++ b/npm/packs/freeze-ui/lib/freeze-ui.min.css @@ -0,0 +1 @@ +@keyframes spin{0%{transform:translateZ(0) rotate(0)}100%{transform:translateZ(0) rotate(360deg)}}.freeze-ui{position:fixed;top:0;left:0;width:100%;height:100%;z-index:999999999;background-color:#fff;opacity:.8;transition:opacity .25s}.freeze-ui.is-unfreezing{opacity:0}.freeze-ui:after{content:attr(data-text);display:block;max-width:125px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:20px;font-family:sans-serif;color:#343a40;text-align:center;text-transform:uppercase}.freeze-ui:before{content:"";display:block;width:150px;height:150px;border-radius:50%;border-width:2px;border-style:solid;border-color:transparent #228ae6 #228ae6;position:absolute;top:calc(50% - 75px);left:calc(50% - 75px);will-change:transform;animation:spin .75s infinite ease-in-out} \ No newline at end of file diff --git a/npm/packs/freeze-ui/lib/freeze-ui.min.js b/npm/packs/freeze-ui/lib/freeze-ui.min.js new file mode 100644 index 0000000000..991416917c --- /dev/null +++ b/npm/packs/freeze-ui/lib/freeze-ui.min.js @@ -0,0 +1 @@ +(()=>{let a=document.createElement('div');a.classList.add('freeze-ui'),window.FreezeUI=(b={})=>{let c=document.querySelector(b.selector)||document.body;a.setAttribute('data-text',b.text||'Loading'),document.querySelector(b.selector)&&(a.style.position='absolute'),c.appendChild(a)},window.UnFreezeUI=()=>{let b=document.querySelector('.freeze-ui');b&&(b.classList.add('is-unfreezing'),setTimeout(()=>{b&&(b.classList.remove('is-unfreezing'),b.parentElement.removeChild(b))},250))}})(); \ No newline at end of file diff --git a/npm/packs/freeze-ui/package.json b/npm/packs/freeze-ui/package.json new file mode 100644 index 0000000000..0a150676c1 --- /dev/null +++ b/npm/packs/freeze-ui/package.json @@ -0,0 +1,11 @@ +{ + "version": "0.5.3", + "name": "@abp/freeze-ui", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@abp/core": "^0.5.3" + }, + "gitHead": "824de4c615c1d4d1d7f07d6ec1e8d0cb3a303c72" +} From 6e9cec0ab4875c677e4447f67f0ee06263c591d0 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Wed, 12 Jun 2019 11:14:59 +0300 Subject: [PATCH 74/75] add freeze-ui to theme.shared --- npm/packs/aspnetcore.mvc.ui.theme.shared/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json index e8fdce70e0..cc803f2154 100644 --- a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json +++ b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json @@ -15,7 +15,8 @@ "@abp/select2": "^0.4.9", "@abp/sweetalert": "^0.4.9", "@abp/timeago": "^0.4.9", - "@abp/toastr": "^0.4.9" + "@abp/toastr": "^0.4.9", + "@abp/freeze-ui": "^0.4.9" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" } From a7e6f82c904ae6b2279d1553bffee885b0f85fa6 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Wed, 12 Jun 2019 11:16:13 +0300 Subject: [PATCH 75/75] Update package.json --- npm/packs/aspnetcore.mvc.ui.theme.shared/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json index cc803f2154..08f41e55e2 100644 --- a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json +++ b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json @@ -16,7 +16,7 @@ "@abp/sweetalert": "^0.4.9", "@abp/timeago": "^0.4.9", "@abp/toastr": "^0.4.9", - "@abp/freeze-ui": "^0.4.9" + "@abp/freeze-ui": "^0.5.3" }, "gitHead": "2e846ad3e5a8cbe04100484865335fbcd845a342" }