From 912c01cdf8a95adc75c7150af4c888c4807ea384 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 28 Jan 2026 10:47:39 -0500 Subject: [PATCH] refactorimg Site Groups --- Oqtane.Client/Modules/Admin/Site/Index.razor | 264 ++++++++++-------- .../Resources/Modules/Admin/Site/Index.resx | 28 +- .../Controllers/SiteGroupController.cs | 6 +- .../Infrastructure/Jobs/SynchronizationJob.cs | 93 +++--- .../SiteGroupDefinitionEntityBuilder.cs | 5 +- .../EntityBuilders/SiteGroupEntityBuilder.cs | 6 - .../Tenant/10010001_AddSiteGroups.cs | 1 + .../Repository/SiteGroupRepository.cs | 20 +- Oqtane.Shared/Models/SiteGroup.cs | 10 - Oqtane.Shared/Models/SiteGroupDefinition.cs | 9 +- 10 files changed, 242 insertions(+), 200 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Site/Index.razor b/Oqtane.Client/Modules/Admin/Site/Index.razor index 7e45f3a2..e85de2a2 100644 --- a/Oqtane.Client/Modules/Admin/Site/Index.razor +++ b/Oqtane.Client/Modules/Admin/Site/Index.razor @@ -399,7 +399,7 @@ @foreach (var alias in _aliases) { - + } @if (!_addAlias) @@ -473,69 +473,75 @@ } @if (_siteGroupDefinitionId != -1 || _addSiteGroupDefinition) { - @if (!_addSiteGroupDefinition) - { -
- -
- +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ } + @if (_siteGroupDefinitionId != -1) + { +
+ +
+
+
- } - @if (_member == "Primary") - { -
- -
- -
+
+ } + @if (_siteGroupDefinitionId != -1 && _siteId != -1) + { +
+ +
+
-
- -
- -
-
-
- -
- -
-
- } - @if (_member == "Secondary") - { -
- -
- -
-
-
- -
- -
-
- } +
}
- @if ((_siteGroupDefinitionId != -1 || _addSiteGroupDefinition) && _member != "False") + @if ((_siteGroupDefinitionId != -1 || _addSiteGroupDefinition)) { } @@ -577,7 +583,7 @@
- @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && _siteGroupDefinitions.Any(item => item.PrimarySiteId == PageState.Site.SiteId && item.Synchronization)) + @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && _siteGroupDefinitions.Any(item => item.PrimarySiteId == PageState.Site.SiteId && item.Synchronization != null)) { } @@ -645,26 +651,27 @@ private int _pwasplashiconfileid = -1; private FileManager _pwasplashiconfilemanager; - private List _aliases; - private int _aliasid = -1; - private string _aliasname; - private string _defaultalias; - private bool _addAlias = false; - private string _rendermode = RenderModes.Interactive; private string _enhancednavigation = "True"; private string _runtime = Runtimes.Server; private string _prerender = "True"; private string _hybrid = "False"; - private List _siteGroupDefinitions = new List(); + private List _aliases; + private int _aliasid = -1; + private string _aliasname; + private string _defaultalias; + private bool _addAlias = false; + + private List _siteGroupDefinitions = new List(); + private List _sites = new List(); private int _siteGroupDefinitionId = -1; + private int _siteId = -1; private string _groupName = string.Empty; - private string _member = "Primary"; - private string _synchronization = "True"; - private string _synchronize = "True"; - private string _notifyRoleName = RoleNames.Admin; + private string _synchronization = "Update"; + private string _notify = "True"; private string _localization = "False"; + private string _member = "Primary"; private bool _addSiteGroupDefinition = false; private string _tenant = string.Empty; @@ -1246,36 +1253,80 @@ if (group != null) { _groupName = group.Name; - _member = (group.PrimarySiteId == PageState.Site.SiteId) ? "Primary" : "Secondary"; - _synchronization = group.Synchronization.ToString(); + if (group.Synchronization == null) + { + _synchronization = "False"; + } + else + { + _synchronization = (group.Synchronization.Value) ? "Update" : "Compare"; + } + _notify = group.Notify.ToString(); _localization = group.Localization.ToString(); - } - var siteGroup = await SiteGroupService.GetSiteGroupAsync(PageState.Site.SiteId, _siteGroupDefinitionId); - if (siteGroup != null) - { - _synchronize = siteGroup.Synchronize.ToString(); - _notifyRoleName = siteGroup.NotifyRoleName; - } - else - { + if (_sites.Count == 0) + { + _sites = await SiteService.GetSitesAsync(); + } + _siteId = PageState.Site.SiteId; _member = "False"; - _synchronize = "True"; - _notifyRoleName = RoleNames.Admin; + + var siteGroups = await SiteGroupService.GetSiteGroupsAsync(-1, _siteGroupDefinitionId); + foreach (var site in _sites) + { + site.Fingerprint = ""; // used as temporary state + var siteGroup = siteGroups.FirstOrDefault(item => item.SiteId == site.SiteId); + if (siteGroup != null) + { + if (group.PrimarySiteId == site.SiteId) + { + site.Fingerprint = "Primary"; + } + else + { + site.Fingerprint = "Secondary"; + } + + if (siteGroup.SiteId == _siteId) + { + _member = site.Fingerprint; + } + } + } } } StateHasChanged(); } - private async void MemberChanged(ChangeEventArgs e) + private async void SiteChanged(ChangeEventArgs e) { - _member = e.Value.ToString(); + _siteId = int.Parse(e.Value.ToString()); + if (_siteId != -1) + { + var siteGroup = await SiteGroupService.GetSiteGroupAsync(_siteId, _siteGroupDefinitionId); + if (siteGroup != null) + { + if (siteGroup.SiteGroupDefinition.PrimarySiteId == _siteId) + { + _member = "Primary"; + } + else + { + _member = "Secondary"; + } + } + else + { + _member = "False"; + } + } StateHasChanged(); } private async Task AddSiteGroup() { _groupName = ""; + _siteId = PageState.Site.SiteId; _member = "Primary"; _addSiteGroupDefinition = true; } @@ -1284,6 +1335,10 @@ { SiteGroupDefinition siteGroupDefinition = null; + bool? synchronization = null; + if (_synchronization == "Compare") synchronization = false; + if (_synchronization == "Update") synchronization = true; + if (_siteGroupDefinitionId == -1) { if (!string.IsNullOrEmpty(_groupName)) @@ -1291,8 +1346,9 @@ siteGroupDefinition = new Models.SiteGroupDefinition { Name = _groupName, - PrimarySiteId = PageState.Site.SiteId, - Synchronization = bool.Parse(_synchronization), + PrimarySiteId = _siteId, + Synchronization = synchronization, + Notify = bool.Parse(_notify), Localization = bool.Parse(_localization), Synchronize = false }; @@ -1304,23 +1360,12 @@ siteGroupDefinition = _siteGroupDefinitions.FirstOrDefault(item => item.SiteGroupDefinitionId == _siteGroupDefinitionId); if (siteGroupDefinition != null && !string.IsNullOrEmpty(_groupName)) { - if (_member == "False") - { - var siteGroup = await SiteGroupService.GetSiteGroupAsync(PageState.Site.SiteId, siteGroupDefinition.SiteGroupDefinitionId); - if (siteGroup != null) - { - await SiteGroupService.DeleteSiteGroupAsync(siteGroup.SiteGroupId); - } - siteGroupDefinition = null; - } - else - { - siteGroupDefinition.Name = _groupName; - siteGroupDefinition.PrimarySiteId = (_member == "Primary") ? PageState.Site.SiteId : siteGroupDefinition.PrimarySiteId; - siteGroupDefinition.Synchronization = bool.Parse(_synchronization); - siteGroupDefinition.Localization = bool.Parse(_localization); - siteGroupDefinition = await SiteGroupDefinitionService.UpdateSiteGroupDefinitionAsync(siteGroupDefinition); - } + siteGroupDefinition.Name = _groupName; + siteGroupDefinition.PrimarySiteId = (_member == "Primary") ? _siteId : siteGroupDefinition.PrimarySiteId; + siteGroupDefinition.Synchronization = synchronization; + siteGroupDefinition.Notify = bool.Parse(_notify); + siteGroupDefinition.Localization = bool.Parse(_localization); + siteGroupDefinition = await SiteGroupDefinitionService.UpdateSiteGroupDefinitionAsync(siteGroupDefinition); } else { @@ -1330,23 +1375,22 @@ if (siteGroupDefinition != null) { - var siteGroup = await SiteGroupService.GetSiteGroupAsync(PageState.Site.SiteId, siteGroupDefinition.SiteGroupDefinitionId); + var siteGroup = await SiteGroupService.GetSiteGroupAsync(_siteId, siteGroupDefinition.SiteGroupDefinitionId); if (siteGroup == null) { siteGroup = new SiteGroup { SiteGroupDefinitionId = siteGroupDefinition.SiteGroupDefinitionId, - SiteId = PageState.Site.SiteId, - Synchronize = bool.Parse(_synchronize), - NotifyRoleName= _notifyRoleName + SiteId = _siteId }; await SiteGroupService.AddSiteGroupAsync(siteGroup); } else { - siteGroup.Synchronize = bool.Parse(_synchronize); - siteGroup.NotifyRoleName = _notifyRoleName; - await SiteGroupService.UpdateSiteGroupAsync(siteGroup); + if (_member == "False") + { + await SiteGroupService.DeleteSiteGroupAsync(siteGroup.SiteGroupId); + } } await LoadSiteGroups(); @@ -1396,7 +1440,7 @@ } // mark secondary sites for synchronization - foreach (var group in _siteGroupDefinitions.Where(item => item.PrimarySiteId == PageState.Site.SiteId && item.Synchronization)) + foreach (var group in _siteGroupDefinitions.Where(item => item.PrimarySiteId == PageState.Site.SiteId && item.Synchronization != null)) { group.Synchronize = true; await SiteGroupDefinitionService.UpdateSiteGroupDefinitionAsync(group); diff --git a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx index 380e951a..e7efa0bb 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx @@ -327,8 +327,8 @@ Url: - - Default? + + Default Are You Sure You Wish To Delete {0}? @@ -540,18 +540,6 @@ Update - - Synchronization: - - - Specifies the synchronization approach from the primary site to the current site - - - Notify Role: - - - Optionally specifies a role in the current site whose users should be notified of content changes in the primary site - Delete Site Group @@ -567,4 +555,16 @@ Synchronize + + Notify? + + + Specifies if the site administrator of secondary sites should be notified of any synchronization activity + + + Site: + + + he sites in this tenant (database) + \ No newline at end of file diff --git a/Oqtane.Server/Controllers/SiteGroupController.cs b/Oqtane.Server/Controllers/SiteGroupController.cs index e59f57d8..62441495 100644 --- a/Oqtane.Server/Controllers/SiteGroupController.cs +++ b/Oqtane.Server/Controllers/SiteGroupController.cs @@ -110,12 +110,12 @@ namespace Oqtane.Controllers if (siteGroup != null) { _siteGroupRepository.DeleteSiteGroup(id); - _syncManager.AddSyncEvent(_alias, EntityNames.SiteGroup, siteGroup.SiteGroupDefinitionId, SyncEventActions.Delete); - _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Site Group Deleted {SiteGroupDefinitionId}", id); + _syncManager.AddSyncEvent(_alias, EntityNames.SiteGroup, siteGroup.SiteGroupId, SyncEventActions.Delete); + _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Site Group Deleted {SiteGroupId}", id); } else { - _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Delete Attempt {SiteGroupDefinitionId}", id); + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Delete Attempt {SiteGroupId}", id); HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; } } diff --git a/Oqtane.Server/Infrastructure/Jobs/SynchronizationJob.cs b/Oqtane.Server/Infrastructure/Jobs/SynchronizationJob.cs index 8ca7f7a5..7c3a0d8c 100644 --- a/Oqtane.Server/Infrastructure/Jobs/SynchronizationJob.cs +++ b/Oqtane.Server/Infrastructure/Jobs/SynchronizationJob.cs @@ -53,7 +53,7 @@ namespace Oqtane.Infrastructure var groups = siteGroupDefinitionRepository.GetSiteGroupDefinitions(); // iterate through groups which need to be synchronized - foreach (var group in groups.Where(item => item.Synchronize)) + foreach (var group in groups.Where(item => item.Synchronization != null && item.Synchronize)) { // get data if (siteGroups == null) @@ -64,7 +64,7 @@ namespace Oqtane.Infrastructure } var aliasName = "https://" + aliases.First(item => item.TenantId == tenantManager.GetTenant().TenantId && item.SiteId == group.PrimarySiteId && item.IsDefault).Name; - log += $"Processing Primary Site: {sites.First(item => item.SiteId == group.PrimarySiteId).Name} - {aliasName}
"; + log += $"Processing Primary Site: {sites.First(item => item.SiteId == group.PrimarySiteId).Name} - {CreateLink(aliasName)}
"; // get primary site var primarySite = sites.FirstOrDefault(item => item.SiteId == group.PrimarySiteId); @@ -97,17 +97,17 @@ namespace Oqtane.Infrastructure siteGroup.SynchronizedOn = DateTime.UtcNow; siteGroupRepository.UpdateSiteGroup(siteGroup); - log += $"Processed Target Site: {secondarySite.Name} - {siteGroup.AliasName}
" + siteLog; + log += $"Processed Secondary Site: {secondarySite.Name} - {CreateLink(siteGroup.AliasName)}
" + siteLog; } else { - log += $"Site Group Has A SiteId {siteGroup.SiteId} Which Does Not Exist
"; + log += $"Site Group {group.Name} Has A SiteId {siteGroup.SiteId} Which Does Not Exist
"; } } } else { - log += $"Site Group Has A PrimarySiteId {group.PrimarySiteId} Which Does Not Exist
"; + log += $"Site Group {group.Name} Has A PrimarySiteId {group.PrimarySiteId} Which Does Not Exist
"; } } @@ -177,7 +177,7 @@ namespace Oqtane.Infrastructure secondarySite.DeletedOn = primarySite.DeletedOn; var siteRepository = provider.GetRequiredService(); - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { siteRepository.UpdateSite(secondarySite); } @@ -195,10 +195,10 @@ namespace Oqtane.Infrastructure syncManager.AddSyncEvent(alias, EntityNames.Site, secondarySite.SiteId, SyncEventActions.Refresh); } - if (!string.IsNullOrEmpty(log) && !string.IsNullOrEmpty(siteGroup.NotifyRoleName)) + if (!string.IsNullOrEmpty(log) && siteGroup.SiteGroupDefinition.Notify) { - // send change log to users in role - SendNotifications(provider, secondarySite.SiteId, secondarySite.Name, siteGroup.NotifyRoleName, log); + // send change log to administrators + SendNotifications(provider, secondarySite.SiteId, secondarySite.Name, log); } return log; @@ -244,7 +244,7 @@ namespace Oqtane.Infrastructure if (role == null) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { roleRepository.AddRole(secondaryRole); } @@ -252,7 +252,7 @@ namespace Oqtane.Infrastructure } else { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { roleRepository.UpdateRole(secondaryRole); } @@ -265,7 +265,7 @@ namespace Oqtane.Infrastructure // remove roles in the secondary site which do not exist in the primary site foreach (var secondaryRole in secondaryRoles.Where(item => !primaryRoles.Select(item => item.Name).Contains(item.Name))) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { roleRepository.DeleteRole(secondaryRole.RoleId); } @@ -323,7 +323,7 @@ namespace Oqtane.Infrastructure if (folder == null) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { folderRepository.AddFolder(secondaryFolder); } @@ -331,7 +331,7 @@ namespace Oqtane.Infrastructure } else { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { folderRepository.UpdateFolder(secondaryFolder); } @@ -370,21 +370,21 @@ namespace Oqtane.Infrastructure if (file == null) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { fileRepository.AddFile(secondaryFile); ReplicateFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile); } - log += Log(siteGroup, $"File Added: {siteGroup.AliasName}{secondaryFolder.Path}{secondaryFile.Name}"); + log += Log(siteGroup, $"File Added: {CreateLink(siteGroup.AliasName + secondaryFolder.Path + secondaryFile.Name)}"); } else { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { fileRepository.UpdateFile(secondaryFile); ReplicateFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile); } - log += Log(siteGroup, $"File Updated: {siteGroup.AliasName}{secondaryFolder.Path}{secondaryFile.Name}"); + log += Log(siteGroup, $"File Updated: {CreateLink(siteGroup.AliasName + secondaryFolder.Path + secondaryFile.Name)}"); secondaryFiles.Remove(file); } } @@ -393,20 +393,20 @@ namespace Oqtane.Infrastructure // remove files in the secondary site which do not exist in the primary site foreach (var secondaryFile in secondaryFiles.Where(item => !primaryFiles.Select(item => item.Name).Contains(item.Name))) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { fileRepository.DeleteFile(secondaryFile.FileId); var secondaryPath = Path.Combine(folderRepository.GetFolderPath(secondaryFolder), secondaryFile.Name); System.IO.File.Delete(secondaryPath); } - log += Log(siteGroup, $"File Deleted: {siteGroup.AliasName}{secondaryFolder.Path}{secondaryFile.Name}"); + log += Log(siteGroup, $"File Deleted: {CreateLink(siteGroup.AliasName + secondaryFolder.Path + secondaryFile.Name)}"); } } // remove folders in the secondary site which do not exist in the primary site foreach (var secondaryFolder in secondaryFolders.Where(item => !primaryFolders.Select(item => item.Path).Contains(item.Path))) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { folderRepository.DeleteFolder(secondaryFolder.FolderId); } @@ -490,19 +490,19 @@ namespace Oqtane.Infrastructure if (page == null) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { secondaryPage = pageRepository.AddPage(secondaryPage); } - log += Log(siteGroup, $"Page Added: {siteGroup.AliasName}{secondaryPage.Path}"); + log += Log(siteGroup, $"Page Added: {CreateLink(siteGroup.AliasName + secondaryPage.Path)}"); } else { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { secondaryPage = pageRepository.UpdatePage(secondaryPage); } - log += Log(siteGroup, $"Page Updated: {siteGroup.AliasName}{secondaryPage.Path}"); + log += Log(siteGroup, $"Page Updated: {CreateLink(siteGroup.AliasName + secondaryPage.Path)}"); secondaryPages.Remove(page); } } @@ -558,22 +558,22 @@ namespace Oqtane.Infrastructure if (module == null) { // add new module - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { module = moduleRepository.AddModule(secondaryPageModule.Module); updateContent = true; } - log += Log(siteGroup, $"Module Added: {module.Title} - {siteGroup.AliasName}{secondaryPage.Path}"); + log += Log(siteGroup, $"Module Added: {module.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}"); } if (module != null) { secondaryPageModule.ModuleId = module.ModuleId; secondaryPageModule.Module = null; // remove tracking - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { secondaryPageModule = pageModuleRepository.AddPageModule(secondaryPageModule); } - log += Log(siteGroup, $"Page Module Added: {module.Title} - {siteGroup.AliasName}{secondaryPage.Path}"); + log += Log(siteGroup, $"Page Module Added: {module.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}"); secondaryPageModule.Module = module; } } @@ -582,20 +582,20 @@ namespace Oqtane.Infrastructure // update existing module if (primaryPageModule.Module.ModifiedOn > siteGroup.SynchronizedOn) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { moduleRepository.UpdateModule(secondaryPageModule.Module); updateContent = true; } - log += Log(siteGroup, $"Module Updated: {secondaryPageModule.Title} - {siteGroup.AliasName}{secondaryPage.Path}"); + log += Log(siteGroup, $"Module Updated: {secondaryPageModule.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}"); } if (primaryPageModule.ModifiedOn > siteGroup.SynchronizedOn) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { secondaryPageModule = pageModuleRepository.UpdatePageModule(secondaryPageModule); } - log += Log(siteGroup, $"Page Module Updated: {secondaryPageModule.Title} - {siteGroup.AliasName}{secondaryPage.Path}"); + log += Log(siteGroup, $"Page Module Updated: {secondaryPageModule.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}"); secondaryPageModules.Remove(pageModule); } } @@ -613,11 +613,11 @@ namespace Oqtane.Infrastructure var secondaryModuleContent = ((ISynchronizable)moduleObject).ExtractModule(secondaryPageModule.Module); if (primaryModuleContent != secondaryModuleContent) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { ((ISynchronizable)moduleObject).LoadModule(secondaryPageModule.Module, primaryModuleContent, primaryPageModule.Module.ModuleDefinition.Version); } - log += Log(siteGroup, $"Module Content Updated: {secondaryPageModule.Title} - {siteGroup.AliasName}{secondaryPage.Path}"); + log += Log(siteGroup, $"Module Content Updated: {secondaryPageModule.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}"); } } catch @@ -648,22 +648,22 @@ namespace Oqtane.Infrastructure } if (!primaryPageModules.Any(item => item.PageId == primaryPageId && item.Module.ModuleDefinitionName == secondaryPageModule.Module.ModuleDefinitionName && item.Title.ToLower() == secondaryPageModule.Title.ToLower())) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { pageModuleRepository.DeletePageModule(secondaryPageModule.PageModuleId); } - log += Log(siteGroup, $"Page Module Deleted: {secondaryPageModule.Title} - {siteGroup.AliasName}{secondaryPageModule.Page.Path}"); + log += Log(siteGroup, $"Page Module Deleted: {secondaryPageModule.Title} - {CreateLink(siteGroup.AliasName + secondaryPageModule.Page.Path)}"); } } // remove pages in the secondary site which do not exist in the primary site foreach (var secondaryPage in secondaryPages.Where(item => !primaryPages.Select(item => item.Path).Contains(item.Path))) { - if (siteGroup.Synchronize) + if (siteGroup.SiteGroupDefinition.Synchronization.Value) { pageRepository.DeletePage(secondaryPage.PageId); } - log += Log(siteGroup, $"Page Deleted: {siteGroup.AliasName}{secondaryPage.Path}"); + log += Log(siteGroup, $"Page Deleted: {CreateLink(siteGroup.AliasName + secondaryPage.Path)}"); } if (siteGroup.SynchronizedOn == DateTime.MinValue || !string.IsNullOrEmpty(log)) @@ -710,7 +710,7 @@ namespace Oqtane.Infrastructure secondarySetting.SettingName = primarySetting.SettingName; secondarySetting.SettingValue = primarySetting.SettingValue; secondarySetting.IsPrivate = primarySetting.IsPrivate; - if (siteGroup.Synchronize && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName)) + if (siteGroup.SiteGroupDefinition.Synchronization.Value && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName)) { settingRepository.AddSetting(secondarySetting); updated = true; @@ -722,7 +722,7 @@ namespace Oqtane.Infrastructure { secondarySetting.SettingValue = primarySetting.SettingValue; secondarySetting.IsPrivate = primarySetting.IsPrivate; - if (siteGroup.Synchronize && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName)) + if (siteGroup.SiteGroupDefinition.Synchronization.Value && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName)) { settingRepository.UpdateSetting(secondarySetting); updated = true; @@ -735,7 +735,7 @@ namespace Oqtane.Infrastructure // any remaining secondary settings need to be deleted foreach (var secondarySetting in secondarySettings) { - if (siteGroup.Synchronize && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName)) + if (siteGroup.SiteGroupDefinition.Synchronization.Value && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName)) { settingRepository.DeleteSetting(secondarySetting.EntityName, secondarySetting.SettingId); updated = true; @@ -750,12 +750,12 @@ namespace Oqtane.Infrastructure return log; } - private void SendNotifications(IServiceProvider provider, int siteId, string siteName, string roleName, string log) + private void SendNotifications(IServiceProvider provider, int siteId, string siteName, string log) { var userRoleRepository = provider.GetRequiredService(); var notificationRepository = provider.GetRequiredService(); - foreach (var userRole in userRoleRepository.GetUserRoles(roleName, siteId)) + foreach (var userRole in userRoleRepository.GetUserRoles(RoleNames.Admin, siteId)) { var notification = new Notification(siteId, userRole.User, $"{siteName} Change Log", log); notificationRepository.AddNotification(notification); @@ -774,5 +774,10 @@ namespace Oqtane.Infrastructure return ""; } } + + private string CreateLink(string url) + { + return "" + url + ""; + } } } diff --git a/Oqtane.Server/Migrations/EntityBuilders/SiteGroupDefinitionEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/SiteGroupDefinitionEntityBuilder.cs index 72974ecb..180e896d 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/SiteGroupDefinitionEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/SiteGroupDefinitionEntityBuilder.cs @@ -24,7 +24,8 @@ namespace Oqtane.Migrations.EntityBuilders SiteGroupDefinitionId = AddAutoIncrementColumn(table, "SiteGroupDefinitionId"); Name = AddStringColumn(table, "Name", 200); PrimarySiteId = AddIntegerColumn(table, "PrimarySiteId"); - Synchronization = AddBooleanColumn(table, "Synchronization"); + Synchronization = AddBooleanColumn(table, "Synchronization", true); + Notify = AddBooleanColumn(table, "Notify"); Synchronize = AddBooleanColumn(table, "Synchronize"); Localization = AddBooleanColumn(table, "Localization"); @@ -41,6 +42,8 @@ namespace Oqtane.Migrations.EntityBuilders public OperationBuilder Synchronization { get; set; } + public OperationBuilder Notify { get; set; } + public OperationBuilder Synchronize { get; set; } public OperationBuilder Localization { get; set; } diff --git a/Oqtane.Server/Migrations/EntityBuilders/SiteGroupEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/SiteGroupEntityBuilder.cs index ed063737..e9e385ce 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/SiteGroupEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/SiteGroupEntityBuilder.cs @@ -28,8 +28,6 @@ namespace Oqtane.Migrations.EntityBuilders SiteGroupId = AddAutoIncrementColumn(table, "SiteGroupId"); SiteGroupDefinitionId = AddIntegerColumn(table, "SiteGroupDefinitionId"); SiteId = AddIntegerColumn(table, "SiteId"); - Synchronize = AddBooleanColumn(table, "Synchronize"); - NotifyRoleName = AddStringColumn(table, "NotifyRoleName", 256, true); SynchronizedOn = AddDateTimeColumn(table, "SynchronizedOn", true); AddAuditableColumns(table); @@ -43,10 +41,6 @@ namespace Oqtane.Migrations.EntityBuilders public OperationBuilder SiteId { get; set; } - public OperationBuilder Synchronize { get; set; } - - public OperationBuilder NotifyRoleName { get; set; } - public OperationBuilder SynchronizedOn { get; set; } } } diff --git a/Oqtane.Server/Migrations/Tenant/10010001_AddSiteGroups.cs b/Oqtane.Server/Migrations/Tenant/10010001_AddSiteGroups.cs index 42255ce8..a8e767c2 100644 --- a/Oqtane.Server/Migrations/Tenant/10010001_AddSiteGroups.cs +++ b/Oqtane.Server/Migrations/Tenant/10010001_AddSiteGroups.cs @@ -21,6 +21,7 @@ namespace Oqtane.Migrations.Tenant var siteGroupEntityBuilder = new SiteGroupEntityBuilder(migrationBuilder, ActiveDatabase); siteGroupEntityBuilder.Create(); + siteGroupEntityBuilder.AddIndex("IX_SiteGroup", new[] { "SiteId", "SiteGroupDefinitionId" }, true); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/Oqtane.Server/Repository/SiteGroupRepository.cs b/Oqtane.Server/Repository/SiteGroupRepository.cs index 644cec0c..392f83e7 100644 --- a/Oqtane.Server/Repository/SiteGroupRepository.cs +++ b/Oqtane.Server/Repository/SiteGroupRepository.cs @@ -11,9 +11,9 @@ namespace Oqtane.Repository IEnumerable GetSiteGroups(int siteId, int siteGroupDefinitionId); SiteGroup AddSiteGroup(SiteGroup siteGroup); SiteGroup UpdateSiteGroup(SiteGroup siteGroup); - SiteGroup GetSiteGroup(int siteSiteGroupDefinitionId); - SiteGroup GetSiteGroup(int siteSiteGroupDefinitionId, bool tracking); - void DeleteSiteGroup(int siteSiteGroupDefinitionId); + SiteGroup GetSiteGroup(int siteSiteGroupId); + SiteGroup GetSiteGroup(int siteSiteGroupId, bool tracking); + void DeleteSiteGroup(int siteSiteGroupId); } public class SiteGroupRepository : ISiteGroupRepository @@ -55,32 +55,32 @@ namespace Oqtane.Repository return SiteGroup; } - public SiteGroup GetSiteGroup(int SiteGroupDefinitionId) + public SiteGroup GetSiteGroup(int SiteGroupId) { - return GetSiteGroup(SiteGroupDefinitionId, true); + return GetSiteGroup(SiteGroupId, true); } - public SiteGroup GetSiteGroup(int SiteGroupDefinitionId, bool tracking) + public SiteGroup GetSiteGroup(int SiteGroupId, bool tracking) { using var db = _dbContextFactory.CreateDbContext(); if (tracking) { return db.SiteGroup .Include(item => item.SiteGroupDefinition) // eager load - .FirstOrDefault(item => item.SiteGroupDefinitionId == SiteGroupDefinitionId); + .FirstOrDefault(item => item.SiteGroupId == SiteGroupId); } else { return db.SiteGroup.AsNoTracking() .Include(item => item.SiteGroupDefinition) // eager load - .FirstOrDefault(item => item.SiteGroupDefinitionId == SiteGroupDefinitionId); + .FirstOrDefault(item => item.SiteGroupId == SiteGroupId); } } - public void DeleteSiteGroup(int SiteGroupDefinitionId) + public void DeleteSiteGroup(int SiteGroupId) { using var db = _dbContextFactory.CreateDbContext(); - SiteGroup SiteGroup = db.SiteGroup.Find(SiteGroupDefinitionId); + SiteGroup SiteGroup = db.SiteGroup.Find(SiteGroupId); db.SiteGroup.Remove(SiteGroup); db.SaveChanges(); } diff --git a/Oqtane.Shared/Models/SiteGroup.cs b/Oqtane.Shared/Models/SiteGroup.cs index dffc30b6..2668f55e 100644 --- a/Oqtane.Shared/Models/SiteGroup.cs +++ b/Oqtane.Shared/Models/SiteGroup.cs @@ -20,16 +20,6 @@ namespace Oqtane.Models /// public int SiteId { get; set; } - /// - /// Indicates if content should be synchronized for the site (false = compare, true = update) - /// - public bool Synchronize { get; set; } - - /// - /// The role who should be notified of changes to the site (non-primary site only) - /// - public string NotifyRoleName { get; set; } - /// /// The last date/time the site was synchronized /// diff --git a/Oqtane.Shared/Models/SiteGroupDefinition.cs b/Oqtane.Shared/Models/SiteGroupDefinition.cs index 8436ed68..a5e91a7b 100644 --- a/Oqtane.Shared/Models/SiteGroupDefinition.cs +++ b/Oqtane.Shared/Models/SiteGroupDefinition.cs @@ -18,9 +18,14 @@ namespace Oqtane.Models public int PrimarySiteId { get; set; } /// - /// Indicates if the group supports synchronization + /// Indicates if the group supports synchronization (null = no, false = compare, true = update) /// - public bool Synchronization { get; set; } + public bool? Synchronization { get; set; } + + /// + /// Indicates if the site administrator should be notified of any synchronization activity + /// + public bool Notify { get; set; } /// /// Specifies if the group needs to be synchronized