diff --git a/.gitignore b/.gitignore index 6e767c8f76..5b8dfe9c11 100644 --- a/.gitignore +++ b/.gitignore @@ -305,3 +305,6 @@ modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Logs/ /modules/client-simulation/demo/Volo.ClientSimulation.Demo/package-lock.json abp-build-config.json /templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/Test/ + +# Identity Server temp signature file +tempkey.jwk \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/zh-Hans.json index adc808ed7e..0d66f1288d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/zh-Hans.json @@ -8,6 +8,7 @@ "FrameworkDocumentation": "框架文档", "OfficialBlog": "官方博客", "CommercialHomePage": "商业版首页", - "CommercialSupportWebSite": "商业版支持网站" + "CommercialSupportWebSite": "商业版支持网站", + "CommunityWebSite": "ABP社区网站" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json index bc78a54119..f5cbeb0213 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json @@ -3,6 +3,12 @@ "texts": { "Permission:Organizations": "组织", "Permission:Manage": "管理组织", + "Permission:DiscountRequests": "折扣请求", + "Permission:DiscountManage": "管理折扣请求", + "Permission:Disable": "禁用", + "Permission:Enable": "启动", + "Permission:EnableSendEmail": "启用发送邮件", + "Permission:SendEmail": "发送邮件", "Permission:NpmPackages": "NPM包", "Permission:NugetPackages": "Nuget包", "Permission:Maintenance": "维护", @@ -13,8 +19,13 @@ "Permission:Edit": "编辑", "Permission:Delete": "删除", "Permission:Create": "创建", + "Permission:Accounting": "账单", + "Permission:Accounting:Quotation": "报价", + "Permission:Accounting:Invoice": "发票", "Menu:Organizations": "组织", + "Menu:Accounting": "账单", "Menu:Packages": "包", + "Menu:DiscountRequests": "折扣请求", "NpmPackageDeletionWarningMessage": "该NPM包将会被删除. 你确定吗?", "NugetPackageDeletionWarningMessage": "该Nuget包将会被删除. 你确定吗?", "ModuleDeletionWarningMessage": "该模块将会被删除. 你确定吗?", @@ -24,6 +35,7 @@ "NameFilter": "名称", "CreationTime": "创建时间", "IsPro": "是否为专业版", + "ShowOnModuleList": "展示模块列表", "EfCoreConfigureMethodName": "配置方法法", "IsProFilter": "是否为专业版", "ApplicationType": "应用程序类型", @@ -53,6 +65,7 @@ "CreateANugetPackage": "创建Nuget包", "AddNew": "新建", "PackageAlreadyExist{0}": "\"{0}\"已经被添加.", + "ModuleAlreadyExist{0}": "\"{0}\" 模块已经添加.", "ClearCache": "清除缓存", "SuccessfullyCleared": "清除成功", "Menu:NpmPackages": "NPM包", @@ -63,6 +76,7 @@ "Organizations": "组织", "LongName": "完整名称", "LicenseType": "授权类型", + "MissingLicenseTypeField": "许可证类型字段是必需的!", "LicenseStartTime": "授权开始时间", "LicenseEndTime": "授权结束时间", "AllowedDeveloperCount": "允许的开发人员数量", @@ -74,14 +88,112 @@ "AddDeveloper": "添加开发者", "Create": "创建", "UserNotFound": "用户不存在", - "{0}WillBeRemovedFromMembers": "{0} 将从成员中删除", + "{0}WillBeRemovedFromDevelopers": "{0} 将从开发者中移除, 你确定吗?", + "{0}WillBeRemovedFromOwners": "{0} 将从所有者中移除, 你确定吗?", "Computers": "计算机", "UniqueComputerId": "计算机唯一ID", "LastSeenDate": "上次查看日期", "{0}Computer{1}WillBeRemovedFromRecords": "计算机 {0} ({1}) 将从记录中删除", "OrganizationDeletionWarningMessage": "组织将被删除", + "DeletingLastOwnerWarningMessage": "一个组织必须至少有一个所有者!因此你不能删除此所有者", "This{0}AlreadyExistInThisOrganization": "该组织中已经存在此 {0}", "AreYouSureYouWantToDeleteAllComputers": "您确定要删除所有计算机吗?", - "DeleteAll": "删除所有" + "DeleteAll": "删除所有", + "DoYouWantToCreateNewUser": "你想要创建一个新用户吗", + "MasterModules": "主模块", + "OrganizationName": "组织名称", + "CreationDate": "创建时间", + "LicenseStartDate": "许可开始时间", + "LicenseEndDate": "许可结束时间", + "OrganizationNamePlaceholder": "组织名称...", + "TotalQuestionCountPlaceholder": "问题总数...", + "RemainingQuestionCountPlaceholder": "剩下的问题数...", + "LicenseTypePlaceholder": "许可类型...", + "CreationDatePlaceholder": "创建时间...", + "LicenseStartDatePlaceholder": "许可开始时间...", + "LicenseEndDatePlaceholder": "许可结束时间...", + "UsernameOrEmail": "用户名或邮箱", + "UsernameOrEmailPlaceholder": "用户名或邮箱...", + "Member": "成员", + "PurchaseOrderNo": "订单编号", + "QuotationDate": "报价日期", + "CompanyName": "公司名称", + "CompanyAddress": "公司地址", + "Price": "价格", + "DiscountText": "折扣文字", + "DiscountQuantity": "折扣数量", + "DiscountPrice": "折扣价格", + "Quotation": "报价单", + "ExtraText": "额外文字", + "ExtraAmount": "额外金额", + "DownloadQuotation": "下载报价单", + "Invoice": "发票", + "TaxNumber": "税号", + "InvoiceNumber": "发票数字", + "InvoiceDate": "发票日期", + "InvoiceNote": "发票说明", + "Quantity": "数量", + "AddProduct": "添加产品", + "AddProductWarning": "你需要添加产品", + "TotalPrice": "总价", + "Generate": "生成", + "MissingQuantityField": "数量字段为必填项!", + "MissingPriceField": "价格字段为必填项!", + "CodeUsageStatus": "状态", + "Country": "国家", + "DeveloperCount": "开发者数量", + "RequestCode": "请求码", + "WebSite": "网站", + "GithubUsername": "Github用户名", + "PhoneNumber": "手机号", + "ProjectDescription": "产品描述", + "Referrer": "推荐人", + "DiscountRequests": "折扣请求", + "Copylink": "拷贝链接", + "Disable": "禁用", + "Enable": "启用", + "EnableSendEmail": "启用发送邮件", + "SendEmail": "发送邮件", + "SuccessfullyDisabled": "禁用成功", + "SuccessfullyEnabled": "启用成功", + "EmailSent": "邮件发送", + "SuccessfullySent": "发送成功", + "SuccessfullyDeleted": "删除成功", + "DiscountRequestDeletionWarningMessage": "折扣成功将被删除", + "BusinessType": "商业类型", + "TotalQuestionCount": "问题总数", + "RemainingQuestionCount": "剩余问题数", + "TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount必须大于RemainingQuestionCount!", + "QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount和RemainingQuestionCount必须为0或大于0", + "UnlimitedQuestionCount": "无限的问题计数", + "Notes": "笔记", + "Menu:Community": "社区", + "Menu:Articles": "文章", + "Wait": "等待", + "Approve": "批准", + "Reject": "拒绝", + "Details": "详情", + "Url": "Url", + "Title": "标题", + "ContentSource": "内容源", + "Status": "状态", + "ReadArticle": "阅读文章", + "ArticleHasBeenWaiting": "文章还在等待", + "ArticleHasBeenApproved": "文章已被批准", + "ArticleHasBeenRejected": "文章已被拒绝", + "Permission:Community": "社区", + "Permission:CommunityArticle": "文字", + "Link": "链接", + "Enum:ContentSource:0": "Github", + "Enum:ContentSource:1": "外部", + "Enum:Status:0": "等待中", + "Enum:Status:1": "已拒绝", + "Enum:Status:2": "已批准", + "Summary": "概要", + "AuthorName": "作者名称", + "CoverImage": "封面图片", + "RemoveCacheConfirmationMessage": "你确定要删除\"{0}\" 文章缓存?", + "SuccessfullyRemoved": "清除成功", + "RemoveCache": "删除缓存" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index d6f334f7cd..a916cd82d9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -27,6 +27,7 @@ "Blog": "Blog", "Commercial": "Commercial", "MyAccount": "My account", - "SeeDocuments": "See Documents" + "SeeDocuments": "See Documents", + "Samples": "Samples" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json index 986d1fdc2c..79493b537e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json @@ -26,6 +26,8 @@ "ContributionGuide": "贡献指南", "Blog": "博客", "Commercial": "商业版", - "SeeDocuments": "查看文档" + "MyAccount": "我的账户", + "SeeDocuments": "查看文档", + "Samples": "示例" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json index e80457377f..0147e71a05 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json @@ -6,6 +6,8 @@ "Volo.AbpIo.Commercial:010003": "你不是该组织的所有者!", "OrganizationNotFoundMessage": "找不到任何组织!", "DeveloperCount": "开发者数量", + "QuestionCount": "剩余 / 问题总数", + "Unlimited": "无限制", "Owners": "所有者", "AddMember": "添加成员", "AddOwner": "添加所有者", @@ -25,6 +27,9 @@ "Volo.AbpIo.Commercial:010004": "不能找到指定的用户! 用户必须已经注册.", "MyOrganizations": "我的组织", "ApiKey": "API key", - "UserNameNotFound": "没有用户名为{0}的用户" + "UserNameNotFound": "没有用户名为{0}的用户", + "SuccessfullyAddedToNewsletter": "感谢你订阅我们的新闻通讯!", + "MyProfile": "我的资料", + "EmailNotValid": "请输入有效的电子邮件地址" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index 2544e50726..87db8c931a 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -84,6 +84,7 @@ "Edit": "Edit", "ProfileImageChange": "Change the profile image", "BlogItemErrorMessage": "Could not get the latest blog post details from ABP.", - "PlannedReleaseDate": "Planned release date" + "PlannedReleaseDate": "Planned release date", + "CommunityArticleRequestErrorMessage": "Could not get the latest article request from Github." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json index 307ff066a7..fa793c91a0 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json @@ -1,64 +1,89 @@ { - "culture": "zh-Hans", - "texts": { - "Permission:CommunityArticle": "社区文章", - "Permission:Edit": "修改", - "Waiting": "等待中", - "Approved": "已批准", - "Rejected": "已拒绝", - "Wait": "等待", - "Approve": "批准", - "Reject": "拒绝", - "ReadArticle": "阅读文章", - "Status": "状态", - "ContentSource": "内容来源", - "Details": "详情", - "Url": "url", - "Title": "标题", - "CreationTime": "创建时间", - "Save": "保存", - "SameUrlAlreadyExist": "url已存在,如果你想要添加这篇文章,你需要更改url!", - "UrlIsNotValid": "Url无效.", - "UrlNotFound" : "Url未找到.", - "UrlContentNotFound": "Url内容未找到.", - "Summary": "摘要", - "MostRead": "阅读最多", - "Latest": "最新", - "ContributeAbpCommunity": "为ABP社区做贡献", - "SubmitYourArticle": "提交你的文章", - "ContributionGuide": "贡献指南", - "BugReport": "Bug报告", - "SeeAllArticles": "查看所有的文章", - "WelcomeToABPCommunity!": "欢迎来到ABP社区!", - "MyProfile": "我的资料", - "MyOrganizations": "我的组织", - "EmailNotValid": "请输入有效的电子邮箱地址.", - "FeatureRequest": "功能请求", - "CreateArticleTitleInfo": "文章标题显示在文章列表中.", - "CreateArticleUrlInfo": "文章的原始GitHub/外部URL.", - "CreateArticleSummaryInfo": "文章的简短摘要将显示在文章列表中.", - "CreateArticleCoverInfo": "为了创建有效的文章,请添加封面图. 仅支持16:9的图片!", - "ThisExtensionIsNotAllowed": "不允许此扩展名.", - "TheFileIsTooLarge": "文件过大.", - "GoToTheArticle": "转到文章", - "Contribute": "贡献", - "OverallProgress": "总体流程", - "Done": "完成", - "Open": "打开", - "Closed": "关闭", - "LatestQuestionOnThe": "有关的最新问题", - "Stackoverflow": "Stackoverflow", - "Votes": "票数", - "Answer": "回答", - "Views": "观看次数", - "Answered": "已回答", - "WaitingForYourAnswer": "等待你的回答", - "Asked": "提问", - "AllQuestions": "所有的问题", - "NextVersion": "下一个版本", - "MilestoneErrorMessage": "无法从Github获取当前的里程碑详细信息.", - "QuestionItemErrorMessage": "无法从Stackoverflow获取最新的问题详细信息.", - "Oops": "哎呀!" - } + "culture": "zh-Hans", + "texts": { + "Permission:CommunityArticle": "社区文章", + "Permission:Edit": "修改", + "Waiting": "等待中", + "Approved": "已批准", + "Rejected": "已拒绝", + "Wait": "等待", + "Approve": "批准", + "Reject": "拒绝", + "ReadArticle": "阅读文章", + "Status": "状态", + "ContentSource": "内容来源", + "Details": "详情", + "Url": "url", + "Title": "标题", + "CreationTime": "创建时间", + "Save": "保存", + "SameUrlAlreadyExist": "url已存在,如果你想要添加这篇文章,你需要更改url!", + "UrlIsNotValid": "Url无效.", + "UrlNotFound": "Url未找到.", + "UrlContentNotFound": "Url内容未找到.", + "Summary": "摘要", + "MostRead": "阅读最多", + "Latest": "最新", + "ContributeAbpCommunity": "为ABP社区做贡献", + "SubmitYourArticle": "提交你的文章", + "ContributionGuide": "贡献指南", + "BugReport": "Bug报告", + "SeeAllArticles": "查看所有的文章", + "WelcomeToABPCommunity!": "欢迎来到ABP社区!", + "MyProfile": "我的资料", + "MyOrganizations": "我的组织", + "EmailNotValid": "请输入有效的电子邮箱地址.", + "FeatureRequest": "功能请求", + "CreateArticleTitleInfo": "文章标题显示在文章列表中.", + "CreateArticleUrlInfo": "文章的原始GitHub/外部URL.", + "CreateArticleSummaryInfo": "文章的简短摘要将显示在文章列表中.", + "CreateArticleCoverInfo": "为了创建有效的文章,请添加封面图. 仅支持16:9的图片!", + "ThisExtensionIsNotAllowed": "不允许此扩展名.", + "TheFileIsTooLarge": "文件过大.", + "GoToTheArticle": "转到文章", + "Contribute": "贡献", + "OverallProgress": "总体流程", + "Done": "完成", + "Open": "打开", + "Closed": "关闭", + "LatestQuestionOnThe": "有关的最新问题", + "Stackoverflow": "Stackoverflow", + "Votes": "票数", + "Answer": "回答", + "Views": "观看次数", + "Answered": "已回答", + "WaitingForYourAnswer": "等待你的回答", + "Asked": "提问", + "AllQuestions": "所有的问题", + "NextVersion": "下一个版本", + "MilestoneErrorMessage": "无法从Github获取当前的里程碑详细信息.", + "QuestionItemErrorMessage": "无法从Stackoverflow获取最新的问题详细信息.", + "Oops": "哎呀!", + "CreateArticleSuccessMessage": "文章提交成功. 网站管理员审核通过后将被发布.", + "ChooseCoverImage": "选项一张封面图片", + "CoverImage": "封面图片", + "ShareYourExperiencesWithTheABPFramework": "分享你的ABP Framework经验!", + "Optional": "可选的", + "UpdateUserWebSiteInfo": "示例: https://johndoe.com", + "UpdateUserTwitterInfo": "示例: johndoe", + "UpdateUserGithubInfo": "示例: johndoe", + "UpdateUserLinkedinInfo": "示例: https://www.linkedin.com/...", + "UpdateUserCompanyInfo": "示例v: Volosoft", + "UpdateUserJobTitleInfo": "示例: Software Developer", + "UserName": "用户名", + "Company": "公司", + "PersonalWebsite": "个人网站", + "RegistrationDate": "注册时间", + "Social": "社交", + "Biography": "传记", + "HasNoPublishedArticlesYet": "尚未发表文章", + "Author": "作者", + "LatestGithubAnnouncements": "最新的Github公告", + "SeeAllAnnouncements": "查看所有公告", + "LatestBlogPost": "最新博客文章", + "Edit": "修改", + "ProfileImageChange": "更改资料图片", + "BlogItemErrorMessage": "无法从ABP获取最新的博客文章详细信息.", + "PlannedReleaseDate": "计划发布日期" } - \ No newline at end of file +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index fa7b216bd0..cb4a8d076c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -93,6 +93,7 @@ "DynamicForms": "Dynamic Forms", "BundlingMinification": "Bundling & Minification", "BackgroundJobs": "Background Jobs", + "BackgroundJobsExplanation": "Define simple classes to execute jobs in background as queued. Use built-in job manager or integrate your own. Hangfire & RabbitMQ integrations are already available.", "DDDInfrastructure": "DDD Infrastructure", "DomainDrivenDesignInfrastructure": "Domain Driven Design Infrastructure", "AutoRESTAPIs": "Auto REST APIs", @@ -102,6 +103,7 @@ "TestInfrastructure": "Test Infrastructure", "AuditLoggingEntityHistories": "Audit Logging & Entity Histories", "ObjectToObjectMapping": "Object to Object Mapping", + "ObjectToObjectMappingExplanation": "Object to object mapping abstraction with AutoMapper integration.", "EmailSMSAbstractions": "Email & SMS Abstractions", "EmailSMSAbstractionsWithTemplatingSupport": "Email & SMS Abstractions with Templating Support", "Localization": "Localization", @@ -156,6 +158,32 @@ "UiFramework": "UI Framework", "EmailAddress": "Email address", "Mobile": "Mobile", - "ReactNative": "React Native" + "ReactNative": "React Native", + "Strong": "Strong", + "Complete": "Complete", + "BasedLayeringModel": "Based Layering Model", + "Microservice": "Microservice", + "Compatible": "Compatible", + "MeeTTheABPCommunityInfo": "Our mission is to create an environment where developers can help each other with articles, tutorials, case studies, etc. and meet like-minded people.", + "JoinTheABPCommunityInfo": "Get involved with a vibrant community and become a contributor to the ABP Framework!", + "AllArticles": "All Articles", + "SubmitYourArticle": "Submit Your Article", + "DynamicClientProxyDocument": "See the dynamic client proxy documentations for JavaScript & C#.", + "EmailSMSAbstractionsDocument": "See the emailing and SMS sending documents for more information.", + "CreateProjectWizard": "This wizard creates a new project from the startup template which is properly configured to jump start to your project.", + "TieredOption": "Creates a tiered solution where Web and Http API layers are physically separated. If not checked, creates a layered solution which is less complex and suitable for most scenarios.", + "SeparateIdentityServerOption": "Separates server side into two applications: First one is for the identity server and the second one is for your server side HTTP API.", + "UseslatestPreVersion": "Uses latest pre-release version", + "ReadTheDocumentation": "ReadThe Documentation", + "Documentation": "Documentation", + "GettingStartedTutorial": "Getting Started Tutorial", + "ApplicationDevelopmentTutorial": "Application Development Tutorial", + "TheStartupTemplate": "The Startup Template", + "InstallABPCLIInfo": "ABP CLI is the fastest way to start a new solution with the ABP framework. Install the ABP CLI using a command line window:", + "DifferentLevelOfNamespaces": "You can use different level of namespaces; e.g. BookStore, Acme.BookStore or Acme.Retail.BookStore.", + "ABPCLIExamplesInfo": "new command creates a layered MVC application with Entity Framework Core as the database provider. However, it has additional options. Examples:", + "SeeCliDocumentForMoreInformation": "See the ABP CLI document for more options or select the \"Direct Download\" tab above.", + "Optional": "Optional", + "LocalFrameworkRef": "Keep local project reference for the framework packages." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json index 7bd02b44ac..4dcb0cad51 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json @@ -89,10 +89,11 @@ "Features": "功能", "ABPCLI": "ABP CLI", "Modularity": "模块化", - "BootstrapTagHelpers": "Bootstrap Tag Helpers", + "BootstrapTagHelpers": "Bootstrap 标签助手", "DynamicForms": "动态表单", "BundlingMinification": "Bundling & Minification", "BackgroundJobs": "后台作业", + "BackgroundJobsExplanation": "定义简单的类以在队列中在后台执行作业. 使用内置的作业管理器或集成你自己的作业管理器. Hangfire & RabbitMQ集成已经可用.", "DDDInfrastructure": "DDD基础设施", "DomainDrivenDesignInfrastructure": "Domain Driven Design基础设施", "AutoRESTAPIs": "自动REST APIs", @@ -102,6 +103,7 @@ "TestInfrastructure": "测试基础设施", "AuditLoggingEntityHistories": "审计日志和实体历史", "ObjectToObjectMapping": "对象映射", + "ObjectToObjectMappingExplanation": "对象到对象映射 抽象AutoMapper集成.", "EmailSMSAbstractions": "电子邮件和短信抽象", "EmailSMSAbstractionsWithTemplatingSupport": "具有模板支持的电子邮件和短信抽象", "Localization": "本土化", @@ -112,7 +114,7 @@ "DependencyInjection": "依赖注入", "DependencyInjectionByConventions": "依据约定的依赖注入", "ABPCLIExplanation": "ABP CLI(命令行界面)是用于对ABP解决方案执行常见操作的命令行工具.", - "ModularityExplanation": "ABP提供了一个完整的基础设施来构建你自己的应用程序模块,这些模块可能具有实体,服务,数据库集成,API,UI组件等.", //TODO: strong "your own application modules",- + "ModularityExplanation": "ABP提供了一个完整的基础设施来构建你自己的应用程序模块,这些模块可能具有实体,服务,数据库集成,API,UI组件等.", "MultiTenancyExplanation": "ABP框架不仅支持开发多租户应用程序,而且使你的代码几乎无需知道多租户.", "MultiTenancyExplanation2": "可以自动确定当前租户,将不同租户的数据相互隔离.", "MultiTenancyExplanation3": "支持单一数据库,或每个租户单独数据库或者混合方式.", @@ -154,6 +156,34 @@ "SeeTheDocumentForMoreInformation": "查看{0} 文档获得更多信息", "IndexPageHeroSection": "asp.net core的开源Web应用程序
框架
", "UiFramework": "UI框架", - "EmailAddress": "电子邮件地址" + "EmailAddress": "电子邮件地址", + "Mobile": "移动", + "ReactNative": "React Native", + "Strong": "强大的", + "Complete": "完整的", + "BasedLayeringModel": "基于分层模型", + "Microservice": "微服务", + "Compatible": "兼容", + "MeeTTheABPCommunityInfo": "我们的使命是创建一个环境使开发人员可以在文章,教程,案例研究等方面互相帮助并结识志趣相投的人.", + "JoinTheABPCommunityInfo": "参与充满活力的社区并成为ABP框架的贡献者", + "AllArticles": "所有的文章", + "SubmitYourArticle": "提交你的文章", + "DynamicClientProxyDocument": "参阅JavaScript & C#的动态客户端代理文档.", + "EmailSMSAbstractionsDocument": "参阅emailing 和 SMS sending 文档获得更多信息.", + "CreateProjectWizard": "此向导让你从启动模板创建一个新项目,该启动模板已正确配置为可以快速启动你的项目.", + "TieredOption": "创建一个分层解决方案,其中Web和Http API层在物理上是分离的. 如果没有选中则创建一个不那么复杂且适合大多数场景的分层解决方案.", + "SeparateIdentityServerOption": "将服务器端分离为两个应用程序:第一个应用程序用于身份服务器,第二个应用程序用于服务器端HTTP API.", + "UseslatestPreVersion": "使用最新的预发布版本", + "ReadTheDocumentation": "阅读文档", + "Documentation": "文档", + "GettingStartedTutorial": "入门教程", + "ApplicationDevelopmentTutorial": "应用程序开发教程", + "TheStartupTemplate": "启动模板", + "InstallABPCLIInfo": "ABP CLI是使用ABP框架启动新解决方案的最快方式. 使用命令行窗口安装ABP CLI:", + "DifferentLevelOfNamespaces": "你可以使用不同级别的名称空间. 例如 BookStore, Acme.BookStore 或 Acme.Retail.BookStore", + "ABPCLIExamplesInfo": "new命令创建一个 分层的MVC应用程序 使用 Entity Framework Core 做为数据库提供程序. 它还有其他选项. 示例:", + "SeeCliDocumentForMoreInformation": "参阅 ABP CLI 文档 获得更多选项或选择上方的 \"直接下载\" 标签.", + "Optional": "可选的", + "LocalFrameworkRef": "保留框架包的本地项目引用." } } \ No newline at end of file diff --git a/build/common.ps1 b/build/common.ps1 index 830b6ce270..0afe55f120 100644 --- a/build/common.ps1 +++ b/build/common.ps1 @@ -31,6 +31,8 @@ if ($full -eq "-f") "../modules/blogging", "../templates/module/aspnet-core", "../templates/app/aspnet-core", + "../templates/console", + "../templates/wpf", "../abp_io/AbpIoLocalization" ) }else{ diff --git a/common.props b/common.props index fb54e50baf..9f6b677e72 100644 --- a/common.props +++ b/common.props @@ -1,6 +1,6 @@ - - latest + + latest 4.0.0 $(NoWarn);CS1591;CS0436 https://abp.io/assets/abp_nupkg.png diff --git a/docs/en/API/Auto-API-Controllers.md b/docs/en/API/Auto-API-Controllers.md index 77819c48c9..e139c16d20 100644 --- a/docs/en/API/Auto-API-Controllers.md +++ b/docs/en/API/Auto-API-Controllers.md @@ -75,17 +75,48 @@ Configure(options => Then the route for getting a book will be '**/api/volosoft/book-store/book/{id}**'. This sample uses two-level root path, but you generally use a single level depth. -* Continues with the **normalized controller/service name**. Normalization removes 'AppService', 'ApplicationService' and 'Service' postfixes and converts it to **camelCase**. If your application service class name is 'BookAppService' then it becomes only '/book'. +* Continues with the **normalized controller/service name**. Normalization removes 'AppService', 'ApplicationService' and 'Service' postfixes and converts it to **kebab-case**. If your application service class name is 'ReadingBookAppService' then it becomes only '/reading-book'. * If you want to customize naming, then set the `UrlControllerNameNormalizer` option. It's a func delegate which allows you to determine the name per controller/service. * If the method has an '**id**' parameter then it adds '**/{id}**' ro the route. * Then it adds the action name if necessary. Action name is obtained from the method name on the service and normalized by; * Removing '**Async**' postfix. If the method name is 'GetPhonesAsync' then it becomes 'GetPhones'. * Removing **HTTP method prefix**. 'GetList', 'GetAll', 'Get', 'Put', 'Update', 'Delete', 'Remove', 'Create', 'Add', 'Insert', 'Post' and 'Patch' prefixes are removed based on the selected HTTP method. So, 'GetPhones' becomes 'Phones' since 'Get' prefix is a duplicate for a GET request. - * Converting the result to **camelCase**. + * Converting the result to **kebab-case**. * If the resulting action name is **empty** then it's not added to the route. If it's not empty, it's added to the route (like '/phones'). For 'GetAllAsync' method name it will be empty, for 'GetPhonesAsync' method name it will be 'phones'. * Normalization can be customized by setting the `UrlActionNameNormalizer` option. It's an action delegate that is called for every method. * If there is another parameter with 'Id' postfix, then it's also added to the route as the final route segment (like '/phoneId'). +#### Customizing the Route Calculation + +`IConventionalRouteBuilder` is used to build the route. It is implemented by the `ConventionalRouteBuilder` by default and works as explained above. You can replace/override this service to customize the route calculation strategy. + +#### Version 3.x Style Route Calculation + +The route calculation was different before the version 4.0. It was using camelCase conventions, while the ABP Framework version 4.0+ uses kebab-case. If you use the old route calculation strategy, follow one of the approaches; + +* Set `UseV3UrlStyle` to `true` in the options of the `options.ConventionalControllers.Create(...)` method. Example: + +````csharp +options.ConventionalControllers + .Create(typeof(BookStoreApplicationModule).Assembly, opts => + { + opts.UseV3UrlStyle = true; + }); +```` + +This approach effects only the controllers for the `BookStoreApplicationModule`. + +* Set `UseV3UrlStyle` to `true` for the `AbpConventionalControllerOptions` to set it globally. Example: + +```csharp +Configure(options => +{ + options.UseV3UrlStyle = true; +}); +``` + +Setting it globally effects all the modules in a modular application. + ## Service Selection Creating conventional HTTP API controllers are not unique to application services actually. diff --git a/docs/en/Migration-Guides/Abp-4_0.md b/docs/en/Migration-Guides/Abp-4_0.md new file mode 100644 index 0000000000..b562c8573c --- /dev/null +++ b/docs/en/Migration-Guides/Abp-4_0.md @@ -0,0 +1,87 @@ +# ABP Framework 3.3 to 4.0 Migration Guide + +## Auto API Controller Route Changes + +The route calculation for the [Auto API Controllers](https://docs.abp.io/en/abp/latest/API/Auto-API-Controllers) is changing with the ABP Framework version 4.0 ([#5325](https://github.com/abpframework/abp/issues/5325)). Previously, **camelCase** route paths were being used. Beginning from the version 4.0, it uses **kebab-case** route paths where it is possible. + +**A typical auto API before v4.0** + +![route-before-4](images/route-before-4.png) + +**camelCase route parts become kebab-case with 4.0** + +![route-4](images/route-4.png) + +If it is hard to change it for your application, you can continue to use the version 3.x route strategy, by following one of the approaches; + +* Set `UseV3UrlStyle` to `true` in the options of the `options.ConventionalControllers.Create(...)` method. Example: + +````csharp +options.ConventionalControllers + .Create(typeof(BookStoreApplicationModule).Assembly, opts => + { + opts.UseV3UrlStyle = true; + }); +```` + +This approach effects only the controllers for the `BookStoreApplicationModule`. + +* Set `UseV3UrlStyle` to `true` for the `AbpConventionalControllerOptions` to set it globally. Example: + +```csharp +Configure(options => +{ + options.UseV3UrlStyle = true; +}); +``` + +Setting it globally effects all the modules in a modular application. + +## Identity Server Changes + +ABP Framework upgrades the [IdentityServer4](https://www.nuget.org/packages/IdentityServer4) library from 3.x to 4.x with the ABP Framework version 4.0. IdentityServer 4.x has a lot of changes, some of them are **breaking changes in the data structure**. + +### Database Changes + +**So, if you are upgrading from 3.x, then there are some change should be done in your database.** + +#### ApiScope + +As the **most important breaking change**, Identity Server 4.x places the `ApiScope` as an independent aggregate root. Previously it was a part of the to `ApiResource` aggregate. This requires manual operation. See the *Database Migration* section. + +Also, added `Enabled(string)` and `Description(bool,true)` properties. + +#### ApiResource + +* Added `AllowedAccessTokenSigningAlgorithms (string)` and `ShowInDiscoveryDocument(bool, default: true)` properties + +#### Client + +* Added `RequireRequestObject (bool)` and `AllowedIdentityTokenSigningAlgorithms (string)` properties. +* Changed default value of `RequireConsent` from `true` to `false`. +* Changed default value of `RequirePkce` from `false` to `true`. + +#### DeviceFlowCodes + +* Added `SessionId (string)` and `Description (string)` properties. + +#### PersistedGrant + +* Added `SessionId (string)` and `Description(string)` and `ConsumedTime (DateTime?)` properties + +## Migrating the Database + +> Attention: **Please backup your database** before the migration! + +If you are using **Entity Framework Core**, you need to add a new database migration, using the `Add-Migration` command, and apply changes to the database. Please **review the migration** script to understand if it effects your existing data. Otherwise, you may **loose some of your configuration**. + +If you haven't customize the `IdentityServerDataSeedContributor` and haven't customized the initial data inside the `IdentityServer*` tables; + +1. Update `IdentityServerDataSeedContributor` class by comparing to [the latest code](https://github.com/abpframework/abp/blob/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs). You probably only need to add the `CreateApiScopesAsync` method and the code related to it. +2. Then you can simply clear all the **table data** in these tables then execute the `DbMigrator` application again to fill it with the new configuration. + +If you've customize your IdentityServer configuration in the database or in the seed data, you should understand the changes and upgrade your code/data accordingly. + +### Related Resources +* https://leastprivilege.com/2020/06/19/announcing-identityserver4-v4-0/ +* https://github.com/IdentityServer/IdentityServer4/issues/4592 diff --git a/docs/en/Migration-Guides/BlazorUI-3_3.md b/docs/en/Migration-Guides/BlazorUI-3_3.md index 8a14481912..bb3d07f615 100644 --- a/docs/en/Migration-Guides/BlazorUI-3_3.md +++ b/docs/en/Migration-Guides/BlazorUI-3_3.md @@ -6,6 +6,7 @@ * Remove the ``typeof(AbpAccountBlazorModule)`` from the dependency list of *YourProjectBlazorModule* class and add the `typeof(AbpTenantManagementBlazorModule)`. * Add `@using Volo.Abp.BlazoriseUI` and `@using Volo.Abp.BlazoriseUI.Components` into the `_Imports.razor` file. * Remove the `div` with `id="blazor-error-ui"` (with its contents) from the `wwwroot/index.html ` file, since the ABP Framework now shows error messages as a better message box. +* Update the`AddOidcAuthentication` options in your *YourProjectBlazorModule* class as described in the issue [#5913](https://github.com/abpframework/abp/issues/5913). ## BlazoriseCrudPageBase to AbpCrudPageBase diff --git a/docs/en/Migration-Guides/images/route-4.png b/docs/en/Migration-Guides/images/route-4.png new file mode 100644 index 0000000000..0d57a57f3e Binary files /dev/null and b/docs/en/Migration-Guides/images/route-4.png differ diff --git a/docs/en/Migration-Guides/images/route-before-4.png b/docs/en/Migration-Guides/images/route-before-4.png new file mode 100644 index 0000000000..48d87c60c0 Binary files /dev/null and b/docs/en/Migration-Guides/images/route-before-4.png differ diff --git a/docs/en/Module-Development-Basics.md b/docs/en/Module-Development-Basics.md index e6f80233e4..4b76465a3e 100644 --- a/docs/en/Module-Development-Basics.md +++ b/docs/en/Module-Development-Basics.md @@ -57,7 +57,7 @@ public class BlogModule : AbpModule } ```` -See Configuration (TODO: link) document for more about the configuration system. +See the [Configuration](Configuration.md) document for more about the configuration system. #### Pre & Post Configure Services @@ -139,4 +139,4 @@ A depended module may depend on another module, but you only need to define your There are **two types of modules.** They don't have any structural difference but categorized by functionality and purpose: - **Framework modules**: These are **core modules of the framework** like caching, emailing, theming, security, serialization, validation, EF Core integration, MongoDB integration... etc. They do not have application/business functionalities but makes your daily development easier by providing common infrastructure, integration and abstractions. -- **Application modules**: These modules implement **specific application/business functionalities** like blogging, document management, identity management, tenant management... etc. They generally have their own entities, services, APIs and UI components. See [pre-built application modules](Modules/Index.md). \ No newline at end of file +- **Application modules**: These modules implement **specific application/business functionalities** like blogging, document management, identity management, tenant management... etc. They generally have their own entities, services, APIs and UI components. See [pre-built application modules](Modules/Index.md). diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 03b3420ada..8cdda55af2 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -329,6 +329,7 @@ Configure(options => `MyCustomTenantResolveContributor` must inherit from the `TenantResolveContributorBase` (or implement the `ITenantResolveContributor`) as shown below: ````csharp +using System.Threading.Tasks; using Volo.Abp.MultiTenancy; namespace MultiTenancyDemo.Web @@ -337,7 +338,7 @@ namespace MultiTenancyDemo.Web { public override string Name => "Custom"; - public override void Resolve(ITenantResolveContext context) + public override Task ResolveAsync(ITenantResolveContext context) { //TODO... } diff --git a/docs/en/UI/AspNetCore/JavaScript-API/Features.md b/docs/en/UI/AspNetCore/JavaScript-API/Features.md index e3cd2be445..8d58347f49 100644 --- a/docs/en/UI/AspNetCore/JavaScript-API/Features.md +++ b/docs/en/UI/AspNetCore/JavaScript-API/Features.md @@ -6,10 +6,24 @@ ## Basic Usage -`abp.features.values` can be used to access to the all feature values. - ````js -var excelExportFeatureValue = abp.features.values["ExportingToExcel"]; +//Gets a value as string. +var value = abp.features.get('ExportingToExcel'); + +//Check the feature is enabled +var enabled = abp.features.isEnabled('ExportingToExcel.Enabled'); ```` -Then you can check the value of the feature to perform your logic. \ No newline at end of file +## All Values + +`abp.features.values` can be used to access to the all feature values. + +An example value of this object is shown below: + +````js +{ + Identity.TwoFactor: "Optional", + ExportingToExcel.Enabled: "true", + ... +} +```` \ No newline at end of file diff --git a/docs/en/Validation.md b/docs/en/Validation.md index 15c3f13412..c4821adf65 100644 --- a/docs/en/Validation.md +++ b/docs/en/Validation.md @@ -112,6 +112,29 @@ namespace Acme.BookStore > ABP framework uses the [dynamic proxying / interception](Dynamic-Proxying-Interceptors.md) system to perform the validation. In order to make it working, your method should be **virtual** or your service should be injected and used over an **interface** (like `IMyService`). +#### Enabling/Disabling Validation + +You can use the `[DisableValidation]` to disable it for methods, classs and properties. + +````csharp +[DisableValidation] +public Void MyMethod() +{ +} + +[DisableValidation] +public class InputClass +{ + public string MyProperty { get; set; } +} + +public class InputClass +{ + [DisableValidation] + public string MyProperty { get; set; } +} +```` + ### AbpValidationException Once ABP determines a validation error, it throws an exception of type `AbpValidationException`. Your application code can throw `AbpValidationException`, but most of the times it is not needed. @@ -155,4 +178,4 @@ public class MyObjectValidationContributor ## FluentValidation Integration -Volo.Abp.FluentValidation package integrates the FluentValidation library to the validation system (by implementing the `IObjectValidationContributor`). See the [FluentValidation Integration document](FluentValidation.md) for more. \ No newline at end of file +Volo.Abp.FluentValidation package integrates the FluentValidation library to the validation system (by implementing the `IObjectValidationContributor`). See the [FluentValidation Integration document](FluentValidation.md) for more. diff --git a/docs/zh-Hans/Multi-Tenancy.md b/docs/zh-Hans/Multi-Tenancy.md index 863e9cfb4b..8e92d10673 100644 --- a/docs/zh-Hans/Multi-Tenancy.md +++ b/docs/zh-Hans/Multi-Tenancy.md @@ -127,13 +127,14 @@ namespace MyCompany.MyProject `MyCustomTenantResolveContributor`必须像下面这样实现**ITenantResolveContributor**接口: ````C# +using System.Threading.Tasks; using Volo.Abp.MultiTenancy; namespace MyCompany.MyProject { public class MyCustomTenantResolveContributor : ITenantResolveContributor { - public void Resolve(ITenantResolveContext context) + public override Task ResolveAsync(ITenantResolveContext context) { context.TenantIdOrName = ... //从其他地方获取租户id或租户名字... } diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 50320b645f..65cac6e7cd 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -347,9 +347,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Autofac.WebAssembl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Authentication.OpenIdConnect", "src\Volo.Abp.AspNetCore.Authentication.OpenIdConnect\Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj", "{DEFE3DB2-EA4F-4F90-87FC-B25D64427BC5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Rebus", "src\Volo.Abp.EventBus.Rebus\Volo.Abp.EventBus.Rebus.csproj", "{F689967F-1EF1-4D75-8BA4-2F2F3506B1F3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EventBus.Rebus", "src\Volo.Abp.EventBus.Rebus\Volo.Abp.EventBus.Rebus.csproj", "{F689967F-1EF1-4D75-8BA4-2F2F3506B1F3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.ExceptionHandling", "src\Volo.Abp.ExceptionHandling\Volo.Abp.ExceptionHandling.csproj", "{B9D1ADCB-D552-4626-A1F1-78FF72C1E822}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ExceptionHandling", "src\Volo.Abp.ExceptionHandling\Volo.Abp.ExceptionHandling.csproj", "{B9D1ADCB-D552-4626-A1F1-78FF72C1E822}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Components", "src\Volo.Abp.AspNetCore.Components\Volo.Abp.AspNetCore.Components.csproj", "{89840441-5A3A-4FD7-9CB4-E5B52FAEF72A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Swashbuckle", "src\Volo.Abp.Swashbuckle\Volo.Abp.Swashbuckle.csproj", "{DD9519E0-5A68-48DC-A051-7BF2AC922F3E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1045,6 +1049,14 @@ Global {B9D1ADCB-D552-4626-A1F1-78FF72C1E822}.Debug|Any CPU.Build.0 = Debug|Any CPU {B9D1ADCB-D552-4626-A1F1-78FF72C1E822}.Release|Any CPU.ActiveCfg = Release|Any CPU {B9D1ADCB-D552-4626-A1F1-78FF72C1E822}.Release|Any CPU.Build.0 = Release|Any CPU + {89840441-5A3A-4FD7-9CB4-E5B52FAEF72A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89840441-5A3A-4FD7-9CB4-E5B52FAEF72A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89840441-5A3A-4FD7-9CB4-E5B52FAEF72A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89840441-5A3A-4FD7-9CB4-E5B52FAEF72A}.Release|Any CPU.Build.0 = Release|Any CPU + {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1222,6 +1234,8 @@ Global {DEFE3DB2-EA4F-4F90-87FC-B25D64427BC5} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {F689967F-1EF1-4D75-8BA4-2F2F3506B1F3} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {B9D1ADCB-D552-4626-A1F1-78FF72C1E822} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {89840441-5A3A-4FD7-9CB4-E5B52FAEF72A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {DD9519E0-5A68-48DC-A051-7BF2AC922F3E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor new file mode 100644 index 0000000000..574a684213 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor @@ -0,0 +1,48 @@ +@using Volo.Abp.UI.Navigation +@{ + var elementId = MenuItem.ElementId ?? "MenuItem_" + MenuItem.Name.Replace(".", "_"); + var cssClass = string.IsNullOrEmpty(MenuItem.CssClass) ? string.Empty : MenuItem.CssClass; + var disabled = MenuItem.IsDisabled ? "disabled" : string.Empty; + var url = string.IsNullOrEmpty(MenuItem.Url) ? "#" : MenuItem.Url; +} +@if (MenuItem.IsLeaf) +{ + if (MenuItem.Url != null) + { + + } +} +else +{ + +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor.cs new file mode 100644 index 0000000000..d0ff42879c --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Routing; +using Volo.Abp.UI.Navigation; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic +{ + public partial class FirstLevelNavMenuItem : IDisposable + { + [Inject] private NavigationManager NavigationManager { get; set; } + + [Parameter] + public ApplicationMenuItem MenuItem { get; set; } + + public bool IsSubMenuOpen { get; set; } + + protected override void OnInitialized() + { + NavigationManager.LocationChanged += OnLocationChanged; + } + + private void ToggleSubMenu() + { + IsSubMenuOpen = !IsSubMenuOpen; + } + + public void Dispose() + { + NavigationManager.LocationChanged -= OnLocationChanged; + } + + private void OnLocationChanged(object sender, LocationChangedEventArgs e) + { + IsSubMenuOpen = false; + StateHasChanged(); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor index 3d3dd26fae..e4767cc031 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor @@ -1,13 +1,22 @@ @using Microsoft.AspNetCore.Components.WebAssembly.Authentication @using Volo.Abp.Users +@using Volo.Abp.MultiTenancy @inject ICurrentUser CurrentUser +@inject ICurrentTenant CurrentTenant @inject NavigationManager Navigation @inject SignOutSessionStateManager SignOutManager - @CurrentUser.UserName + @if (CurrentTenant.Name != null) + { + @CurrentTenant.Name\@CurrentUser.UserName + } + else + { + @CurrentUser.UserName + } @if (Menu != null) diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor index 6954057142..45496a7984 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor @@ -4,12 +4,12 @@
+ @Body diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor.cs new file mode 100644 index 0000000000..2464275c2c --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor.cs @@ -0,0 +1,34 @@ +using System; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Routing; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic +{ + public partial class MainLayout : IDisposable + { + [Inject] private NavigationManager NavigationManager { get; set; } + + private bool IsCollapseShown { get; set; } + + protected override void OnInitialized() + { + NavigationManager.LocationChanged += OnLocationChanged; + } + + private void ToggleCollapse() + { + IsCollapseShown = !IsCollapseShown; + } + + public void Dispose() + { + NavigationManager.LocationChanged -= OnLocationChanged; + } + + private void OnLocationChanged(object sender, LocationChangedEventArgs e) + { + IsCollapseShown = false; + StateHasChanged(); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor index c3ada520dc..b35ec8ba2e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor @@ -2,50 +2,6 @@ { foreach (var menuItem in Menu.Items) { - var elementId = menuItem.ElementId ?? "MenuItem_" + menuItem.Name.Replace(".", "_"); - var cssClass = string.IsNullOrEmpty(menuItem.CssClass) ? string.Empty : menuItem.CssClass; - var disabled = menuItem.IsDisabled ? "disabled" : string.Empty; - var url = string.IsNullOrEmpty(menuItem.Url) ? "#" : menuItem.Url; - if (menuItem.IsLeaf) - { - if (menuItem.Url != null) - { - - } - } - else - { - - } + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs index e47603e163..1779d73d28 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs @@ -6,22 +6,14 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic { public partial class NavMenu { - [Inject] protected IMenuManager MenuManager { get; set; } + [Inject] + protected IMenuManager MenuManager { get; set; } protected ApplicationMenu Menu { get; set; } - private bool collapseNavMenu = true; - - private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; - - protected override async Task OnInitializedAsync() + protected async override Task OnInitializedAsync() { Menu = await MenuManager.GetAsync(StandardMenus.Main); } - - private void ToggleNavMenu() - { - collapseNavMenu = !collapseNavMenu; - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenuItem.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor similarity index 82% rename from framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenuItem.razor rename to framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor index 338ce7b464..4e75e26b50 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenuItem.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor @@ -24,7 +24,7 @@ else {