From aa19a3583430ba6814ec89bbade07810b69157ec Mon Sep 17 00:00:00 2001 From: hishamco Date: Sun, 10 Jan 2021 20:09:04 +0300 Subject: [PATCH 01/17] Add language repository & controller --- .../Controllers/LanguageController.cs | 52 +++++++++++++++++++ .../Repository/Context/TenantDBContext.cs | 4 +- .../Interfaces/ILanguageRepository.cs | 16 ++++++ .../Repository/LanguageRepository.cs | 35 +++++++++++++ Oqtane.Server/Startup.cs | 1 + Oqtane.Shared/Models/Language.cs | 25 +++++++++ 6 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 Oqtane.Server/Controllers/LanguageController.cs create mode 100644 Oqtane.Server/Repository/Interfaces/ILanguageRepository.cs create mode 100644 Oqtane.Server/Repository/LanguageRepository.cs create mode 100644 Oqtane.Shared/Models/Language.cs diff --git a/Oqtane.Server/Controllers/LanguageController.cs b/Oqtane.Server/Controllers/LanguageController.cs new file mode 100644 index 00000000..b2a38ee5 --- /dev/null +++ b/Oqtane.Server/Controllers/LanguageController.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Oqtane.Enums; +using Oqtane.Infrastructure; +using Oqtane.Models; +using Oqtane.Repository; +using Oqtane.Shared; + +namespace Oqtane.Controllers +{ + [Route(ControllerRoutes.Default)] + public class LanguageController : Controller + { + private readonly ILanguageRepository _languages; + private readonly ILogManager _logger; + + public LanguageController(ILanguageRepository language, ILogManager logger) + { + _languages = roles; + _logger = language; + } + + [HttpGet] + [Authorize(Roles = RoleNames.Registered)] + public IEnumerable Get(string siteid) => _languages.GetLanguages(int.Parse(siteid)); + + [HttpGet("{id}")] + [Authorize(Roles = RoleNames.Registered)] + public Language Get(int id) => _languages.GetLanguage(id); + + [HttpPost] + [Authorize(Roles = RoleNames.Admin)] + public Language Post([FromBody] Language language) + { + if (ModelState.IsValid) + { + language = _languages.AddLanguage(language); + _logger.Log(LogLevel.Information, this, LogFunction.Create, "Language Added {Language}", role); + } + return role; + } + + [HttpDelete("{id}")] + [Authorize(Roles = RoleNames.Admin)] + public void Delete(int id) + { + _languages.DeleteLanguage(id); + _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Language Deleted {LanguageId}", id); + } + } +} diff --git a/Oqtane.Server/Repository/Context/TenantDBContext.cs b/Oqtane.Server/Repository/Context/TenantDBContext.cs index be085b20..79270ffb 100644 --- a/Oqtane.Server/Repository/Context/TenantDBContext.cs +++ b/Oqtane.Server/Repository/Context/TenantDBContext.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Oqtane.Models; @@ -21,6 +21,8 @@ namespace Oqtane.Repository public virtual DbSet Folder { get; set; } public virtual DbSet File { get; set; } + public virtual DbSet Languages { get; set; } + public TenantDBContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor) : base(tenantResolver, accessor) { // DBContextBase handles multi-tenant database connections diff --git a/Oqtane.Server/Repository/Interfaces/ILanguageRepository.cs b/Oqtane.Server/Repository/Interfaces/ILanguageRepository.cs new file mode 100644 index 00000000..0ec10442 --- /dev/null +++ b/Oqtane.Server/Repository/Interfaces/ILanguageRepository.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public interface ILanguageRepository + { + IEnumerable GetLanguages(int siteId); + + Language AddLanguage(Language language); + + Language GetLanguage(int languageId); + + void DeleteLanguage(int languageId); + } +} diff --git a/Oqtane.Server/Repository/LanguageRepository.cs b/Oqtane.Server/Repository/LanguageRepository.cs new file mode 100644 index 00000000..2f59a047 --- /dev/null +++ b/Oqtane.Server/Repository/LanguageRepository.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Linq; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public class LanguageRepository : ILanguageRepository + { + private TenantDBContext _db; + + public LanguageRepository(TenantDBContext context) + { + _db = context; + } + + public IEnumerable GetLanguages(int siteId) => _db.Languages.Where(l => l.SiteId == siteId); + + public Language AddLanguage(Language language) + { + _db.Languages.Add(language); + _db.SaveChanges(); + + return language; + } + + public Language GetLanguage(int languageId) => _db.Languages.Find(languageId); + + public void DeleteLanguage(int languageId) + { + var language = _db.Languages.Find(languageId); + _db.Languages.Remove(language); + _db.SaveChanges(); + } + } +} diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index b134a19e..b4e9569d 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -213,6 +213,7 @@ namespace Oqtane services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); // load the external assemblies into the app domain, install services services.AddOqtane(_runtime, _supportedCultures); diff --git a/Oqtane.Shared/Models/Language.cs b/Oqtane.Shared/Models/Language.cs new file mode 100644 index 00000000..2433d0d0 --- /dev/null +++ b/Oqtane.Shared/Models/Language.cs @@ -0,0 +1,25 @@ +using System; + +namespace Oqtane.Models +{ + public class Language : IAuditable + { + public int LanguageId { get; set; } + + public int? SiteId { get; set; } + + public string Name { get; set; } + + public string Code { get; set; } + + public bool IsCurrent { get; set; } + + public string CreatedBy { get; set; } + + public DateTime CreatedOn { get; set; } + + public string ModifiedBy { get; set; } + + public DateTime ModifiedOn { get; set; } + } +} From 3059e8c763d87740f38262cf5f3896e0afffdb50 Mon Sep 17 00:00:00 2001 From: hishamco Date: Sun, 10 Jan 2021 20:17:35 +0300 Subject: [PATCH 02/17] Add language service --- Oqtane.Client/Program.cs | 1 + .../Services/Interfaces/ILanguageService.cs | 17 +++++++++ Oqtane.Client/Services/LanguageService.cs | 38 +++++++++++++++++++ Oqtane.Server/Startup.cs | 1 + 4 files changed, 57 insertions(+) create mode 100644 Oqtane.Client/Services/Interfaces/ILanguageService.cs create mode 100644 Oqtane.Client/Services/LanguageService.cs diff --git a/Oqtane.Client/Program.cs b/Oqtane.Client/Program.cs index 4c2d1201..558b8290 100644 --- a/Oqtane.Client/Program.cs +++ b/Oqtane.Client/Program.cs @@ -67,6 +67,7 @@ namespace Oqtane.Client builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); await LoadClientAssemblies(httpClient); diff --git a/Oqtane.Client/Services/Interfaces/ILanguageService.cs b/Oqtane.Client/Services/Interfaces/ILanguageService.cs new file mode 100644 index 00000000..82fbcc78 --- /dev/null +++ b/Oqtane.Client/Services/Interfaces/ILanguageService.cs @@ -0,0 +1,17 @@ +using Oqtane.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Oqtane.Services +{ + public interface ILanguageService + { + Task> GetLanguagesAsync(int siteId); + + Task GetLanguageAsync(int languageId); + + Task AddLanguageAsync(Language language); + + Task DeleteLanguageAsync(int languageId); + } +} diff --git a/Oqtane.Client/Services/LanguageService.cs b/Oqtane.Client/Services/LanguageService.cs new file mode 100644 index 00000000..432a2312 --- /dev/null +++ b/Oqtane.Client/Services/LanguageService.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Oqtane.Models; +using Oqtane.Shared; + +namespace Oqtane.Services +{ + public class LanguageService : ServiceBase, ILanguageService + { + + private readonly SiteState _siteState; + + public LanguageService(HttpClient http, SiteState siteState) : base(http) + { + _siteState = siteState; + } + + private string Apiurl => CreateApiUrl(_siteState.Alias, "Language"); + + public async Task> GetLanguagesAsync(int siteId) + { + var languages = await GetJsonAsync>($"{Apiurl}?siteid={siteId}"); + + return languages.OrderBy(l => l.Name).ToList(); + } + + public async Task GetLanguageAsync(int languageId) + => await GetJsonAsync($"{Apiurl}/{languageId}"); + + public async Task AddRoleAsync(Language language) + => await PostJsonAsync(Apiurl, language); + + public async Task DeleteLanguageAsync(int languageId) + => await DeleteAsync($"{Apiurl}/{languageId}"); + } +} diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index b4e9569d..0353bc03 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -128,6 +128,7 @@ namespace Oqtane services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddSingleton(); From 9b4316d6cd66d7b09e66f23b3afabab7d716acfd Mon Sep 17 00:00:00 2001 From: hishamco Date: Sun, 10 Jan 2021 21:32:11 +0300 Subject: [PATCH 03/17] Fix errors --- Oqtane.Client/Services/LanguageService.cs | 2 +- Oqtane.Server/Controllers/LanguageController.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Oqtane.Client/Services/LanguageService.cs b/Oqtane.Client/Services/LanguageService.cs index 432a2312..da1e0342 100644 --- a/Oqtane.Client/Services/LanguageService.cs +++ b/Oqtane.Client/Services/LanguageService.cs @@ -29,7 +29,7 @@ namespace Oqtane.Services public async Task GetLanguageAsync(int languageId) => await GetJsonAsync($"{Apiurl}/{languageId}"); - public async Task AddRoleAsync(Language language) + public async Task AddLanguageAsync(Language language) => await PostJsonAsync(Apiurl, language); public async Task DeleteLanguageAsync(int languageId) diff --git a/Oqtane.Server/Controllers/LanguageController.cs b/Oqtane.Server/Controllers/LanguageController.cs index b2a38ee5..2b8f7cf0 100644 --- a/Oqtane.Server/Controllers/LanguageController.cs +++ b/Oqtane.Server/Controllers/LanguageController.cs @@ -17,8 +17,8 @@ namespace Oqtane.Controllers public LanguageController(ILanguageRepository language, ILogManager logger) { - _languages = roles; - _logger = language; + _languages = language; + _logger = logger; } [HttpGet] @@ -36,9 +36,9 @@ namespace Oqtane.Controllers if (ModelState.IsValid) { language = _languages.AddLanguage(language); - _logger.Log(LogLevel.Information, this, LogFunction.Create, "Language Added {Language}", role); + _logger.Log(LogLevel.Information, this, LogFunction.Create, "Language Added {Language}", language); } - return role; + return language; } [HttpDelete("{id}")] From 21e09d95da17aaaf297b52e68179bf3451b4cd32 Mon Sep 17 00:00:00 2001 From: hishamco Date: Sun, 10 Jan 2021 21:32:25 +0300 Subject: [PATCH 04/17] Add migration script --- Oqtane.Server/Scripts/Tenant.02.00.02.00.sql | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Oqtane.Server/Scripts/Tenant.02.00.02.00.sql diff --git a/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql b/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql new file mode 100644 index 00000000..8eb6eef3 --- /dev/null +++ b/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql @@ -0,0 +1,26 @@ +/* + +Version 2.0.0 Tenant migration script + +*/ + +CREATE TABLE [dbo].[Language]( + [LanguageId] [int] IDENTITY(1,1) NOT NULL, + [Name] [nvarchar](100) NOT NULL, + [Code] [nvarchar](10) NOT NULL, + [TenantId] [int], + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, + CONSTRAINT [PK_Language] PRIMARY KEY CLUSTERED + ( + [LanguageId] ASC + ) +) +GO + +ALTER TABLE [dbo].[Language] WITH CHECK ADD CONSTRAINT [FK_Language_Tenant] FOREIGN KEY([TenantId]) +REFERENCES [dbo].[Tenant] ([TenantId]) +ON DELETE CASCADE +GO \ No newline at end of file From 91a844c9101b726a9bb73b75ea64fe6067417948 Mon Sep 17 00:00:00 2001 From: hishamco Date: Sun, 10 Jan 2021 23:17:03 +0300 Subject: [PATCH 05/17] Add language management page template --- .../Modules/Admin/Languages/Index.razor | 54 +++++++++++++++++++ Oqtane.Server/Repository/SiteRepository.cs | 27 ++++++++++ Oqtane.Server/Scripts/Tenant.02.00.02.00.sql | 1 + 3 files changed, 82 insertions(+) create mode 100644 Oqtane.Client/Modules/Admin/Languages/Index.razor diff --git a/Oqtane.Client/Modules/Admin/Languages/Index.razor b/Oqtane.Client/Modules/Admin/Languages/Index.razor new file mode 100644 index 00000000..c45a8bc2 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/Languages/Index.razor @@ -0,0 +1,54 @@ +@namespace Oqtane.Modules.Admin.Languages +@inherits ModuleBase +@inject ILanguageService LanguageService +@inject IStringLocalizer Localizer + +@if (_languages == null) +{ +

@Localizer["Loading..."]

+} +else +{ + + + +
+   + @Localizer["Name"] + @Localizer["Code"] +
+ + + @context.Name + @context.Code + +
+} + +@code { + private List _languages; + + public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; + + protected override async Task OnParametersSetAsync() + { + _languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId); + } + + private async Task DeleteLanguage(Language language) + { + try + { + await LanguageService.DeleteLanguageAsync(language.LanguageId); + await logger.LogInformation("Language Deleted {Language}", language); + + StateHasChanged(); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Deleting Language {Language} {Error}", language, ex.Message); + + AddModuleMessage(Localizer["Error Deleting Language"], MessageType.Error); + } + } +} diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index d8df82b6..64791442 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -502,6 +502,33 @@ namespace Oqtane.Repository } }); pageTemplates.Add(new PageTemplate + { + Name = "Language Management", + Parent = "Admin", + Path = "admin/languages", + Icon = Icons.Text, + IsNavigation = false, + IsPersonalizable = false, + PagePermissions = new List + { + new Permission(PermissionNames.View, RoleNames.Host, true), + new Permission(PermissionNames.Edit, RoleNames.Host, true) + }.EncodePermissions(), + PageTemplateModules = new List + { + new PageTemplateModule + { + ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Languages.Index).ToModuleDefinitionName(), Title = "Language Management", Pane = "Content", + ModulePermissions = new List + { + new Permission(PermissionNames.View, RoleNames.Host, true), + new Permission(PermissionNames.Edit, RoleNames.Host, true) + }.EncodePermissions(), + Content = "" + } + } + }); + pageTemplates.Add(new PageTemplate { Name = "Scheduled Jobs", Parent = "Admin", Path = "admin/jobs", Icon = Icons.Timer, IsNavigation = false, IsPersonalizable = false, PagePermissions = new List diff --git a/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql b/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql index 8eb6eef3..a52e8022 100644 --- a/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql +++ b/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql @@ -8,6 +8,7 @@ CREATE TABLE [dbo].[Language]( [LanguageId] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](100) NOT NULL, [Code] [nvarchar](10) NOT NULL, + [IsCurrent] [bit] NOT NULL, [TenantId] [int], [CreatedBy] [nvarchar](256) NOT NULL, [CreatedOn] [datetime] NOT NULL, From 8ab511fda773aad2ed4958485798ae891a7355ae Mon Sep 17 00:00:00 2001 From: hishamco Date: Sun, 10 Jan 2021 23:17:35 +0300 Subject: [PATCH 06/17] Return empty list if languages list are null --- Oqtane.Client/Services/LanguageService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Client/Services/LanguageService.cs b/Oqtane.Client/Services/LanguageService.cs index da1e0342..5f5d29cb 100644 --- a/Oqtane.Client/Services/LanguageService.cs +++ b/Oqtane.Client/Services/LanguageService.cs @@ -23,7 +23,7 @@ namespace Oqtane.Services { var languages = await GetJsonAsync>($"{Apiurl}?siteid={siteId}"); - return languages.OrderBy(l => l.Name).ToList(); + return languages?.OrderBy(l => l.Name).ToList() ?? Enumerable.Empty().ToList(); } public async Task GetLanguageAsync(int languageId) From 70595eb90ab04a77789045cc00b8a455bf80df12 Mon Sep 17 00:00:00 2001 From: hishamco Date: Sun, 10 Jan 2021 23:50:21 +0300 Subject: [PATCH 07/17] Fix Language table --- Oqtane.Server/Repository/Context/TenantDBContext.cs | 2 +- Oqtane.Server/Repository/LanguageRepository.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Oqtane.Server/Repository/Context/TenantDBContext.cs b/Oqtane.Server/Repository/Context/TenantDBContext.cs index 79270ffb..d6fd06c4 100644 --- a/Oqtane.Server/Repository/Context/TenantDBContext.cs +++ b/Oqtane.Server/Repository/Context/TenantDBContext.cs @@ -21,7 +21,7 @@ namespace Oqtane.Repository public virtual DbSet Folder { get; set; } public virtual DbSet File { get; set; } - public virtual DbSet Languages { get; set; } + public virtual DbSet Language { get; set; } public TenantDBContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor) : base(tenantResolver, accessor) { diff --git a/Oqtane.Server/Repository/LanguageRepository.cs b/Oqtane.Server/Repository/LanguageRepository.cs index 2f59a047..bdfd1b3e 100644 --- a/Oqtane.Server/Repository/LanguageRepository.cs +++ b/Oqtane.Server/Repository/LanguageRepository.cs @@ -13,22 +13,22 @@ namespace Oqtane.Repository _db = context; } - public IEnumerable GetLanguages(int siteId) => _db.Languages.Where(l => l.SiteId == siteId); + public IEnumerable GetLanguages(int siteId) => _db.Language.Where(l => l.SiteId == siteId); public Language AddLanguage(Language language) { - _db.Languages.Add(language); + _db.Language.Add(language); _db.SaveChanges(); return language; } - public Language GetLanguage(int languageId) => _db.Languages.Find(languageId); + public Language GetLanguage(int languageId) => _db.Language.Find(languageId); public void DeleteLanguage(int languageId) { - var language = _db.Languages.Find(languageId); - _db.Languages.Remove(language); + var language = _db.Language.Find(languageId); + _db.Language.Remove(language); _db.SaveChanges(); } } From 128729d4a09d3f0f048ff93d30a75a0cd8206cfb Mon Sep 17 00:00:00 2001 From: hishamco Date: Sun, 10 Jan 2021 23:50:34 +0300 Subject: [PATCH 08/17] TenantId -> SiteId --- Oqtane.Server/Scripts/Tenant.02.00.02.00.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql b/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql index a52e8022..8eb54714 100644 --- a/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql +++ b/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql @@ -9,7 +9,7 @@ CREATE TABLE [dbo].[Language]( [Name] [nvarchar](100) NOT NULL, [Code] [nvarchar](10) NOT NULL, [IsCurrent] [bit] NOT NULL, - [TenantId] [int], + [SiteId] [int], [CreatedBy] [nvarchar](256) NOT NULL, [CreatedOn] [datetime] NOT NULL, [ModifiedBy] [nvarchar](256) NOT NULL, @@ -21,7 +21,7 @@ CREATE TABLE [dbo].[Language]( ) GO -ALTER TABLE [dbo].[Language] WITH CHECK ADD CONSTRAINT [FK_Language_Tenant] FOREIGN KEY([TenantId]) +ALTER TABLE [dbo].[Language] WITH CHECK ADD CONSTRAINT [FK_Language_Tenant] FOREIGN KEY([SiteId]) REFERENCES [dbo].[Tenant] ([TenantId]) ON DELETE CASCADE GO \ No newline at end of file From 7d090e51a12d00f9b6573ba0adf9b754ecaa6b78 Mon Sep 17 00:00:00 2001 From: hishamco Date: Sun, 10 Jan 2021 23:51:15 +0300 Subject: [PATCH 09/17] Add language page --- .../Modules/Admin/Languages/Add.razor | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Oqtane.Client/Modules/Admin/Languages/Add.razor diff --git a/Oqtane.Client/Modules/Admin/Languages/Add.razor b/Oqtane.Client/Modules/Admin/Languages/Add.razor new file mode 100644 index 00000000..baa287e5 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/Languages/Add.razor @@ -0,0 +1,72 @@ +@namespace Oqtane.Modules.Admin.Languages +@inherits ModuleBase +@using System.Globalization +@inject NavigationManager NavigationManager +@inject ILanguageService LanguageService +@inject IStringLocalizer Localizer + + + + + + + + + + +
+ + + +
+ + + +
+ +@Localizer["Cancel"] + +@code { + private string _code = string.Empty; + private string _isCurrent = "False"; + + public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; + + private static IEnumerable GetCultures() + => CultureInfo.GetCultures(CultureTypes.AllCultures) + .Select(c => new Culture { Name = c.Name, DisplayName = c.DisplayName }); + + private async Task SaveLanguage() + { + var language = new Language + { + SiteId = PageState.Page.SiteId, + Name = CultureInfo.GetCultureInfo(_code).DisplayName, + Code = _code, + IsCurrent = (_isCurrent == null ? false : Boolean.Parse(_isCurrent)) + }; + + try + { + language = await LanguageService.AddLanguageAsync(language); + + await logger.LogInformation("Language Added {Language}", language); + + NavigationManager.NavigateTo(NavigateUrl()); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Adding Language {Language} {Error}", language, ex.Message); + + AddModuleMessage(Localizer["Error Adding Language"], MessageType.Error); + } + } +} From 3a8fc428a6e3a719f13aa66ee5e36ed62ae9da5b Mon Sep 17 00:00:00 2001 From: hishamco Date: Mon, 11 Jan 2021 00:04:43 +0300 Subject: [PATCH 10/17] Use TriaStateCheckBox for language IsCurrent --- Oqtane.Client/Modules/Admin/Languages/Index.razor | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Oqtane.Client/Modules/Admin/Languages/Index.razor b/Oqtane.Client/Modules/Admin/Languages/Index.razor index c45a8bc2..933903cc 100644 --- a/Oqtane.Client/Modules/Admin/Languages/Index.razor +++ b/Oqtane.Client/Modules/Admin/Languages/Index.razor @@ -16,11 +16,13 @@ else   @Localizer["Name"] @Localizer["Code"] + @Localizer["Is Current"] @context.Name @context.Code + } From 932c5590afee063eb1cded3c312335afe5b8ce2e Mon Sep 17 00:00:00 2001 From: hishamco Date: Mon, 11 Jan 2021 00:11:30 +0300 Subject: [PATCH 11/17] Make sure one language is set to current --- Oqtane.Server/Repository/LanguageRepository.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Oqtane.Server/Repository/LanguageRepository.cs b/Oqtane.Server/Repository/LanguageRepository.cs index bdfd1b3e..ade74f2d 100644 --- a/Oqtane.Server/Repository/LanguageRepository.cs +++ b/Oqtane.Server/Repository/LanguageRepository.cs @@ -17,6 +17,12 @@ namespace Oqtane.Repository public Language AddLanguage(Language language) { + if (language.IsCurrent) + { + // Ensure all other languages are not set to current + _db.Language.ToList().ForEach(l => l.IsCurrent = false); + } + _db.Language.Add(language); _db.SaveChanges(); From c5ae8c979b74efdee4c7ee90d215efc7e39becf3 Mon Sep 17 00:00:00 2001 From: hishamco Date: Wed, 13 Jan 2021 18:19:56 +0300 Subject: [PATCH 12/17] Cultures should come from supported cultures --- .../Modules/Admin/Languages/Add.razor | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Languages/Add.razor b/Oqtane.Client/Modules/Admin/Languages/Add.razor index baa287e5..efd5f22b 100644 --- a/Oqtane.Client/Modules/Admin/Languages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Languages/Add.razor @@ -2,6 +2,7 @@ @inherits ModuleBase @using System.Globalization @inject NavigationManager NavigationManager +@inject ILocalizationService LocalizationService @inject ILanguageService LanguageService @inject IStringLocalizer Localizer @@ -11,12 +12,15 @@ - + @if (_supportedCultures?.Count() > 1) + { + + } @@ -31,7 +35,7 @@ - + @Localizer["Cancel"] @code { @@ -40,9 +44,12 @@ public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; - private static IEnumerable GetCultures() - => CultureInfo.GetCultures(CultureTypes.AllCultures) - .Select(c => new Culture { Name = c.Name, DisplayName = c.DisplayName }); + private IEnumerable _supportedCultures; + + protected override async Task OnParametersSetAsync() + { + _supportedCultures = await LocalizationService.GetCulturesAsync(); + } private async Task SaveLanguage() { From b3152ee3e5c162cfa0b511062532bf6d5afab438 Mon Sep 17 00:00:00 2001 From: hishamco Date: Wed, 13 Jan 2021 18:26:36 +0300 Subject: [PATCH 13/17] LanguageSwitcher should have the cultures from language management --- Oqtane.Client/Themes/Controls/LanguageSwitcher.razor | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Themes/Controls/LanguageSwitcher.razor b/Oqtane.Client/Themes/Controls/LanguageSwitcher.razor index 16391513..dd92bf15 100644 --- a/Oqtane.Client/Themes/Controls/LanguageSwitcher.razor +++ b/Oqtane.Client/Themes/Controls/LanguageSwitcher.razor @@ -1,9 +1,9 @@ @namespace Oqtane.Themes.Controls @inherits ThemeControlBase @using System.Globalization -@using Microsoft.AspNetCore.Localization; +@using Microsoft.AspNetCore.Localization; @using Oqtane.Models -@inject ILocalizationService LocalizationService +@inject ILanguageService LanguageService @inject NavigationManager NavigationManager @if (_supportedCultures?.Count() > 1) @@ -26,7 +26,8 @@ protected override async Task OnParametersSetAsync() { - _supportedCultures = await LocalizationService.GetCulturesAsync(); + var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId); + _supportedCultures = languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name }); } private async Task SetCultureAsync(string culture) From a2943d083beae73cf45156459d5b483346262cf1 Mon Sep 17 00:00:00 2001 From: hishamco Date: Wed, 13 Jan 2021 18:43:26 +0300 Subject: [PATCH 14/17] Set culture when added language set to current --- .../Modules/Admin/Languages/Add.razor | 18 ++++++++++++++++++ .../Themes/Controls/LanguageSwitcher.razor | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Oqtane.Client/Modules/Admin/Languages/Add.razor b/Oqtane.Client/Modules/Admin/Languages/Add.razor index efd5f22b..02b8e0c2 100644 --- a/Oqtane.Client/Modules/Admin/Languages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Languages/Add.razor @@ -1,6 +1,7 @@ @namespace Oqtane.Modules.Admin.Languages @inherits ModuleBase @using System.Globalization +@using Microsoft.AspNetCore.Localization @inject NavigationManager NavigationManager @inject ILocalizationService LocalizationService @inject ILanguageService LanguageService @@ -65,6 +66,11 @@ { language = await LanguageService.AddLanguageAsync(language); + if (language.IsCurrent) + { + await SetCultureAsync(language.Code); + } + await logger.LogInformation("Language Added {Language}", language); NavigationManager.NavigateTo(NavigateUrl()); @@ -76,4 +82,16 @@ AddModuleMessage(Localizer["Error Adding Language"], MessageType.Error); } } + + private async Task SetCultureAsync(string culture) + { + if (culture != CultureInfo.CurrentUICulture.Name) + { + var interop = new Interop(JSRuntime); + var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)); + await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360); + + NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true); + } + } } diff --git a/Oqtane.Client/Themes/Controls/LanguageSwitcher.razor b/Oqtane.Client/Themes/Controls/LanguageSwitcher.razor index dd92bf15..bd4ac6fc 100644 --- a/Oqtane.Client/Themes/Controls/LanguageSwitcher.razor +++ b/Oqtane.Client/Themes/Controls/LanguageSwitcher.razor @@ -1,7 +1,7 @@ @namespace Oqtane.Themes.Controls @inherits ThemeControlBase @using System.Globalization -@using Microsoft.AspNetCore.Localization; +@using Microsoft.AspNetCore.Localization @using Oqtane.Models @inject ILanguageService LanguageService @inject NavigationManager NavigationManager From 54ff8eced16cd2e641b6db32c3f8ce365a536706 Mon Sep 17 00:00:00 2001 From: hishamco Date: Wed, 13 Jan 2021 23:41:08 +0300 Subject: [PATCH 15/17] Fix the relationship --- Oqtane.Server/Scripts/Tenant.02.00.02.00.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql b/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql index 8eb54714..0e6d04ab 100644 --- a/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql +++ b/Oqtane.Server/Scripts/Tenant.02.00.02.00.sql @@ -21,7 +21,7 @@ CREATE TABLE [dbo].[Language]( ) GO -ALTER TABLE [dbo].[Language] WITH CHECK ADD CONSTRAINT [FK_Language_Tenant] FOREIGN KEY([SiteId]) -REFERENCES [dbo].[Tenant] ([TenantId]) +ALTER TABLE [dbo].[Language] WITH CHECK ADD CONSTRAINT [FK_Language_Site] FOREIGN KEY([SiteId]) +REFERENCES [dbo].[Site] ([SiteId]) ON DELETE CASCADE GO \ No newline at end of file From e938d4f8015a2aa039a67b1df1263fd86732b3c2 Mon Sep 17 00:00:00 2001 From: hishamco Date: Fri, 15 Jan 2021 00:28:59 +0300 Subject: [PATCH 16/17] Add Admins role --- Oqtane.Server/Controllers/LanguageController.cs | 6 ++++-- Oqtane.Server/Repository/SiteRepository.cs | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Oqtane.Server/Controllers/LanguageController.cs b/Oqtane.Server/Controllers/LanguageController.cs index 2b8f7cf0..c63988bb 100644 --- a/Oqtane.Server/Controllers/LanguageController.cs +++ b/Oqtane.Server/Controllers/LanguageController.cs @@ -12,6 +12,8 @@ namespace Oqtane.Controllers [Route(ControllerRoutes.Default)] public class LanguageController : Controller { + private const string HostAdminRoles = RoleNames.Host + "," + RoleNames.Admin; + private readonly ILanguageRepository _languages; private readonly ILogManager _logger; @@ -30,7 +32,7 @@ namespace Oqtane.Controllers public Language Get(int id) => _languages.GetLanguage(id); [HttpPost] - [Authorize(Roles = RoleNames.Admin)] + [Authorize(Roles = HostAdminRoles)] public Language Post([FromBody] Language language) { if (ModelState.IsValid) @@ -42,7 +44,7 @@ namespace Oqtane.Controllers } [HttpDelete("{id}")] - [Authorize(Roles = RoleNames.Admin)] + [Authorize(Roles = HostAdminRoles)] public void Delete(int id) { _languages.DeleteLanguage(id); diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index 64791442..774d0330 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -512,7 +512,9 @@ namespace Oqtane.Repository PagePermissions = new List { new Permission(PermissionNames.View, RoleNames.Host, true), - new Permission(PermissionNames.Edit, RoleNames.Host, true) + new Permission(PermissionNames.Edit, RoleNames.Host, true), + new Permission(PermissionNames.View, RoleNames.Admin, true), + new Permission(PermissionNames.Edit, RoleNames.Admin, true) }.EncodePermissions(), PageTemplateModules = new List { @@ -522,7 +524,9 @@ namespace Oqtane.Repository ModulePermissions = new List { new Permission(PermissionNames.View, RoleNames.Host, true), - new Permission(PermissionNames.Edit, RoleNames.Host, true) + new Permission(PermissionNames.Edit, RoleNames.Host, true), + new Permission(PermissionNames.View, RoleNames.Admin, true), + new Permission(PermissionNames.Edit, RoleNames.Admin, true) }.EncodePermissions(), Content = "" } From bc0ba9230397e3f092455480e7d2e4a80a680df4 Mon Sep 17 00:00:00 2001 From: hishamco Date: Fri, 15 Jan 2021 01:35:53 +0300 Subject: [PATCH 17/17] Revert the changes in the LanguageController --- Oqtane.Server/Controllers/LanguageController.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Oqtane.Server/Controllers/LanguageController.cs b/Oqtane.Server/Controllers/LanguageController.cs index c63988bb..2b8f7cf0 100644 --- a/Oqtane.Server/Controllers/LanguageController.cs +++ b/Oqtane.Server/Controllers/LanguageController.cs @@ -12,8 +12,6 @@ namespace Oqtane.Controllers [Route(ControllerRoutes.Default)] public class LanguageController : Controller { - private const string HostAdminRoles = RoleNames.Host + "," + RoleNames.Admin; - private readonly ILanguageRepository _languages; private readonly ILogManager _logger; @@ -32,7 +30,7 @@ namespace Oqtane.Controllers public Language Get(int id) => _languages.GetLanguage(id); [HttpPost] - [Authorize(Roles = HostAdminRoles)] + [Authorize(Roles = RoleNames.Admin)] public Language Post([FromBody] Language language) { if (ModelState.IsValid) @@ -44,7 +42,7 @@ namespace Oqtane.Controllers } [HttpDelete("{id}")] - [Authorize(Roles = HostAdminRoles)] + [Authorize(Roles = RoleNames.Admin)] public void Delete(int id) { _languages.DeleteLanguage(id);