diff --git a/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.html b/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.html index 8727315..c6e3c82 100644 --- a/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.html +++ b/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.html @@ -38,16 +38,18 @@

Import redirects from CSV file

- + + +
diff --git a/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.js b/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.js index 73a9e97..6bbe582 100644 --- a/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.js +++ b/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.js @@ -58,6 +58,7 @@ define("redirectsMenu/RedirectsMenu", [ on(this.deleteButton, "click", this._onDeleteClick.bind(this)); on(this.refreshButton, "click", this._refreshView.bind(this)); on(this.clearAllButton, "click", this._onClearAllClick.bind(this)); + on(this.removeDuplicatesButton, "click", this._onRemoveDuplicatesClick.bind(this)); /*on(this.simulateFindButton, "click", this._onSimulateFindClick.bind(this)); on(this.simulateResetButton, "click", this._onSimulateResetClick.bind(this));*/ on(this.uploadFormSubmit, "click", this._onImportSubmit.bind(this)); @@ -130,6 +131,17 @@ define("redirectsMenu/RedirectsMenu", [ } }, + _onRemoveDuplicatesClick: function() { + if (window.confirm("Do you really want to remove all duplicates?")) { + var removeDuplicatesStatus = this.removeDuplicatesStatus; + removeDuplicatesStatus.innerText = "Removing duplicates..."; + this.redirectsMenuViewModel.removeDuplicateRules().then((r) => { + removeDuplicatesStatus.innerText = "Duplicates removed."; + this._refreshView() + }); + } + }, + _onEditClick: function () { if (this.selectedModel.redirectRuleType === "System") return; diff --git a/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenuViewModel.js b/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenuViewModel.js index 56f936a..8b564e4 100644 --- a/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenuViewModel.js +++ b/AlloyDemoKit/modules/_protected/Forte.EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenuViewModel.js @@ -6,6 +6,8 @@ ], function (declare, Stateful, dependency) { var clearAllGuid = "00000000-0000-0000-0000-000000000000"; + var clearAllDuplicatesGuid = "00000000-0000-0000-0000-000000000001"; + return declare([Stateful], { store: null, @@ -64,6 +66,10 @@ clearRedirectRules: function() { return this.store.remove(clearAllGuid); + }, + + removeDuplicateRules: function () { + return this.store.remove(clearAllDuplicatesGuid); } }); }); diff --git a/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.html b/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.html index 8727315..c6e3c82 100644 --- a/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.html +++ b/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.html @@ -38,16 +38,18 @@

Import redirects from CSV file

- + + +
diff --git a/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.js b/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.js index 73a9e97..6bbe582 100644 --- a/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.js +++ b/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenu.js @@ -58,6 +58,7 @@ define("redirectsMenu/RedirectsMenu", [ on(this.deleteButton, "click", this._onDeleteClick.bind(this)); on(this.refreshButton, "click", this._refreshView.bind(this)); on(this.clearAllButton, "click", this._onClearAllClick.bind(this)); + on(this.removeDuplicatesButton, "click", this._onRemoveDuplicatesClick.bind(this)); /*on(this.simulateFindButton, "click", this._onSimulateFindClick.bind(this)); on(this.simulateResetButton, "click", this._onSimulateResetClick.bind(this));*/ on(this.uploadFormSubmit, "click", this._onImportSubmit.bind(this)); @@ -130,6 +131,17 @@ define("redirectsMenu/RedirectsMenu", [ } }, + _onRemoveDuplicatesClick: function() { + if (window.confirm("Do you really want to remove all duplicates?")) { + var removeDuplicatesStatus = this.removeDuplicatesStatus; + removeDuplicatesStatus.innerText = "Removing duplicates..."; + this.redirectsMenuViewModel.removeDuplicateRules().then((r) => { + removeDuplicatesStatus.innerText = "Duplicates removed."; + this._refreshView() + }); + } + }, + _onEditClick: function () { if (this.selectedModel.redirectRuleType === "System") return; diff --git a/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenuViewModel.js b/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenuViewModel.js index 56f936a..8b564e4 100644 --- a/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenuViewModel.js +++ b/EpiserverRedirects/ClientResources/RedirectsMenu/RedirectsMenuViewModel.js @@ -6,6 +6,8 @@ ], function (declare, Stateful, dependency) { var clearAllGuid = "00000000-0000-0000-0000-000000000000"; + var clearAllDuplicatesGuid = "00000000-0000-0000-0000-000000000001"; + return declare([Stateful], { store: null, @@ -64,6 +66,10 @@ clearRedirectRules: function() { return this.store.remove(clearAllGuid); + }, + + removeDuplicateRules: function () { + return this.store.remove(clearAllDuplicatesGuid); } }); }); diff --git a/EpiserverRedirects/Menu/RedirectRuleStore.cs b/EpiserverRedirects/Menu/RedirectRuleStore.cs index 492dcfd..d244c66 100644 --- a/EpiserverRedirects/Menu/RedirectRuleStore.cs +++ b/EpiserverRedirects/Menu/RedirectRuleStore.cs @@ -15,6 +15,7 @@ public class RedirectRuleStore : RestControllerBase private readonly IRedirectRuleRepository _redirectRuleRepository; private readonly IRedirectRuleMapper _redirectRuleMapper; private readonly Guid _clearAllGuid = Guid.Parse("00000000-0000-0000-0000-000000000000"); + private readonly Guid _clearAllDuplicatesGuid = Guid.Parse("00000000-0000-0000-0000-000000000001"); public RedirectRuleStore(IRedirectRuleRepository redirectRuleRepository, IRedirectRuleMapper redirectRuleMapper) { @@ -77,9 +78,17 @@ public ActionResult Put(RedirectRuleDto dto) [HttpDelete] public ActionResult Delete(Guid id) { - var deletedSuccessfully = id == _clearAllGuid - ? _redirectRuleRepository.ClearAll() - : _redirectRuleRepository.Delete(id); + bool deletedSuccessfully; + + if (id == _clearAllGuid) { + deletedSuccessfully = _redirectRuleRepository.ClearAll(); + } + else if(id == _clearAllDuplicatesGuid) { + deletedSuccessfully = _redirectRuleRepository.RemoveAllDuplicates(); + } + else { + deletedSuccessfully = _redirectRuleRepository.Delete(id); + } return deletedSuccessfully ? Rest(HttpStatusCode.OK) diff --git a/EpiserverRedirects/Repository/DynamicDataStoreRepository.cs b/EpiserverRedirects/Repository/DynamicDataStoreRepository.cs index d98178f..00277ea 100644 --- a/EpiserverRedirects/Repository/DynamicDataStoreRepository.cs +++ b/EpiserverRedirects/Repository/DynamicDataStoreRepository.cs @@ -10,7 +10,31 @@ public class DynamicDataStoreRepository : RedirectRuleRepository private readonly DynamicDataStoreFactory _dynamicDataStoreFactory; private DynamicDataStore DynamicDataStore => _dynamicDataStoreFactory.CreateStore(typeof(RedirectRule)); + private IQueryable GetAllByOldPattern(string oldPattern) + { + return DynamicDataStore.Items().Where(x => x.OldPattern == oldPattern); + } + private IQueryable RemoveDuplicates(RedirectRule redirectRule) + { + var oldPatternRedirectRules = + GetAllByOldPattern(redirectRule.OldPattern) + .Where(x => x.RedirectRuleType != RedirectRuleType.Regex) + .OrderByDescending(x => x.CreatedOn); + + IQueryable duplicates = null; + + if (oldPatternRedirectRules.Count() > 1) + { + duplicates = oldPatternRedirectRules.Skip(1); + + foreach (var duplicate in duplicates) + { + Delete(duplicate.Id.ExternalId); + } + } + return duplicates; + } public DynamicDataStoreRepository(DynamicDataStoreFactory dynamicDataStoreFactory) { _dynamicDataStoreFactory = dynamicDataStoreFactory; @@ -27,8 +51,10 @@ public override RedirectRule GetById(Guid id) } public override RedirectRule Add(RedirectRule redirectRule) - { + { DynamicDataStore.Save(redirectRule); + RemoveDuplicates(redirectRule); + return redirectRule; } @@ -46,6 +72,24 @@ public override RedirectRule Update(RedirectRule redirectRule) return redirectRuleToUpdate; } + public override bool RemoveAllDuplicates() + { + var redirectRules = GetAll(); + + try + { + foreach (var redirectRule in redirectRules) + { + RemoveDuplicates(redirectRule); + } + return true; + } + catch + { + return false; + } + } + public override bool Delete(Guid id) { try diff --git a/EpiserverRedirects/Repository/RedirectRuleCachedRepositoryDecorator.cs b/EpiserverRedirects/Repository/RedirectRuleCachedRepositoryDecorator.cs index 9922907..e5a41cf 100644 --- a/EpiserverRedirects/Repository/RedirectRuleCachedRepositoryDecorator.cs +++ b/EpiserverRedirects/Repository/RedirectRuleCachedRepositoryDecorator.cs @@ -45,6 +45,8 @@ public IQueryable GetAll() public RedirectRule Update(RedirectRule redirectRule) => _redirectRuleRepository.Update(redirectRule); + public bool RemoveAllDuplicates() => _redirectRuleRepository.RemoveAllDuplicates(); + public bool Delete(Guid id) => _redirectRuleRepository.Delete(id); public bool ClearAll() => _redirectRuleRepository.ClearAll(); diff --git a/EpiserverRedirects/Repository/Repository.cs b/EpiserverRedirects/Repository/Repository.cs index 023c165..7758bfa 100644 --- a/EpiserverRedirects/Repository/Repository.cs +++ b/EpiserverRedirects/Repository/Repository.cs @@ -10,6 +10,7 @@ public interface IRedirectRuleRepository IQueryable GetAll(); RedirectRule Add(RedirectRule redirectRule); RedirectRule Update(RedirectRule redirectRule); + bool RemoveAllDuplicates(); bool Delete(Guid id); bool ClearAll(); } @@ -20,6 +21,7 @@ public abstract class RedirectRuleRepository : IRedirectRuleRepository public abstract IQueryable GetAll(); public abstract RedirectRule Add(RedirectRule redirectRule); public abstract RedirectRule Update(RedirectRule redirectRule); + public abstract bool RemoveAllDuplicates(); public abstract bool Delete(Guid id); public abstract bool ClearAll();