+
+
+
+
+
+
+
+
+ {{vm.getTypeName(result.ItemType)}}
+
+
+ {{result.Name}}
+
+
+ {{result.Change}}
+
+
+ {{result.Message}}
+
+
+
+
+ ({{result.Details.length}} items)
-
-
-
-
- {{detail.Name}}
-
-
- {{detail.OldValue}}
-
-
- {{detail.NewValue}}
+
+
+
+
+
+
+
Action
+
Item
+
Old Value
+
New Value
-
- {{detail.Change}}
+
+
+
+
+
+
+
+
+
+
+ {{detail.Change}}
+
+
+ {{detail.Name}}
+
+
+ {{detail.OldValue}}
+
+
+ {{detail.NewValue}}
+
@@ -157,20 +179,113 @@
{{vm.status.Message}}
-
-
-
No Changes
-
-
-
+
+
No Changes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Import at startup
+
Run an import of files from the disk when Umbraco starts
+
+
+
+
+
+
+
+
Export at startup
+
Export the Umbraco settings when the site starts up
+
+
-
+
+
+
+
+
Export on Save
+
Generate uSync files when items are saved
+
+
+
+
+
+
+
+
+
+
+
+
+
Flat structure
+
All items of a type are stored in a flat folder strucure
+
+
+
+
+
+
+
use Guids for filenames
+
use the guid of an item as the filename
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{handler.Alias}}
+
+
Enabled for : {{handler.Actions}}
+
+
+
+
+
+
+
diff --git a/uSync8.BackOffice/App_Plugins/uSync8/lang/en-US.xml b/uSync8.BackOffice/App_Plugins/uSync8/lang/en-US.xml
index 83dc70be..829e9912 100644
--- a/uSync8.BackOffice/App_Plugins/uSync8/lang/en-US.xml
+++ b/uSync8.BackOffice/App_Plugins/uSync8/lang/en-US.xml
@@ -9,11 +9,13 @@
Database elements to and from disk
Import
+
Full Import
Report
Export
Details
Item Handlers
+
Save Settings
\ No newline at end of file
diff --git a/uSync8.BackOffice/App_Plugins/uSync8/uSyncDashboardController.js b/uSync8.BackOffice/App_Plugins/uSync8/uSyncDashboardController.js
index caba3f5e..5dbed382 100644
--- a/uSync8.BackOffice/App_Plugins/uSync8/uSyncDashboardController.js
+++ b/uSync8.BackOffice/App_Plugins/uSync8/uSyncDashboardController.js
@@ -31,6 +31,7 @@
vm.runmode = modes.NONE;
vm.showAll = false;
+ vm.settingsView = false;
vm.settings = {};
vm.handlers = [];
@@ -38,17 +39,38 @@
vm.reportAction = '';
+ // buttons
+
+ vm.importButton = {
+ state: 'init',
+ defaultButton: {
+ labelKey: "usync_import",
+ handler: importItems
+ },
+ subButtons: [{
+ labelKey: "usync_importforce",
+ handler: importForce
+ }]
+ };
+
+
// functions
vm.report = report;
vm.exportItems = exportItems;
+ vm.importForce = importForce;
vm.importItems = importItems;
+ vm.saveSettings = saveSettings;
+
vm.toggleDetails = toggleDetails;
vm.getTypeName = getTypeName;
vm.toggleAll = toggleAll;
vm.countChanges = countChanges;
vm.calcPercentage = calcPercentage;
+ vm.toggleSettings = toggleSettings;
+ vm.toggle = toggle;
+
vm.showChange = showChange;
// kick it all off
@@ -80,14 +102,35 @@
});
}
+ function importForce() {
+ importItems(true);
+ }
+
function importItems(force) {
resetStatus(modes.IMPORT);
+ vm.importButton.state = 'busy';
uSync8DashboardService.importItems(force, getClientId())
.then(function (result) {
vm.results = result.data;
vm.working = false;
vm.reported = true;
+ vm.importButton.state = 'success';
+ }, function (error) {
+ vm.importButton.state = 'error';
+ notificationsService.error('Failed', error.data.ExceptionMessage);
+
+ vm.working = false;
+ vm.reported = true;
+ });
+ }
+
+ function saveSettings() {
+ vm.working = false;
+ uSync8DashboardService.saveSettings(vm.settings)
+ .then(function (result) {
+ vm.working = false;
+ notificationsService.success('Saved', 'Settings updated');
});
}
@@ -124,6 +167,14 @@
return (100 * status.Processed) / status.TotalSteps;
}
+ function toggle(item) {
+ item = !item;
+ }
+
+ function toggleSettings() {
+ vm.settingsView = !vm.settingsView;
+ }
+
////// private
function init() {
diff --git a/uSync8.BackOffice/App_Plugins/uSync8/uSyncService.js b/uSync8.BackOffice/App_Plugins/uSync8/uSyncService.js
index 6e59d40f..2ae3cab6 100644
--- a/uSync8.BackOffice/App_Plugins/uSync8/uSyncService.js
+++ b/uSync8.BackOffice/App_Plugins/uSync8/uSyncService.js
@@ -20,7 +20,8 @@
report: report,
exportItems: exportItems,
- importItems: importItems
+ importItems: importItems,
+ saveSettings: saveSettings
};
return service;
@@ -46,6 +47,10 @@
function importItems(force, clientId) {
return $http.put(serviceRoot + 'import', { force: force, clientId: clientId });
}
+
+ function saveSettings(settings) {
+ return $http.post(serviceRoot + 'savesettings', settings);
+ }
}
angular.module('umbraco.services')
diff --git a/uSync8.BackOffice/App_Plugins/uSync8/usync.css b/uSync8.BackOffice/App_Plugins/uSync8/usync.css
index eac4ea82..7f7f05d6 100644
--- a/uSync8.BackOffice/App_Plugins/uSync8/usync.css
+++ b/uSync8.BackOffice/App_Plugins/uSync8/usync.css
@@ -29,14 +29,44 @@
font-weight: 700;
}
+.usync-detail-count {
+ padding: 6px 0;
+}
+
.usync-item-details {
border-left: 4px solid #aaa;
}
+ .usync-item-details .umb-table-head .umb-table-row {
+ background-color: rgba(0,0,0,0.05);
+ border-bottom: 1px solid black;
+ }
+
.usync-item-details .umb-table {
background-color: #f3f3f5;
}
+ .usync-item-details .usync-detail-action-cell {
+ flex: 0 0 110px;
+ }
+
+ .usync-item-details .usync-old-value {
+ text-decoration: line-through;
+ color: #C62828;
+ }
+
+ .usync-item-details .usync-new-value {
+ color: #2e7d32
+ }
+
+.usync-row-delete {
+ background-color: #ffebee;
+}
+
+.usync-row-create {
+ background-color: #E8F5E9;
+}
+
.usync-handler-icon {
padding: 0.75em;
margin-right: 14px;
@@ -68,3 +98,27 @@
.usync-handler-icon.usync-complete {
color: #35c786;
}
+
+
+.usync-settings {
+ display: flex;
+}
+
+.usync-settings > div {
+ width: 50%;
+}
+
+ .usync-settings .usync-main-settings {
+ margin-right: 14px;
+ }
+
+ .usync-control {
+ position: relative;
+ padding: 10px 0;
+ }
+
+ .usync-control input[type="text"] {
+ position: absolute;
+ top: 10px;
+ width: 200px;
+ }
\ No newline at end of file
diff --git a/uSync8.BackOffice/Configuration/BackOfficeConfig.cs b/uSync8.BackOffice/Configuration/BackOfficeConfig.cs
new file mode 100644
index 00000000..50f48f38
--- /dev/null
+++ b/uSync8.BackOffice/Configuration/BackOfficeConfig.cs
@@ -0,0 +1,240 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Xml.Linq;
+using Umbraco.Core;
+using uSync8.Core.Extensions;
+
+namespace uSync8.BackOffice.Configuration
+{
+ public class uSyncConfig
+ {
+ public uSyncSettings Settings { get; set; }
+
+ private string settingsFile = Umbraco.Core.IO.SystemDirectories.Config + "/uSync8.config";
+
+ public uSyncConfig()
+ {
+ this.Settings = LoadSettings();
+ }
+
+ public uSyncSettings LoadSettings()
+ {
+ uSyncSettings settings = new uSyncSettings();
+
+ var node = GetSettingsFile();
+ if (node == null)
+ {
+ return SaveSettings(settings);
+ }
+
+ settings.RootFolder = node.Element("Folder").ValueOrDefault(settings.RootFolder);
+ settings.UseFlatStructure = node.Element("FlatFolders").ValueOrDefault(true);
+ settings.ImportAtStartup = node.Element("ImportAtStartup").ValueOrDefault(true);
+ settings.ExportAtStartup = node.Element("ExportAtStartup").ValueOrDefault(false);
+ settings.ExportOnSave = node.Element("ExportOnSave").ValueOrDefault(true);
+ settings.UseGuidNames = node.Element("UseGuidFilenames").ValueOrDefault(false);
+
+ var handlerConfig = node.Element("Handlers");
+
+ if (handlerConfig != null && handlerConfig.HasElements)
+ {
+ settings.EnableMissingHandlers = handlerConfig.Attribute("EnableMissing").ValueOrDefault(true);
+
+ foreach (var handlerNode in handlerConfig.Elements("Handler"))
+ {
+ var handlerSetting = LoadHandlerConfig(handlerNode, settings);
+
+ if (handlerSetting != null)
+ settings.Handlers.Add(handlerSetting);
+ }
+ }
+
+ return settings;
+ }
+
+
+ public uSyncSettings SaveSettings(uSyncSettings settings, bool fireReload = false)
+ {
+ var node = GetSettingsFile(true);
+
+ node.CreateOrSetElement("Folder", settings.RootFolder);
+ node.CreateOrSetElement("FlatFolders", settings.UseFlatStructure);
+ node.CreateOrSetElement("ImportAtStartup", settings.ImportAtStartup);
+ node.CreateOrSetElement("ExportAtStartup", settings.ExportAtStartup);
+ node.CreateOrSetElement("ExportOnSave", settings.ExportOnSave);
+ node.CreateOrSetElement("UseGuidFilenames", settings.UseGuidNames);
+
+ if (settings.Handlers != null && settings.Handlers.Any())
+ {
+ var handlerConfig = node.Element("Handlers");
+ if (handlerConfig == null)
+ {
+ handlerConfig = new XElement("Handlers",
+ new XAttribute("EnableMissing", true));
+ node.Add(handlerConfig);
+ }
+
+
+ foreach (var handler in settings.Handlers)
+ {
+ if (!handler.GuidNames.IsOverridden)
+ handler.GuidNames.SetDefaultValue(settings.UseGuidNames);
+
+ if (!handler.UseFlatStructure.IsOverridden)
+ handler.UseFlatStructure.SetDefaultValue(settings.UseFlatStructure);
+
+ var handlerNode = handlerConfig.Elements("Handler").FirstOrDefault(x => x.Attribute("Alias").Value == handler.Alias);
+ if (handlerNode == null)
+ {
+ handlerNode = new XElement("Handler");
+ handlerConfig.Add(handlerNode);
+ }
+
+ SaveHandlerConfig(handlerNode, handler, settings);
+ }
+ }
+
+ SaveSettingsFile(node);
+
+ if (fireReload)
+ {
+ this.Settings = LoadSettings();
+ Reloaded?.Invoke(settings);
+ }
+
+ return settings;
+ }
+
+ #region Default Handler Loading Stuff
+ public HandlerSettings LoadHandlerConfig(XElement node, uSyncSettings defaultSettings)
+ {
+ if (node == null) return null;
+ var alias = node.Attribute("Alias").ValueOrDefault(string.Empty);
+
+ if (string.IsNullOrEmpty(alias)) return null;
+
+ var enabled = node.Attribute("Enabled").ValueOrDefault(true);
+
+ var settings = new HandlerSettings(alias, enabled);
+
+ // these values can be set locally, but if they aren't
+ // we get them from the global setting.
+ settings.GuidNames = GetLocalValue(node.Attribute("GuidNames"), defaultSettings.UseGuidNames);
+ settings.UseFlatStructure = GetLocalValue(node.Attribute("UseFlatStructure"), defaultSettings.UseFlatStructure);
+
+ settings.Actions = node.Attribute("Actions").ValueOrDefault("All").ToDelimitedList().ToArray();
+
+ var settingNode = node.Element("Settings");
+ if (settingNode != null)
+ {
+ var perHandlerSettings = new Dictionary
();
+
+ foreach (var settingItem in settingNode.Elements("Add"))
+ {
+ var key = settingItem.Attribute("Key").ValueOrDefault(string.Empty);
+ var value = settingItem.Attribute("Value").ValueOrDefault(string.Empty);
+
+ if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(value))
+ continue;
+
+ perHandlerSettings.Add(key, value);
+ }
+
+ settings.Settings = perHandlerSettings;
+ }
+
+ return settings;
+ }
+
+ private OverriddenValue GetLocalValue(XAttribute attribute, TObject defaultValue)
+ {
+ if (attribute == null)
+ return new OverriddenValue(defaultValue, false);
+
+ return new OverriddenValue(attribute.ValueOrDefault(defaultValue), true);
+ }
+
+ public void SaveHandlerConfig(XElement node, HandlerSettings config, uSyncSettings globalSettings)
+ {
+ if (node == null) return;
+
+ node.SetAttributeValue("Alias", config.Alias);
+ node.SetAttributeValue("Enabled", config.Enabled);
+
+ if (config.GuidNames.IsOverridden)
+ node.SetAttributeValue("GuidNames", config.GuidNames);
+
+ if (config.UseFlatStructure.IsOverridden)
+ node.SetAttributeValue("UseFlatStructure", config.UseFlatStructure);
+
+ if (config.Actions.Length > 0 && !(config.Actions.Length == 1 && config.Actions[0].InvariantEquals("all")))
+ node.SetAttributeValue("Actions", string.Join(",", config.Actions));
+
+ if (config.Settings != null && config.Settings.Any())
+ {
+ var settingNode = new XElement("Settings");
+
+ foreach (var setting in config.Settings)
+ {
+ settingNode.Add(new XElement("Add",
+ new XAttribute("Key", setting.Key),
+ new XAttribute("Value", setting.Value)));
+ }
+
+ var existing = node.Element("Settings");
+ if (existing != null) existing.Remove();
+
+ node.Add(settingNode);
+ }
+ }
+
+ #endregion
+
+ private XElement GetSettingsFile(bool loadIfBlank = false)
+ {
+ var filePath = Umbraco.Core.IO.IOHelper.MapPath(settingsFile);
+ if (File.Exists(filePath))
+ {
+ var node = XElement.Load(filePath);
+ var settingsNode = node.Element("BackOffice");
+ if (settingsNode != null)
+ return settingsNode;
+
+ if (loadIfBlank)
+ {
+ node.Add(new XElement("BackOffice"));
+ return node.Element("BackOffice");
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (loadIfBlank)
+ {
+ var file = new XElement("uSync",
+ new XElement("BackOffice"));
+ return file.Element("BackOffice");
+ }
+
+ return null;
+ }
+
+ private void SaveSettingsFile(XElement node)
+ {
+ var root = node.Parent;
+ if (root != null)
+ {
+ var filePath = Umbraco.Core.IO.IOHelper.MapPath(settingsFile);
+ root.Save(filePath);
+ }
+ }
+
+ public static event uSyncSettingsEvent Reloaded;
+
+ public delegate void uSyncSettingsEvent(uSyncSettings settings);
+ }
+
+}
diff --git a/uSync8.BackOffice/Configuration/ConfigExtensions.cs b/uSync8.BackOffice/Configuration/ConfigExtensions.cs
new file mode 100644
index 00000000..bc07e697
--- /dev/null
+++ b/uSync8.BackOffice/Configuration/ConfigExtensions.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Umbraco.Core.Configuration;
+
+namespace uSync8.BackOffice.Configuration
+{
+ public static class ConfigExtensions
+ {
+ public static uSyncSettings uSync(this Configs configs)
+ => configs.GetConfig().Settings;
+ }
+}
diff --git a/uSync8.BackOffice/Configuration/OverriddenValue.cs b/uSync8.BackOffice/Configuration/OverriddenValue.cs
new file mode 100644
index 00000000..bc741f91
--- /dev/null
+++ b/uSync8.BackOffice/Configuration/OverriddenValue.cs
@@ -0,0 +1,41 @@
+namespace uSync8.BackOffice.Configuration
+{
+ ///
+ /// Overridden value - will let us use the value - but when
+ /// we load/save it we can work out if it's actually overriding the global
+ /// setting.
+ ///
+ public class OverriddenValue
+ {
+ public OverriddenValue()
+ : this(default(TObject), false)
+ { }
+
+ public OverriddenValue(TObject value, bool overridden)
+ {
+ Value = value;
+ IsOverridden = overridden;
+ }
+
+ public void Override(TObject value)
+ {
+ Value = value;
+ IsOverridden = true;
+ }
+
+ public void SetDefaultValue(TObject defaultValue)
+ {
+ Value = defaultValue;
+ IsOverridden = false;
+ }
+
+ public TObject Value { get; set; }
+ public bool IsOverridden { get; internal set; }
+
+ public static implicit operator TObject(OverriddenValue value)
+ {
+ return value.Value;
+ }
+ }
+
+}
diff --git a/uSync8.BackOffice/Configuration/uSyncHandlerSettings.cs b/uSync8.BackOffice/Configuration/uSyncHandlerSettings.cs
new file mode 100644
index 00000000..8937e496
--- /dev/null
+++ b/uSync8.BackOffice/Configuration/uSyncHandlerSettings.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+
+namespace uSync8.BackOffice.Configuration
+{
+ public class HandlerSettings
+ {
+ public string Alias { get; }
+ public bool Enabled { get; set; }
+
+ public string[] Actions { get; set; }
+
+ public OverriddenValue UseFlatStructure { get; set; } = new OverriddenValue();
+ public OverriddenValue GuidNames { get; set; } = new OverriddenValue();
+
+ public Dictionary Settings { get; set; } = new Dictionary();
+
+ public HandlerSettings(string alias, bool enabled)
+ {
+ Alias = alias;
+ Enabled = enabled;
+ }
+ }
+
+}
diff --git a/uSync8.BackOffice/Configuration/uSyncSettings.cs b/uSync8.BackOffice/Configuration/uSyncSettings.cs
new file mode 100644
index 00000000..a5a199a0
--- /dev/null
+++ b/uSync8.BackOffice/Configuration/uSyncSettings.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.XPath;
+using uSync8.BackOffice.SyncHandlers;
+
+namespace uSync8.BackOffice.Configuration
+{
+ public class uSyncSettings
+ {
+ public string RootFolder { get; set; } = "~/uSync/v8/";
+
+ public bool UseFlatStructure { get; set; } = true;
+ public bool UseGuidNames { get; set; } = false;
+
+ public bool ImportAtStartup { get; set; } = false;
+ public bool ExportAtStartup { get; set; } = false;
+ public bool ExportOnSave { get; set; } = true;
+
+ public bool EnableMissingHandlers { get; set; } = true;
+ public List Handlers { get; set; } = new List();
+ }
+
+}
diff --git a/uSync8.BackOffice/Controllers/uSyncDashboardApiController.cs b/uSync8.BackOffice/Controllers/uSyncDashboardApiController.cs
index 743bcd5d..6f716009 100644
--- a/uSync8.BackOffice/Controllers/uSyncDashboardApiController.cs
+++ b/uSync8.BackOffice/Controllers/uSyncDashboardApiController.cs
@@ -4,9 +4,11 @@
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
+using Umbraco.Core.Composing;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
using Umbraco.Web.WebApi.Filters;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Hubs;
using uSync8.BackOffice.SyncHandlers;
using Constants = Umbraco.Core.Constants;
@@ -18,22 +20,32 @@ namespace uSync8.BackOffice.Controllers
public class uSyncDashboardApiController : UmbracoAuthorizedApiController
{
private readonly uSyncService uSyncService;
-
- private readonly uSyncBackOfficeSettings settings;
private readonly SyncHandlerCollection syncHandlers;
+ private uSyncSettings settings;
+ private uSyncConfig Config;
+
public uSyncDashboardApiController(
uSyncService uSyncService,
SyncHandlerCollection syncHandlers,
- uSyncBackOfficeSettings settings)
+ uSyncConfig config)
{
+ this.Config = config;
this.uSyncService = uSyncService;
- this.settings = settings;
+
+ this.settings = Current.Configs.uSync();
this.syncHandlers = syncHandlers;
+
+ uSyncConfig.Reloaded += BackOfficeConfig_Reloaded;
+ }
+
+ private void BackOfficeConfig_Reloaded(uSyncSettings settings)
+ {
+ this.settings = settings;
}
[HttpGet]
- public uSyncBackOfficeSettings GetSettings()
+ public uSyncSettings GetSettings()
{
return settings;
}
@@ -56,7 +68,7 @@ public IEnumerable Report(uSyncOptions options)
var hubClient = new HubClientService(options.clientId);
var summaryClient = new SummaryHandler(hubClient);
- return uSyncService.Report(settings.rootFolder, summaryClient.PostSummary);
+ return uSyncService.Report(settings.RootFolder, summaryClient.PostSummary);
}
[HttpPost]
@@ -65,7 +77,7 @@ public IEnumerable Export(uSyncOptions options)
var hubClient = new HubClientService(options.clientId);
var summaryClient = new SummaryHandler(hubClient);
- return uSyncService.Export(settings.rootFolder, summaryClient.PostSummary);
+ return uSyncService.Export(settings.RootFolder, summaryClient.PostSummary);
}
[HttpPut]
@@ -74,9 +86,18 @@ public IEnumerable Import(uSyncOptions options)
var hubClient = new HubClientService(options.clientId);
var summaryClient = new SummaryHandler(hubClient);
- return uSyncService.Import(settings.rootFolder, options.force, summaryClient.PostSummary);
+ return uSyncService.Import(settings.RootFolder, options.force, summaryClient.PostSummary);
}
+ [HttpPost]
+ public void SaveSettings(uSyncSettings settings)
+ {
+ Config.SaveSettings(settings, true);
+ }
+
+
+
+
public class SummaryHandler
{
private readonly HubClientService hubClient;
diff --git a/uSync8.BackOffice/Services/SyncFileService.cs b/uSync8.BackOffice/Services/SyncFileService.cs
index 2394be9c..3ba4375b 100644
--- a/uSync8.BackOffice/Services/SyncFileService.cs
+++ b/uSync8.BackOffice/Services/SyncFileService.cs
@@ -6,7 +6,9 @@
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml.Serialization;
+using Umbraco.Core.Composing;
using Umbraco.Core.IO;
+using uSync8.BackOffice.Configuration;
namespace uSync8.BackOffice.Services
{
@@ -16,15 +18,22 @@ namespace uSync8.BackOffice.Services
///
public class SyncFileService
{
- private readonly uSyncBackOfficeSettings globalSettings;
- private readonly string mappedRoot;
+ private uSyncSettings globalSettings;
+ private string mappedRoot;
- public SyncFileService(uSyncBackOfficeSettings settings)
+ public SyncFileService()
{
- this.globalSettings = settings;
- this.mappedRoot = IOHelper.MapPath(globalSettings.rootFolder);
+ this.globalSettings = Current.Configs.uSync();
+ this.mappedRoot = IOHelper.MapPath(globalSettings.RootFolder);
+
+ uSyncConfig.Reloaded += BackOfficeConfig_Reloaded;
}
+ private void BackOfficeConfig_Reloaded(uSyncSettings settings)
+ {
+ this.globalSettings = Current.Configs.uSync();
+ this.mappedRoot = IOHelper.MapPath(globalSettings.RootFolder);
+ }
private string GetAbsPath(string path)
{
@@ -86,6 +95,13 @@ public void CreateFoldersForFile(string filePath)
Directory.CreateDirectory(absPath);
}
+ public void CleanFolder(string folder)
+ {
+ var absPath = GetAbsPath(folder);
+
+ if (Directory.Exists(absPath))
+ Directory.Delete(absPath, true);
+ }
public IEnumerable GetFiles(string folder, string extensions)
{
diff --git a/uSync8.BackOffice/Services/uSyncService.cs b/uSync8.BackOffice/Services/uSyncService.cs
index f7f84445..0804214b 100644
--- a/uSync8.BackOffice/Services/uSyncService.cs
+++ b/uSync8.BackOffice/Services/uSyncService.cs
@@ -3,7 +3,9 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.SyncHandlers;
namespace uSync8.BackOffice
@@ -16,15 +18,22 @@ namespace uSync8.BackOffice
///
public class uSyncService
{
- private readonly uSyncBackOfficeSettings settings;
+ private uSyncSettings settings;
private readonly SyncHandlerCollection syncHandlers;
- public uSyncService(
- SyncHandlerCollection syncHandlers,
- uSyncBackOfficeSettings settings)
+ public uSyncService(
+ SyncHandlerCollection syncHandlers
+ )
{
this.syncHandlers = syncHandlers;
- this.settings = settings;
+ this.settings = Current.Configs.uSync();
+
+ uSyncConfig.Reloaded += BackOfficeConfig_Reloaded;
+ }
+
+ private void BackOfficeConfig_Reloaded(uSyncSettings settings)
+ {
+ this.settings = Current.Configs.uSync();
}
public delegate void SyncEventCallback(SyncProgressSummary summary);
@@ -33,21 +42,22 @@ public IEnumerable Report(string folder, SyncEventCallback callback
{
var actions = new List();
- var configuredHandlers = settings.Handlers.Where(x => x.Config.Enabled == true).ToList();
+ var configuredHandlers = syncHandlers.GetValidHandlers("report", settings).ToList();
var summary = new SyncProgressSummary(configuredHandlers.Select(x => x.Handler), "Reporting", configuredHandlers.Count);
-
+
foreach (var configuredHandler in configuredHandlers)
{
var handler = configuredHandler.Handler;
+ var handlerSettings = configuredHandler.Settings;
+
summary.Processed++;
- summary.UpdateHandler(
- handler.Name, HandlerStatus.Processing, $"Reporting {handler.Name}");
+ summary.UpdateHandler(handler.Name, HandlerStatus.Processing, $"Reporting {handler.Name}");
callback?.Invoke(summary);
- actions.AddRange(handler.Report($"{folder}/{handler.DefaultFolder}", configuredHandler.Config));
+ actions.AddRange(handler.Report($"{folder}/{handler.DefaultFolder}", handlerSettings));
summary.UpdateHandler(handler.Name, HandlerStatus.Complete);
}
@@ -70,7 +80,7 @@ public IEnumerable Import(string folder, bool force, SyncEventCallb
var actions = new List();
- var configuredHandlers = settings.Handlers.Where(x => x.Config.Enabled == true).ToList();
+ var configuredHandlers = syncHandlers.GetValidHandlers("import", settings).ToList();
var summary = new SyncProgressSummary(configuredHandlers.Select(x => x.Handler), "Importing", configuredHandlers.Count + 1);
summary.Handlers.Add(new SyncHandlerSummary()
@@ -83,6 +93,7 @@ public IEnumerable Import(string folder, bool force, SyncEventCallb
foreach (var configuredHandler in configuredHandlers)
{
var handler = configuredHandler.Handler;
+ var handlerSettings = configuredHandler.Settings;
summary.Processed++;
@@ -91,7 +102,7 @@ public IEnumerable Import(string folder, bool force, SyncEventCallb
callback?.Invoke(summary);
- actions.AddRange(handler.ImportAll($"{folder}/{handler.DefaultFolder}", configuredHandler.Config, force));
+ actions.AddRange(handler.ImportAll($"{folder}/{handler.DefaultFolder}", handlerSettings, force));
summary.UpdateHandler(handler.Name, HandlerStatus.Complete);
}
@@ -111,6 +122,7 @@ public IEnumerable Import(string folder, bool force, SyncEventCallb
foreach (var configuredHandler in configuredHandlers)
{
var handler = configuredHandler.Handler;
+ var handlerSettings = configuredHandler.Settings;
if (handler is ISyncPostImportHandler postHandler)
{
@@ -118,7 +130,7 @@ public IEnumerable Import(string folder, bool force, SyncEventCallb
if (handlerActions.Any())
{
- var postActions = postHandler.ProcessPostImport($"{folder}/{handler.DefaultFolder}", handlerActions, configuredHandler.Config);
+ var postActions = postHandler.ProcessPostImport($"{folder}/{handler.DefaultFolder}", handlerActions, handlerSettings);
if (postActions != null)
actions.AddRange(postActions);
}
@@ -130,7 +142,7 @@ public IEnumerable Import(string folder, bool force, SyncEventCallb
return actions;
}
- catch(Exception ex)
+ catch (Exception ex)
{
throw ex;
}
@@ -145,7 +157,7 @@ public IEnumerable Export(string folder, SyncEventCallback callback
{
var actions = new List();
- var configuredHandlers = settings.Handlers.Where(x => x.Config.Enabled == true).ToList();
+ var configuredHandlers = syncHandlers.GetValidHandlers("export", settings).ToList();
var summary = new SyncProgressSummary(configuredHandlers.Select(x => x.Handler), "Exporting", configuredHandlers.Count);
@@ -159,7 +171,7 @@ public IEnumerable Export(string folder, SyncEventCallback callback
callback?.Invoke(summary);
- actions.AddRange(handler.ExportAll($"{folder}/{handler.DefaultFolder}", configuredHandler.Config));
+ actions.AddRange(handler.ExportAll($"{folder}/{handler.DefaultFolder}", configuredHandler.Settings));
summary.UpdateHandler(handler.Name, HandlerStatus.Complete);
}
@@ -171,4 +183,5 @@ public IEnumerable Export(string folder, SyncEventCallback callback
}
}
+
}
diff --git a/uSync8.BackOffice/SyncHandlers/Handlers/ContentTypeHandler.cs b/uSync8.BackOffice/SyncHandlers/Handlers/ContentTypeHandler.cs
index 019e019b..035932c7 100644
--- a/uSync8.BackOffice/SyncHandlers/Handlers/ContentTypeHandler.cs
+++ b/uSync8.BackOffice/SyncHandlers/Handlers/ContentTypeHandler.cs
@@ -12,6 +12,7 @@
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.Core;
using uSync8.Core.Serialization;
@@ -32,9 +33,8 @@ public ContentTypeHandler(
IContentTypeService contentTypeService,
ISyncSerializer serializer,
ISyncTracker tracker,
- SyncFileService fileService,
- uSyncBackOfficeSettings settings)
- : base(entityService, logger, serializer, tracker, fileService, settings)
+ SyncFileService fileService)
+ : base(entityService, logger, serializer, tracker, fileService)
{
this.contentTypeService = contentTypeService;
@@ -55,15 +55,24 @@ public ContentTypeHandler(
#endregion
- protected override void InitializeEvents()
+ protected override void InitializeEvents(HandlerSettings settings)
{
ContentTypeService.Saved += EventSavedItem;
ContentTypeService.Deleted += EventDeletedItem;
}
- protected override string GetItemFileName(IUmbracoEntity item)
- => item.Name;
+ protected override string GetItemFileName(IUmbracoEntity item, bool useGuid)
+ {
+ if (useGuid) return item.Key.ToString();
+
+ if (item is IContentType contentItem)
+ {
+ return contentItem.Alias.ToSafeFileName();
+ }
+
+ return item.Name.ToSafeFileName();
+ }
protected override IContentType GetFromService(int id)
=> contentTypeService.Get(id);
diff --git a/uSync8.BackOffice/SyncHandlers/Handlers/DataTypeHandler.cs b/uSync8.BackOffice/SyncHandlers/Handlers/DataTypeHandler.cs
index cbcbb350..d54423d3 100644
--- a/uSync8.BackOffice/SyncHandlers/Handlers/DataTypeHandler.cs
+++ b/uSync8.BackOffice/SyncHandlers/Handlers/DataTypeHandler.cs
@@ -9,6 +9,7 @@
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.Core;
using uSync8.Core.Serialization;
@@ -27,30 +28,33 @@ public DataTypeHandler(
IProfilingLogger logger,
ISyncSerializer serializer,
ISyncTracker tracker,
- SyncFileService syncFileService,
- uSyncBackOfficeSettings settings)
- : base(entityService, logger, serializer, tracker, syncFileService, settings)
+ SyncFileService syncFileService)
+ : base(entityService, logger, serializer, tracker, syncFileService)
{
this.dataTypeService = dataTypeService;
this.itemObjectType = UmbracoObjectTypes.DataType;
+ this.itemContainerType = UmbracoObjectTypes.DataTypeContainer;
}
protected override IDataType GetFromService(int id)
=> dataTypeService.GetDataType(id);
- protected override void InitializeEvents()
+ protected override void InitializeEvents(HandlerSettings settings)
{
DataTypeService.Saved += EventSavedItem;
DataTypeService.Deleted += EventDeletedItem;
}
- protected override string GetItemFileName(IUmbracoEntity item)
- => item.Name.ToSafeFileName();
+ protected override string GetItemFileName(IUmbracoEntity item, bool useGuid)
+ {
+ if (useGuid) return item.Key.ToString();
+ return item.Name.ToSafeAlias();
+ }
protected override void DeleteFolder(int id)
=> dataTypeService.DeleteContainer(id);
- public override IEnumerable ProcessPostImport(string folder, IEnumerable actions, uSyncHandlerSettings config)
+ public override IEnumerable ProcessPostImport(string folder, IEnumerable actions, HandlerSettings config)
{
if (actions == null || !actions.Any())
return null;
diff --git a/uSync8.BackOffice/SyncHandlers/Handlers/LanguageHandler.cs b/uSync8.BackOffice/SyncHandlers/Handlers/LanguageHandler.cs
index c1a086ad..92d0ae2a 100644
--- a/uSync8.BackOffice/SyncHandlers/Handlers/LanguageHandler.cs
+++ b/uSync8.BackOffice/SyncHandlers/Handlers/LanguageHandler.cs
@@ -6,8 +6,10 @@
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
+using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.Core.Serialization;
using uSync8.Core.Tracking;
@@ -25,9 +27,8 @@ public LanguageHandler(
ILocalizationService localizationService,
ISyncSerializer serializer,
ISyncTracker tracker,
- SyncFileService syncFileService,
- uSyncBackOfficeSettings settings)
- : base(entityService, logger, serializer, tracker, syncFileService, settings)
+ SyncFileService syncFileService)
+ : base(entityService, logger, serializer, tracker, syncFileService)
{
this.localizationService = localizationService;
@@ -38,15 +39,24 @@ public LanguageHandler(
protected override ILanguage GetFromService(int id)
=> localizationService.GetLanguageById(id);
- protected override string GetItemPath(ILanguage item)
+ // language guids are not consistant (at least in alpha)
+ protected override string GetItemPath(ILanguage item, bool useGuid, bool isFlat)
=> item.IsoCode.ToSafeFileName();
- protected override void InitializeEvents()
+ protected override void InitializeEvents(HandlerSettings settings)
{
LocalizationService.SavedLanguage += EventSavedItem;
LocalizationService.DeletedLanguage += EventDeletedItem;
}
+ protected override IEnumerable GetExportItems(int parent, UmbracoObjectTypes objectType)
+ {
+ if (parent == -1)
+ return localizationService.GetAllLanguages();
+
+ return Enumerable.Empty();
+ }
+
protected override ILanguage GetFromService(Guid key)
=> null;
diff --git a/uSync8.BackOffice/SyncHandlers/Handlers/MacroHandler.cs b/uSync8.BackOffice/SyncHandlers/Handlers/MacroHandler.cs
index a82765d0..57eb5c74 100644
--- a/uSync8.BackOffice/SyncHandlers/Handlers/MacroHandler.cs
+++ b/uSync8.BackOffice/SyncHandlers/Handlers/MacroHandler.cs
@@ -8,6 +8,7 @@
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.Core.Serialization;
using uSync8.Core.Tracking;
@@ -24,9 +25,8 @@ public MacroHandler(IEntityService entityService,
IMacroService macroService,
ISyncSerializer serializer,
ISyncTracker tracker,
- SyncFileService syncFileService,
- uSyncBackOfficeSettings settings)
- : base(entityService, logger, serializer, tracker, syncFileService, settings)
+ SyncFileService syncFileService)
+ : base(entityService, logger, serializer, tracker, syncFileService)
{
this.macroService = macroService;
}
@@ -34,7 +34,7 @@ public MacroHandler(IEntityService entityService,
///
/// overrider the default export, because macros, don't exist as an object type???
///
- public override IEnumerable ExportAll(int parent, string folder, uSyncHandlerSettings config = null)
+ public override IEnumerable ExportAll(int parent, string folder, HandlerSettings config = null)
{
var actions = new List();
@@ -50,10 +50,14 @@ public override IEnumerable ExportAll(int parent, string folder, uS
protected override IMacro GetFromService(int id)
=> macroService.GetById(id);
- protected override string GetItemPath(IMacro item)
- => item.Alias.ToSafeFileName();
+ // not sure we can trust macro guids in the path just yet.
+ protected override string GetItemPath(IMacro item, bool useGuid, bool isFlat)
+ {
+ if (useGuid) return item.Key.ToString();
+ return item.Alias.ToSafeAlias();
+ }
- protected override void InitializeEvents()
+ protected override void InitializeEvents(HandlerSettings settings)
{
MacroService.Saved += EventSavedItem;
MacroService.Deleted += EventDeletedItem;
diff --git a/uSync8.BackOffice/SyncHandlers/Handlers/MediaTypeHandler.cs b/uSync8.BackOffice/SyncHandlers/Handlers/MediaTypeHandler.cs
index 021f078b..f150a54b 100644
--- a/uSync8.BackOffice/SyncHandlers/Handlers/MediaTypeHandler.cs
+++ b/uSync8.BackOffice/SyncHandlers/Handlers/MediaTypeHandler.cs
@@ -3,11 +3,13 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.Core;
using uSync8.Core.Serialization;
@@ -26,9 +28,8 @@ public MediaTypeHandler(
IProfilingLogger logger,
ISyncSerializer serializer,
ISyncTracker tracker,
- SyncFileService syncFileService,
- uSyncBackOfficeSettings settings)
- : base(entityService, logger, serializer, tracker, syncFileService, settings)
+ SyncFileService syncFileService)
+ : base(entityService, logger, serializer, tracker, syncFileService)
{
this.mediaTypeService = mediaTypeService;
@@ -37,20 +38,29 @@ public MediaTypeHandler(
}
- protected override IMediaType GetFromService(int id)
- => mediaTypeService.Get(id);
- protected override string GetItemFileName(IUmbracoEntity item)
- => item.Name;
-
- protected override void InitializeEvents()
+ protected override void InitializeEvents(HandlerSettings settings)
{
MediaTypeService.Saved += EventSavedItem;
MediaTypeService.Deleted += EventDeletedItem;
}
- protected override void DeleteFolder(int id)
- => mediaTypeService.DeleteContainer(id);
+ protected override string GetItemFileName(IUmbracoEntity item, bool useGuid)
+ {
+ if (useGuid) return item.Key.ToString();
+
+ if (item is IMediaType mediaType)
+ {
+ return mediaType.Alias.ToSafeFileName();
+ }
+
+ return item.Name.ToSafeFileName();
+ }
+
+
+
+ protected override IMediaType GetFromService(int id)
+ => mediaTypeService.Get(id);
protected override IMediaType GetFromService(Guid key)
=> mediaTypeService.Get(key);
@@ -60,5 +70,8 @@ protected override IMediaType GetFromService(string alias)
protected override void DeleteViaService(IMediaType item)
=> mediaTypeService.Delete(item);
+
+ protected override void DeleteFolder(int id)
+ => mediaTypeService.DeleteContainer(id);
}
}
diff --git a/uSync8.BackOffice/SyncHandlers/Handlers/MemberTypeHandler.cs b/uSync8.BackOffice/SyncHandlers/Handlers/MemberTypeHandler.cs
index 829ee23a..7658a3c5 100644
--- a/uSync8.BackOffice/SyncHandlers/Handlers/MemberTypeHandler.cs
+++ b/uSync8.BackOffice/SyncHandlers/Handlers/MemberTypeHandler.cs
@@ -3,11 +3,13 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.Core.Serialization;
using uSync8.Core.Tracking;
@@ -25,9 +27,8 @@ public MemberTypeHandler(
IMemberTypeService memberTypeService,
ISyncSerializer serializer,
ISyncTracker tracker,
- SyncFileService syncFileService,
- uSyncBackOfficeSettings settings)
- : base(entityService, logger, serializer, tracker, syncFileService, settings)
+ SyncFileService syncFileService)
+ : base(entityService, logger, serializer, tracker, syncFileService)
{
this.memberTypeService = memberTypeService;
@@ -40,8 +41,7 @@ public MemberTypeHandler(
this.Enabled = false;
// turn it off it appears to break things in current build
}
-
- protected override void InitializeEvents()
+ protected override void InitializeEvents(HandlerSettings settings)
{
MemberTypeService.Saved += EventSavedItem;
MemberTypeService.Deleted += EventDeletedItem;
@@ -62,7 +62,16 @@ protected override IMemberType GetFromService(Guid key)
protected override IMemberType GetFromService(string alias)
=> memberTypeService.Get(alias);
- protected override string GetItemFileName(IUmbracoEntity item)
- => item.Name;
+ protected override string GetItemFileName(IUmbracoEntity item, bool useGuid)
+ {
+ if (useGuid) return item.Key.ToString();
+
+ if (item is IMemberType memberType)
+ {
+ return memberType.Alias.ToSafeFileName();
+ }
+
+ return item.Name.ToSafeFileName();
+ }
}
}
diff --git a/uSync8.BackOffice/SyncHandlers/Handlers/TemplateHandler.cs b/uSync8.BackOffice/SyncHandlers/Handlers/TemplateHandler.cs
index 0f6eb1a0..0f7b8f24 100644
--- a/uSync8.BackOffice/SyncHandlers/Handlers/TemplateHandler.cs
+++ b/uSync8.BackOffice/SyncHandlers/Handlers/TemplateHandler.cs
@@ -3,11 +3,13 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.Core.Serialization;
using uSync8.Core.Tracking;
@@ -26,9 +28,8 @@ public TemplateHandler(
IFileService fileService,
ISyncSerializer serializer,
ISyncTracker tracker,
- SyncFileService syncFileService,
- uSyncBackOfficeSettings settings)
- : base(entityService, logger, serializer, tracker, syncFileService, settings)
+ SyncFileService syncFileService)
+ : base(entityService, logger, serializer, tracker, syncFileService)
{
this.fileService = fileService;
@@ -41,14 +42,14 @@ public TemplateHandler(
protected override ITemplate GetFromService(int id)
=> fileService.GetTemplate(id);
- protected override void InitializeEvents()
+ protected override void InitializeEvents(HandlerSettings settings)
{
FileService.SavedTemplate += EventSavedItem;
FileService.DeletedTemplate += EventDeletedItem;
}
- protected override string GetItemPath(ITemplate item)
- => item.Name;
+ protected override string GetItemPath(ITemplate item, bool useGuid, bool isFlat)
+ => useGuid ? item.Key.ToString() : item.Alias.ToSafeFileName();
protected override ITemplate GetFromService(Guid key)
=> fileService.GetTemplate(key);
diff --git a/uSync8.BackOffice/SyncHandlers/ISyncHandler.cs b/uSync8.BackOffice/SyncHandlers/ISyncHandler.cs
index b2bd2132..2259531c 100644
--- a/uSync8.BackOffice/SyncHandlers/ISyncHandler.cs
+++ b/uSync8.BackOffice/SyncHandlers/ISyncHandler.cs
@@ -4,6 +4,7 @@
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core;
+using uSync8.BackOffice.Configuration;
namespace uSync8.BackOffice.SyncHandlers
{
@@ -17,13 +18,13 @@ public interface ISyncHandler
Type ItemType { get; }
bool Enabled { get; set; }
- uSyncHandlerSettings DefaultConfig { get; set; }
+ HandlerSettings DefaultConfig { get; set; }
- void Initialize();
+ void Initialize(HandlerSettings settings);
- IEnumerable ExportAll(string folder, uSyncHandlerSettings setting);
- IEnumerable ImportAll(string folder, uSyncHandlerSettings setting, bool force);
- IEnumerable Report(string folder, uSyncHandlerSettings setting);
+ IEnumerable ExportAll(string folder, HandlerSettings settings);
+ IEnumerable ImportAll(string folder, HandlerSettings settings, bool force);
+ IEnumerable Report(string folder, HandlerSettings settings);
// uSyncAction Import(string file, bool force);
diff --git a/uSync8.BackOffice/SyncHandlers/ISyncPostImportHanlder.cs b/uSync8.BackOffice/SyncHandlers/ISyncPostImportHanlder.cs
index af5fcc81..2be3e874 100644
--- a/uSync8.BackOffice/SyncHandlers/ISyncPostImportHanlder.cs
+++ b/uSync8.BackOffice/SyncHandlers/ISyncPostImportHanlder.cs
@@ -3,6 +3,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using uSync8.BackOffice.Configuration;
namespace uSync8.BackOffice.SyncHandlers
{
@@ -13,6 +14,6 @@ namespace uSync8.BackOffice.SyncHandlers
///
public interface ISyncPostImportHandler
{
- IEnumerable ProcessPostImport(string folder, IEnumerable actions, uSyncHandlerSettings config);
+ IEnumerable ProcessPostImport(string folder, IEnumerable actions, HandlerSettings config);
}
}
diff --git a/uSync8.BackOffice/SyncHandlers/SyncHandlerBase.cs b/uSync8.BackOffice/SyncHandlers/SyncHandlerBase.cs
index 2afffdcc..d9d6284e 100644
--- a/uSync8.BackOffice/SyncHandlers/SyncHandlerBase.cs
+++ b/uSync8.BackOffice/SyncHandlers/SyncHandlerBase.cs
@@ -4,10 +4,12 @@
using System.Linq;
using System.Xml.Linq;
using Umbraco.Core;
+using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Models;
using uSync8.BackOffice.Services;
using uSync8.Core;
@@ -25,7 +27,6 @@ public abstract class SyncHandlerBase
protected readonly IProfilingLogger logger;
protected readonly IEntityService entityService;
- protected readonly uSyncBackOfficeSettings globalSettings;
protected readonly SyncFileService syncFileService;
protected readonly ISyncSerializer serializer;
@@ -44,7 +45,9 @@ public abstract class SyncHandlerBase
/// settings can be loaded for these.
public bool Enabled { get; set; } = true;
- public uSyncHandlerSettings DefaultConfig { get; set; }
+ public HandlerSettings DefaultConfig { get; set; }
+
+ protected string rootFolder { get; set; }
protected UmbracoObjectTypes itemObjectType = UmbracoObjectTypes.Unknown;
protected UmbracoObjectTypes itemContainerType = UmbracoObjectTypes.Unknown;
@@ -56,15 +59,16 @@ public SyncHandlerBase(
IProfilingLogger logger,
ISyncSerializer serializer,
ISyncTracker tracker,
- SyncFileService syncFileService,
- uSyncBackOfficeSettings settings)
+ SyncFileService syncFileService)
{
- this.entityService = entityService;
this.logger = logger;
- this.globalSettings = settings;
+
+ this.entityService = entityService;
+
this.serializer = serializer;
this.tracker = tracker;
+
this.syncFileService = syncFileService;
var thisType = GetType();
@@ -79,10 +83,26 @@ public SyncHandlerBase(
IsTwoPass = meta.IsTwoPass;
Icon = string.IsNullOrWhiteSpace(meta.Icon) ? "icon-umb-content" : meta.Icon;
+ GetDefaultConfig(Current.Configs.uSync());
+ uSyncConfig.Reloaded += BackOfficeConfig_Reloaded;
+ }
+
+ private void GetDefaultConfig(uSyncSettings setting)
+ {
+ var config = setting.Handlers.FirstOrDefault(x => x.Alias == this.Alias);
+ if (config != null)
+ this.DefaultConfig = config;
+
+ rootFolder = setting.RootFolder;
+ }
+
+ private void BackOfficeConfig_Reloaded(uSyncSettings settings)
+ {
+ GetDefaultConfig(settings);
}
#region Importing
- public IEnumerable ImportAll(string folder, uSyncHandlerSettings config = null, bool force = false)
+ public IEnumerable ImportAll(string folder, HandlerSettings config = null, bool force = false)
{
logger.Info("Running Import: {0}", Path.GetFileName(folder));
@@ -103,7 +123,7 @@ public IEnumerable ImportAll(string folder, uSyncHandlerSettings co
return actions;
}
- protected virtual IEnumerable ImportFolder(string folder, uSyncHandlerSettings config, Dictionary updates, bool force)
+ protected virtual IEnumerable ImportFolder(string folder, HandlerSettings config, Dictionary updates, bool force)
{
List actions = new List();
@@ -117,7 +137,11 @@ protected virtual IEnumerable ImportFolder(string folder, uSyncHand
updates.Add(file, attempt.Item);
}
- actions.Add(uSyncActionHelper.SetAction(attempt, file, IsTwoPass));
+ var action = uSyncActionHelper.SetAction(attempt, file, IsTwoPass);
+ if (attempt.Details != null && attempt.Details.Any())
+ action.Details = attempt.Details;
+
+ actions.Add(action);
}
var folders = syncFileService.GetDirectories(folder);
@@ -130,7 +154,7 @@ protected virtual IEnumerable ImportFolder(string folder, uSyncHand
return actions;
}
- virtual public SyncAttempt Import(string filePath, uSyncHandlerSettings config, bool force = false)
+ virtual public SyncAttempt Import(string filePath, HandlerSettings config, bool force = false)
{
syncFileService.EnsureFileExists(filePath);
@@ -142,7 +166,7 @@ virtual public SyncAttempt Import(string filePath, uSyncHandlerSettings
}
}
- virtual public void ImportSecondPass(string file, TObject item, uSyncHandlerSettings config)
+ virtual public void ImportSecondPass(string file, TObject item, HandlerSettings config)
{
if (IsTwoPass)
{
@@ -160,12 +184,15 @@ virtual public void ImportSecondPass(string file, TObject item, uSyncHandlerSett
#endregion
#region Exporting
- virtual public IEnumerable ExportAll(string folder, uSyncHandlerSettings config = null)
+ virtual public IEnumerable ExportAll(string folder, HandlerSettings config = null)
{
+ // we clean the folder out on an export all.
+ syncFileService.CleanFolder(folder);
+
return ExportAll(-1, folder, config);
}
- virtual public IEnumerable ExportAll(int parent, string folder, uSyncHandlerSettings config)
+ virtual public IEnumerable ExportAll(int parent, string folder, HandlerSettings config)
{
var actions = new List();
@@ -178,11 +205,11 @@ virtual public IEnumerable ExportAll(int parent, string folder, uSy
}
}
- var items = entityService.GetChildren(parent, this.itemObjectType);
+ var items = GetExportItems(parent, itemObjectType);
foreach (var item in items)
{
- var contentType = GetFromService(item.Id);
- actions.Add(Export(contentType, folder, config));
+ var concreateType = GetFromService(item.Id);
+ actions.Add(Export(concreateType, folder, config));
actions.AddRange(ExportAll(item.Id, folder, config));
}
@@ -190,12 +217,17 @@ virtual public IEnumerable ExportAll(int parent, string folder, uSy
return actions;
}
- virtual public uSyncAction Export(TObject item, string folder, uSyncHandlerSettings config)
+ // almost everything does this - but languages can't so we need to
+ // let the language Handler override this.
+ virtual protected IEnumerable GetExportItems(int parent, UmbracoObjectTypes objectType)
+ => entityService.GetChildren(parent, objectType);
+
+ virtual public uSyncAction Export(TObject item, string folder, HandlerSettings config)
{
if (item == null)
return uSyncAction.Fail(nameof(item), typeof(TObject), ChangeType.Fail, "Item not set");
- var filename = GetPath(folder, item, config.GuidNames);
+ var filename = GetPath(folder, item, config.GuidNames, config.UseFlatStructure);
var attempt = serializer.Serialize(item);
if (attempt.Success)
@@ -210,7 +242,7 @@ virtual public uSyncAction Export(TObject item, string folder, uSyncHandlerSetti
#region reporting
- public IEnumerable Report(string folder, uSyncHandlerSettings config = null)
+ public IEnumerable Report(string folder, HandlerSettings config = null)
{
var actions = new List();
actions.AddRange(ProcessActions(true));
@@ -218,7 +250,7 @@ public IEnumerable Report(string folder, uSyncHandlerSettings confi
return actions;
}
- public IEnumerable ReportFolder(string folder, uSyncHandlerSettings config)
+ public IEnumerable ReportFolder(string folder, HandlerSettings config)
{
List actions = new List();
@@ -252,10 +284,18 @@ protected uSyncAction ReportItem(string file)
var action = uSyncActionHelper
.ReportAction(!current, node.GetAlias());
- action.Message = nameof(TObject);
+ action.Message = "";
if (action.Change > ChangeType.NoChange)
+ {
action.Details = tracker.GetChanges(node);
+ if (action.Details == null || action.Details.Count() == 0)
+ {
+ action.Message = "Change details cannot be calculated";
+ }
+
+ action.Message = "Would update";
+ }
return action;
}
@@ -274,7 +314,7 @@ protected virtual void EventDeletedItem(IService sender, Umbraco.Core.Events.Del
foreach (var item in e.DeletedEntities)
{
- ExportDeletedItem(item, Path.Combine(globalSettings.rootFolder, this.DefaultFolder), DefaultConfig);
+ ExportDeletedItem(item, Path.Combine(rootFolder, this.DefaultFolder), DefaultConfig);
actionService.AddAction(item.Key, GetItemName(item), SyncActionType.Delete);
}
@@ -290,7 +330,7 @@ protected virtual void EventSavedItem(IService sender, Umbraco.Core.Events.SaveE
foreach (var item in e.SavedEntities)
{
- var attempt = Export(item, Path.Combine(globalSettings.rootFolder, this.DefaultFolder), DefaultConfig);
+ var attempt = Export(item, Path.Combine(rootFolder, this.DefaultFolder), DefaultConfig);
if (attempt.Success)
{
if (!DefaultConfig.GuidNames)
@@ -302,10 +342,10 @@ protected virtual void EventSavedItem(IService sender, Umbraco.Core.Events.SaveE
actionService.SaveActions();
}
- protected virtual void ExportDeletedItem(TObject item, string folder, uSyncHandlerSettings config)
+ protected virtual void ExportDeletedItem(TObject item, string folder, HandlerSettings config)
{
if (item == null) return;
- var filename = GetPath(folder, item, config.GuidNames);
+ var filename = GetPath(folder, item, config.GuidNames, config.UseFlatStructure);
var attempt = serializer.SerializeEmpty(item, GetItemName(item));
if (attempt.Success)
@@ -377,8 +417,16 @@ virtual public uSyncAction ProcessDelete(Guid key, string keyString, bool report
if (item != null)
{
- if (!report) DeleteViaService(item);
- return uSyncAction.SetAction(true, keyString, typeof(TObject), ChangeType.Delete);
+ var message = "";
+ if (!report)
+ {
+ DeleteViaService(item);
+ }
+ else
+ {
+ message = "Would be deleted";
+ }
+ return uSyncAction.SetAction(true, keyString, typeof(TObject), ChangeType.Delete, message);
}
return uSyncAction.SetAction(false, keyString, typeof(TObject), ChangeType.Removed);
@@ -391,27 +439,27 @@ virtual public uSyncAction ProcessDelete(Guid key, string keyString, bool report
abstract protected TObject GetFromService(string alias);
abstract protected void DeleteViaService(TObject item);
- abstract protected string GetItemPath(TObject item);
+ abstract protected string GetItemPath(TObject item, bool useGuid, bool isFlat);
abstract protected string GetItemName(TObject item);
- virtual protected string GetPath(string folder, TObject item, bool GuidNames)
+ virtual protected string GetPath(string folder, TObject item, bool GuidNames, bool isFlat)
{
- if (GuidNames) return $"{folder}/{item.Key}.config";
+ if (isFlat && GuidNames) return $"{folder}/{item.Key}.config";
- return $"{folder}/{this.GetItemPath(item)}.config";
+ return $"{folder}/{this.GetItemPath(item, GuidNames, isFlat)}.config";
}
virtual public uSyncAction Rename(TObject item)
=> new uSyncAction();
- public void Initialize()
+ public void Initialize(HandlerSettings settings)
{
- actionFile = Path.Combine(globalSettings.rootFolder, $"_Actions/actions_{DefaultFolder}.config");
- InitializeEvents();
+ actionFile = Path.Combine(rootFolder, $"_Actions/actions_{DefaultFolder}.config");
+ InitializeEvents(settings);
}
- protected abstract void InitializeEvents();
+ protected abstract void InitializeEvents(HandlerSettings settings);
}
}
diff --git a/uSync8.BackOffice/SyncHandlers/SyncHandlerCollectionBuilder.cs b/uSync8.BackOffice/SyncHandlers/SyncHandlerCollectionBuilder.cs
index e3e614dd..7689728a 100644
--- a/uSync8.BackOffice/SyncHandlers/SyncHandlerCollectionBuilder.cs
+++ b/uSync8.BackOffice/SyncHandlers/SyncHandlerCollectionBuilder.cs
@@ -3,7 +3,9 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Umbraco.Core;
using Umbraco.Core.Composing;
+using uSync8.BackOffice.Configuration;
namespace uSync8.BackOffice.SyncHandlers
{
@@ -19,5 +21,40 @@ public SyncHandlerCollection(IEnumerable items)
: base(items)
{
}
+
+ public IEnumerable GetValidHandlers(string actionName, uSyncSettings settings)
+ {
+ var validHandlers = new List();
+
+ foreach (var syncHandler in this)
+ {
+ var config = settings.Handlers.FirstOrDefault(x => x.Alias.InvariantEquals(syncHandler.Alias));
+ if (config == null)
+ {
+ config = new HandlerSettings(syncHandler.Alias, settings.EnableMissingHandlers)
+ {
+ GuidNames = new OverriddenValue(settings.UseGuidNames, false),
+ UseFlatStructure = new OverriddenValue(settings.UseFlatStructure, false)
+ };
+ }
+
+ if (config != null && config.Enabled)
+ {
+ validHandlers.Add(new HandlerConfigPair()
+ {
+ Handler = syncHandler,
+ Settings = config
+ });
+ }
+ }
+
+ return validHandlers;
+ }
+ }
+
+ public class HandlerConfigPair
+ {
+ public ISyncHandler Handler { get; set; }
+ public HandlerSettings Settings { get; set; }
}
}
diff --git a/uSync8.BackOffice/SyncHandlers/SyncHandlerTreeBase.cs b/uSync8.BackOffice/SyncHandlers/SyncHandlerTreeBase.cs
index c1160615..4a406770 100644
--- a/uSync8.BackOffice/SyncHandlers/SyncHandlerTreeBase.cs
+++ b/uSync8.BackOffice/SyncHandlers/SyncHandlerTreeBase.cs
@@ -10,6 +10,7 @@
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.Core;
using uSync8.Core.Extensions;
@@ -36,9 +37,8 @@ protected SyncHandlerTreeBase(
IProfilingLogger logger,
ISyncSerializer serializer,
ISyncTracker tracker,
- SyncFileService syncFileService,
- uSyncBackOfficeSettings settings)
- : base(entityService, logger, serializer, tracker, syncFileService, settings)
+ SyncFileService syncFileService)
+ : base(entityService, logger, serializer, tracker, syncFileService)
{
}
@@ -53,11 +53,11 @@ protected SyncHandlerTreeBase(
///
///
///
- protected override IEnumerable ImportFolder(string folder, uSyncHandlerSettings config, Dictionary updates, bool force)
+ protected override IEnumerable ImportFolder(string folder, HandlerSettings config, Dictionary updates, bool force)
{
// if not using flat, then directory structure is doing
// this for us.
- if (globalSettings.UseFlatStructure == false)
+ if (config.UseFlatStructure == false)
return base.ImportFolder(folder, config, updates, force);
List actions = new List();
@@ -103,7 +103,7 @@ protected override IEnumerable ImportFolder(string folder, uSyncHan
}
- public virtual IEnumerable ProcessPostImport(string folder, IEnumerable actions, uSyncHandlerSettings config)
+ public virtual IEnumerable ProcessPostImport(string folder, IEnumerable actions, HandlerSettings config)
{
if (actions == null || !actions.Any())
return null;
@@ -150,28 +150,28 @@ private XElement LoadNode(string path)
// path helpers
- virtual protected string GetItemFileName(IUmbracoEntity item)
+ virtual protected string GetItemFileName(IUmbracoEntity item, bool useGuid)
{
if (item != null)
{
- if (globalSettings.UseFlatStructure)
+ if (useGuid)
return item.Key.ToString();
- return item.Name.ToSafeFileName();
+ return item.Name.ToSafeFileName();
}
return Guid.NewGuid().ToString();
}
- override protected string GetItemPath(TObject item)
+ override protected string GetItemPath(TObject item, bool useGuid, bool isFlat)
{
- if (globalSettings.UseFlatStructure)
- return GetItemFileName((IUmbracoEntity)item);
+ if (isFlat)
+ return GetItemFileName((IUmbracoEntity)item, useGuid);
- return GetEntityPath((IUmbracoEntity)item);
+ return GetEntityPath((IUmbracoEntity)item, useGuid, true);
}
- protected string GetEntityPath(IUmbracoEntity item)
+ protected string GetEntityPath(IUmbracoEntity item, bool useGuid, bool isTop)
{
var path = string.Empty;
if (item != null)
@@ -181,11 +181,12 @@ protected string GetEntityPath(IUmbracoEntity item)
var parent = entityService.Get(item.ParentId);
if (parent != null)
{
- path = GetEntityPath(parent);
+ path = GetEntityPath(parent, useGuid, false);
}
}
- path = Path.Combine(path, GetItemFileName(item));
+ // we only want the guid file name at the top of the tree
+ path = Path.Combine(path, GetItemFileName(item, useGuid && isTop));
}
return path;
diff --git a/uSync8.BackOffice/uSync8.BackOffice.csproj b/uSync8.BackOffice/uSync8.BackOffice.csproj
index 25ce282e..53249317 100644
--- a/uSync8.BackOffice/uSync8.BackOffice.csproj
+++ b/uSync8.BackOffice/uSync8.BackOffice.csproj
@@ -219,6 +219,10 @@
+
+
+
+
@@ -246,7 +250,7 @@
-
+
diff --git a/uSync8.BackOffice/uSyncBackOfficeComposer.cs b/uSync8.BackOffice/uSyncBackOfficeComposer.cs
index 04e66af0..ecf14aa1 100644
--- a/uSync8.BackOffice/uSyncBackOfficeComposer.cs
+++ b/uSync8.BackOffice/uSyncBackOfficeComposer.cs
@@ -5,6 +5,7 @@
using System.Threading.Tasks;
using Umbraco.Core.Components;
using Umbraco.Core.Composing;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.BackOffice.SyncHandlers;
@@ -14,7 +15,8 @@ public class uSyncBackOfficeComposer : IUserComposer
{
public void Compose(Composition composition)
{
- composition.RegisterUnique();
+ composition.Configs.Add(() => new uSyncConfig());
+
composition.RegisterUnique();
composition.WithCollectionBuilder()
diff --git a/uSync8.BackOffice/uSyncBackOfficeSettings.cs b/uSync8.BackOffice/uSyncBackOfficeSettings.cs
deleted file mode 100644
index 9e9073fa..00000000
--- a/uSync8.BackOffice/uSyncBackOfficeSettings.cs
+++ /dev/null
@@ -1,241 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Configuration;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Xml.Linq;
-using System.Xml.XPath;
-using Umbraco.Core;
-using uSync8.BackOffice.SyncHandlers;
-using uSync8.Core.Extensions;
-
-namespace uSync8.BackOffice
-{
- public class uSyncBackOfficeSettings
- {
- public string rootFolder { get; set; } = "~/uSync/v8/";
-
- public bool UseFlatStructure { get; set; } = true;
- public bool ImportAtStartup { get; set; } = false;
-
- public bool ExportAtStartup { get; set; } = false;
- public bool ExportOnSave { get; set; } = true;
- public bool UseGuidNames { get; set; } = false;
-
- public List Handlers { get; set; } = new List();
-
- private string settingsFile = Umbraco.Core.IO.SystemDirectories.Config + "/uSync8.config";
-
- public void LoadSettings(SyncHandlerCollection syncHandlers)
- {
- this.Handlers = syncHandlers
- .Select(x => new uSyncHandlerConfig(x, true))
- .ToList();
-
- var node = GetSettingsFile();
- if (node == null)
- {
- SaveSettings();
- return; // everything will be default;
- }
-
- this.rootFolder = node.Element("Folder").ValueOrDefault(rootFolder);
- this.UseFlatStructure = node.Element("FlatFolders").ValueOrDefault(true);
- this.ImportAtStartup = node.Element("ImportAtStartup").ValueOrDefault(true);
- this.ExportAtStartup = node.Element("ExportAtStartup").ValueOrDefault(false);
- this.ExportOnSave = node.Element("ExportOnSave").ValueOrDefault(true);
- this.UseGuidNames = node.Element("UseGuidFilenames").ValueOrDefault(false);
-
- var handlerConfig = node.Element("Handlers");
- var defaultHandlerEnabled = handlerConfig.Attribute("EnableMissing").ValueOrDefault(false);
-
- if (this.Handlers != null && handlerConfig != null)
- {
- foreach (var handler in this.Handlers)
- {
- handler.Config.Enabled = defaultHandlerEnabled;
- handler.Config.GuidNames = this.UseGuidNames;
-
- var handlerNode = handlerConfig.Elements("Handler").FirstOrDefault(x => x.Attribute("Alias").ValueOrDefault(string.Empty) == handler.Alias);
- if (handlerNode != null)
- {
- LoadHandlerConfig(handlerNode, handler.Alias);
- }
- }
- }
-
- }
- public void SaveSettings()
- {
- var node = GetSettingsFile(true);
-
- node.CreateOrSetElement("Folder", rootFolder);
- node.CreateOrSetElement("FlatFolders", UseFlatStructure);
- node.CreateOrSetElement("ImportAtStartup", ImportAtStartup);
- node.CreateOrSetElement("ExportAtStartup", ExportAtStartup);
- node.CreateOrSetElement("ExportOnSave", ExportOnSave);
- node.CreateOrSetElement("UseGuidFilenames", UseGuidNames);
-
- if (this.Handlers != null)
- {
- var handlerConfig = node.Element("Handlers");
- if (handlerConfig == null)
- {
- handlerConfig = new XElement("Handlers",
- new XAttribute("EnableMissing", true));
- node.Add(handlerConfig);
- }
-
-
- foreach (var handler in Handlers)
- {
- var handlerNode = handlerConfig.Elements("Handler").FirstOrDefault(x => x.Attribute("Alias").Value == handler.Alias);
- if (handlerNode == null)
- {
- handlerNode = new XElement("Handler");
- handlerConfig.Add(handlerNode);
- }
-
- SaveHandlerConfig(handlerNode, handler);
- }
- }
-
- SaveSettingsFile(node);
- }
-
- #region Default Handler Loading Stuff
- public uSyncHandlerSettings LoadHandlerConfig(XElement node, string alias)
- {
- if (node == null) return null;
- var nodeAlias = node.Attribute("Alias").ValueOrDefault("unknown");
-
- if (!alias.InvariantEquals(nodeAlias)) return null;
-
- var settings = new uSyncHandlerSettings();
-
- settings.Enabled = node.Attribute("Enabled").ValueOrDefault(true);
- settings.GuidNames = node.Attribute("GuidNames").ValueOrDefault(this.UseGuidNames);
-
- var settingNode = node.Element("Settings");
- if (settingNode != null)
- {
- var handlerSettings = new Dictionary();
-
- foreach (var setting in settingNode.Elements("Add"))
- {
- var key = setting.Attribute("Key").ValueOrDefault(string.Empty);
- var value = setting.Attribute("Value").ValueOrDefault(string.Empty);
-
- if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(value))
- continue;
-
- handlerSettings.Add(key, value);
- }
-
- settings.Settings = handlerSettings;
- }
-
- return settings;
- }
-
- public void SaveHandlerConfig(XElement node, uSyncHandlerConfig config)
- {
- if (node == null) return;
-
- node.SetAttributeValue("Alias", config.Alias);
- node.SetAttributeValue("Enabled", config.Config.Enabled);
-
- if (config.Config.GuidNames != UseGuidNames)
- node.SetAttributeValue("GuidNames", config.Config.GuidNames);
-
- if (config.Config.Settings != null && config.Config.Settings.Any())
- {
- var settingNode = new XElement("Settings");
-
- foreach (var setting in config.Config.Settings)
- {
- settingNode.Add(new XElement("Add",
- new XAttribute("Key", setting.Key),
- new XAttribute("Value", setting.Value)));
- }
-
- var existing = node.Element("Settings");
- if (existing != null) existing.Remove();
-
- node.Add(settingNode);
- }
- }
-
- #endregion
-
- private XElement GetSettingsFile(bool loadIfBlank = false)
- {
- var filePath = Umbraco.Core.IO.IOHelper.MapPath(settingsFile);
- if (File.Exists(filePath))
- {
- var node = XElement.Load(filePath);
- var settingsNode = node.Element("BackOffice");
- if (settingsNode != null)
- return settingsNode;
-
- if (loadIfBlank)
- {
- node.Add(new XElement("BackOffice"));
- return node.Element("BackOffice");
- }
- else
- {
- return null;
- }
- }
-
- if (loadIfBlank)
- {
- var file = new XElement("uSync",
- new XElement("BackOffice"));
- return file.Element("BackOffice");
- }
-
- return null;
- }
-
- private void SaveSettingsFile(XElement node)
- {
- var root = node.Parent;
- if (root != null)
- {
- var filePath = Umbraco.Core.IO.IOHelper.MapPath(settingsFile);
- root.Save(filePath);
- }
- }
- }
-
- public class uSyncHandlerConfig
- {
- public string Alias { get; }
- public ISyncHandler Handler { get; private set; }
- public uSyncHandlerSettings Config { get; set; }
-
- public uSyncHandlerConfig(ISyncHandler handler, bool enabled)
- {
- Alias = handler.Alias;
- Handler = handler;
- Config = new uSyncHandlerSettings()
- {
- Enabled = enabled
- };
- }
- }
-
- public class uSyncHandlerSettings
- {
- public bool Enabled { get; set; }
- public string[] Actions { get; set; }
- public bool GuidNames { get; set; }
-
- public Dictionary Settings { get; set; } = new Dictionary();
-
- }
-}
diff --git a/uSync8.BackOffice/uSyncBackofficeComponent.cs b/uSync8.BackOffice/uSyncBackofficeComponent.cs
index 9623ecd4..67a3ca4a 100644
--- a/uSync8.BackOffice/uSyncBackofficeComponent.cs
+++ b/uSync8.BackOffice/uSyncBackofficeComponent.cs
@@ -3,8 +3,11 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Umbraco.Core;
using Umbraco.Core.Components;
+using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
+using uSync8.BackOffice.Configuration;
using uSync8.BackOffice.Services;
using uSync8.BackOffice.SyncHandlers;
@@ -16,22 +19,23 @@ public class uSyncBackofficeComponent : IComponent
private readonly SyncHandlerCollection syncHandlers;
private readonly SyncFileService syncFileService;
- private readonly uSyncBackOfficeSettings globalSettings;
+ private readonly uSyncSettings globalSettings;
private readonly uSyncService uSyncService;
public uSyncBackofficeComponent(
SyncHandlerCollection syncHandlers,
IProfilingLogger logger,
- SyncFileService fileService,
- uSyncBackOfficeSettings settings,
+ SyncFileService fileService,
uSyncService uSyncService)
{
+ globalSettings = Current.Configs.uSync();
+
this.syncHandlers = syncHandlers;
this.logger = logger;
this.syncFileService = fileService;
- this.globalSettings = settings;
this.uSyncService = uSyncService;
+
}
public void Initialize()
@@ -39,40 +43,29 @@ public void Initialize()
using (logger.DebugDuration("uSync Starting"))
{
- InitSettings();
-
InitBackOffice();
}
}
- private void InitSettings()
- {
- globalSettings.LoadSettings(syncHandlers);
- foreach(var syncHandler in globalSettings.Handlers)
- {
- syncHandler.Handler.DefaultConfig = syncHandler.Config;
- }
-
- }
-
private void InitBackOffice()
{
- if (globalSettings.ExportAtStartup || (globalSettings.ExportOnSave && !syncFileService.RootExists(globalSettings.rootFolder)))
+ if (globalSettings.ExportAtStartup || (globalSettings.ExportOnSave && !syncFileService.RootExists(globalSettings.RootFolder)))
{
- uSyncService.Export(globalSettings.rootFolder);
+ uSyncService.Export(globalSettings.RootFolder);
}
if (globalSettings.ImportAtStartup)
{
- uSyncService.Import(globalSettings.rootFolder,false);
+ uSyncService.Import(globalSettings.RootFolder,false);
}
if (globalSettings.ExportOnSave)
{
- foreach (var syncHandler in globalSettings.Handlers.Where(x => x.Config.Enabled))
+ var handlers = syncHandlers.GetValidHandlers("Save", globalSettings);
+ foreach (var syncHandler in handlers)
{
logger.Debug($"Starting up Handler {syncHandler.Handler.Name}");
- syncHandler.Handler.Initialize();
+ syncHandler.Handler.Initialize(syncHandler.Settings);
}
}
diff --git a/uSync8.Core/Models/uSyncChange.cs b/uSync8.Core/Models/uSyncChange.cs
index 34d508bb..61dbe80e 100644
--- a/uSync8.Core/Models/uSyncChange.cs
+++ b/uSync8.Core/Models/uSyncChange.cs
@@ -1,6 +1,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -18,6 +19,47 @@ public class uSyncChange
[JsonConverter(typeof(StringEnumConverter))]
public ChangeDetailType Change { get; set; }
+
+ public static uSyncChange Create(string path, string name, string newValue, bool useNew = true)
+ {
+ return new uSyncChange()
+ {
+ Change = ChangeDetailType.Create,
+ Path = path,
+ Name = name,
+ OldValue = "",
+ NewValue = useNew ? newValue : "New Property"
+ };
+ }
+
+ public static uSyncChange Delete(string path, string name, string oldValue, bool useOld = true)
+ {
+ return new uSyncChange()
+ {
+ Change = ChangeDetailType.Delete,
+ Path = path,
+ Name = name,
+ OldValue = useOld ? oldValue : "Missing Property",
+ NewValue = ""
+ };
+ }
+
+ public static uSyncChange Update(string path, string name, string oldValue, string newValue)
+ {
+ return new uSyncChange()
+ {
+ Name = name,
+ Path = path,
+ Change = ChangeDetailType.Update,
+ NewValue = string.IsNullOrEmpty(newValue) ? "(Blank)" : newValue,
+ OldValue = string.IsNullOrEmpty(oldValue) ? "(Blank)" : oldValue
+ };
+ }
+
+ public static uSyncChange Update(string path, string name, TObject oldValue, TObject newValue)
+ {
+ return Update(path, name, oldValue.ToString(), newValue.ToString());
+ }
}
public enum ChangeDetailType
diff --git a/uSync8.Core/Serialization/Serializers/ContentTypeBaseSerializer.cs b/uSync8.Core/Serialization/Serializers/ContentTypeBaseSerializer.cs
index b688283e..ab89e040 100644
--- a/uSync8.Core/Serialization/Serializers/ContentTypeBaseSerializer.cs
+++ b/uSync8.Core/Serialization/Serializers/ContentTypeBaseSerializer.cs
@@ -151,7 +151,7 @@ protected void DeserializeBase(TObject item, XElement node)
var info = node.Element("Info");
if (info == null) return;
- var alias = info.GetAlias();
+ var alias = node.GetAlias();
if (item.Alias != alias)
item.Alias = alias;
diff --git a/uSync8.Core/Serialization/Serializers/MacroSerializer.cs b/uSync8.Core/Serialization/Serializers/MacroSerializer.cs
index 474d0ae0..3d72371d 100644
--- a/uSync8.Core/Serialization/Serializers/MacroSerializer.cs
+++ b/uSync8.Core/Serialization/Serializers/MacroSerializer.cs
@@ -18,7 +18,7 @@ public class MacroSerializer : SyncSerializerBase, ISyncSerializer DeserializeCore(XElement node)
{
+ var changes = new List();
+
if (node.Element("Name") == null)
throw new ArgumentNullException("XML missing Name parameter");
@@ -40,7 +42,6 @@ protected override SyncAttempt DeserializeCore(XElement node)
item = macroService.GetById(key);
-
if (item == null)
{
item = macroService.GetByAlias(alias);
@@ -49,6 +50,7 @@ protected override SyncAttempt DeserializeCore(XElement node)
if (item == null)
{
item = new Macro(alias, name, macroSource, macroType);
+ changes.Add(uSyncChange.Create(alias, name, "New Macro"));
}
item.Name = name;
@@ -56,8 +58,9 @@ protected override SyncAttempt DeserializeCore(XElement node)
item.MacroSource = macroSource;
item.MacroType = macroType;
+
item.UseInEditor = node.Element("UseInEditor").ValueOrDefault(false);
- item.DontRender = node.Element("DontRender").ValueOrDefault(false);
+ item.DontRender = node.Element("DontRender").ValueOrDefault(false);
item.CacheByMember = node.Element("CachedByMember").ValueOrDefault(false);
item.CacheByPage = node.Element("CachedByPage").ValueOrDefault(false);
item.CacheDuration = node.Element("CachedDuration").ValueOrDefault(0);
@@ -65,29 +68,64 @@ protected override SyncAttempt DeserializeCore(XElement node)
var properties = node.Element("Properties");
if (properties != null && properties.HasElements)
{
- foreach(var propNode in properties.Elements("Property"))
+ foreach (var propNode in properties.Elements("Property"))
{
var propertyAlias = propNode.Element("Alias").ValueOrDefault(string.Empty);
var editorAlias = propNode.Element("EditorAlias").ValueOrDefault(string.Empty);
var propertyName = propNode.Element("Name").ValueOrDefault(string.Empty);
var sortOrder = propNode.Element("SortOrder").ValueOrDefault(0);
+ var propPath = $"{alias}: {propertyName}";
+
if (item.Properties.ContainsKey(propertyAlias))
{
item.Properties.UpdateProperty(propertyAlias, propertyName, sortOrder, editorAlias);
}
else
{
+ changes.Add(uSyncChange.Create(propPath, "Property", propertyAlias));
item.Properties.Add(new MacroProperty(propertyAlias, propertyName, sortOrder, editorAlias));
}
}
+
}
+ RemoveOrphanProperties(item, properties);
+
macroService.Save(item);
- return SyncAttempt.Succeed(item.Name, item, ChangeType.Import);
+ var attempt = SyncAttempt.Succeed(item.Name, item, ChangeType.Import);
+ if (changes.Any())
+ attempt.Details = changes;
+
+ return attempt;
}
+ private void RemoveOrphanProperties(IMacro item, XElement properties)
+ {
+ var removalKeys = new List();
+ if (properties == null)
+ {
+ removalKeys = item.Properties.Keys.ToList();
+ }
+ else
+ {
+ var aliases = properties.Elements("Property")
+ .Where(x => x.Element("Alias").ValueOrDefault(string.Empty) != string.Empty)
+ .Select(x => x.Element("Alias").ValueOrDefault(string.Empty))
+ .ToList();
+
+ removalKeys = item.Properties.Values.Where(x => !aliases.Contains(x.Alias))
+ .Select(x => x.Alias)
+ .ToList();
+ }
+
+ foreach (var propKey in removalKeys)
+ {
+ item.Properties.Remove(propKey);
+ }
+
+ }
protected override SyncAttempt SerializeCore(IMacro item)
{
@@ -103,14 +141,14 @@ protected override SyncAttempt SerializeCore(IMacro item)
node.Add(new XElement("CachedDuration", item.CacheDuration));
var properties = new XElement("Properties");
- foreach(var property in item.Properties)
+ foreach (var property in item.Properties)
{
properties.Add(new XElement("Property",
new XElement("Key", property.Key),
- new XElement("Name", property.Name)),
+ new XElement("Name", property.Name),
new XElement("Alias", property.Alias),
new XElement("SortOrder", property.SortOrder),
- new XElement("EditorAlias", property.EditorAlias));
+ new XElement("EditorAlias", property.EditorAlias)));
}
node.Add(properties);
diff --git a/uSync8.Core/Serialization/SyncSerializerBase.cs b/uSync8.Core/Serialization/SyncSerializerBase.cs
index 7b9f9fe6..3e5c1f66 100644
--- a/uSync8.Core/Serialization/SyncSerializerBase.cs
+++ b/uSync8.Core/Serialization/SyncSerializerBase.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections;
+using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Xml.Linq;
@@ -200,5 +202,6 @@ private string MakeHash(XElement node)
protected virtual XElement CleanseNode(XElement node) => node;
+
}
}
diff --git a/uSync8.Core/Tracking/Impliment/ContentTypeBaseTracker.cs b/uSync8.Core/Tracking/Impliment/ContentTypeBaseTracker.cs
new file mode 100644
index 00000000..efeb72ce
--- /dev/null
+++ b/uSync8.Core/Tracking/Impliment/ContentTypeBaseTracker.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Umbraco.Core.Models;
+using uSync8.Core.Serialization;
+
+namespace uSync8.Core.Tracking.Impliment
+{
+ public class ContentTypeBaseTracker : SyncBaseTracker
+ where TObject : IContentTypeBase
+ {
+ public ContentTypeBaseTracker(ISyncSerializer serializer) : base(serializer)
+ {
+ }
+
+ protected override TrackedItem TrackChanges()
+ {
+ return new TrackedItem("", true)
+ {
+ Children = new List()
+ {
+ new TrackedItem("", "/Info")
+ {
+ Children = new List()
+ {
+ new TrackedItem("Name", "/Name", true),
+ new TrackedItem("Icon", "/Icon", true),
+ new TrackedItem("Thumbnail", "/Thumbnail", true),
+ new TrackedItem("Description", "/Description", true),
+ new TrackedItem("AllowAtRoot", "/AllowAtRoot", true),
+ new TrackedItem("IsListView", "/IsListView", true),
+ new TrackedItem("Variations", "/Variations", true),
+ new TrackedItem("IsElement", "/IsElement", true),
+ }
+ },
+ new TrackedItem("", "/GenericProperties", false)
+ {
+ Children = new List()
+ {
+ new TrackedItem("Property", "/GenericProperty")
+ {
+ Repeating = new RepeatingInfo("Key", "/GenericProperty", "Name"),
+ Children = new List()
+ {
+ new TrackedItem("Key", "/Key", true),
+ new TrackedItem("Name", "/Name", true),
+ new TrackedItem("Alias", "/Alias", true),
+ new TrackedItem("Definition", "/Definition", true),
+ new TrackedItem("Type", "/Type", true),
+ new TrackedItem("Mandatory", "/Mandatory", true),
+ new TrackedItem("Validation", "/Validation", true),
+ new TrackedItem("Description", "/Description", true),
+ new TrackedItem("SortOrder", "/SortOrder", true),
+ new TrackedItem("Tab", "/Tab", true)
+ }
+ }
+ }
+ },
+ new TrackedItem("", "/Tabs", false)
+ {
+ Children = new List()
+ {
+ new TrackedItem("Tab", "/Tab")
+ {
+ Repeating = new RepeatingInfo("Key", "/Tab", "Caption"),
+ Children = new List()
+ {
+ new TrackedItem("Key", "/Key", true),
+ new TrackedItem("Caption", "/Caption", true),
+ new TrackedItem("SortOrder", "/SortOrder", true)
+ }
+ }
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/uSync8.Core/Tracking/Impliment/ContentTypeTracker.cs b/uSync8.Core/Tracking/Impliment/ContentTypeTracker.cs
index c3793967..b4875cc5 100644
--- a/uSync8.Core/Tracking/Impliment/ContentTypeTracker.cs
+++ b/uSync8.Core/Tracking/Impliment/ContentTypeTracker.cs
@@ -8,7 +8,7 @@
namespace uSync8.Core.Tracking.Impliment
{
- public class ContentTypeTracker : SyncBaseTracker, ISyncTracker
+ public class ContentTypeTracker : ContentTypeBaseTracker, ISyncTracker
{
public ContentTypeTracker(ISyncSerializer serializer) : base(serializer)
{
@@ -16,7 +16,56 @@ public ContentTypeTracker(ISyncSerializer serializer) : base(seria
protected override TrackedItem TrackChanges()
{
- return new TrackedItem(serializer.ItemType);
+ var tracker = base.TrackChanges();
+ tracker.Children[0]
+ .Children.Add(new TrackedItem("DefaultTemplate", "/DefaultTemplate", true));
+
+ tracker.Children[0]
+ .Children.Add(new TrackedItem("Parent", "/Master", true));
+
+ tracker.Children[0]
+ .Children.Add(new TrackedItem("AllowedTemplates", "/AllowedTemplates")
+ {
+ Children = new List()
+ {
+ new TrackedItem("Template", "/Template")
+ {
+ Repeating = new RepeatingInfo("Key", string.Empty, "Template")
+ {
+ KeyIsAttribute = true
+ }
+ }
+ }
+ });
+
+ tracker.Children[0]
+ .Children.Add(new TrackedItem("Compositions", "/Compositions")
+ {
+ Children = new List()
+ {
+ new TrackedItem("Composition", "/Composition")
+ {
+ Repeating = new RepeatingInfo("Key", string.Empty, "Template")
+ {
+ KeyIsAttribute = true
+ }
+ }
+ }
+ });
+
+ tracker.Children.Add(
+ new TrackedItem("Structure", "/Structure")
+ {
+ Children = new List()
+ {
+ new TrackedItem("ContentType", "/ContentType")
+ {
+ Repeating = new RepeatingInfo(string.Empty, string.Empty, string.Empty)
+ }
+ }
+ });
+
+ return tracker;
}
}
}
diff --git a/uSync8.Core/Tracking/Impliment/DataTypeTracker.cs b/uSync8.Core/Tracking/Impliment/DataTypeTracker.cs
index da7fb109..4a5377d0 100644
--- a/uSync8.Core/Tracking/Impliment/DataTypeTracker.cs
+++ b/uSync8.Core/Tracking/Impliment/DataTypeTracker.cs
@@ -17,7 +17,7 @@ public DataTypeTracker(ISyncSerializer serializer)
protected override TrackedItem TrackChanges()
{
- return new TrackedItem(serializer.ItemType)
+ return new TrackedItem(serializer.ItemType, true)
{
Children = new List()
{
@@ -25,10 +25,10 @@ protected override TrackedItem TrackChanges()
{
Children = new List()
{
- new TrackedItem("Name", "/Info/Name", true),
- new TrackedItem("EditorAlias", "/Info/EditorAlias", true),
- new TrackedItem("DatabaseType", "/Info/DatabaseType", true),
- new TrackedItem("SortOrder", "/Info/SortOrder")
+ new TrackedItem("Name", "/Name", true),
+ new TrackedItem("EditorAlias", "/EditorAlias", true),
+ new TrackedItem("DatabaseType", "/DatabaseType", true),
+ new TrackedItem("SortOrder", "/SortOrder")
}
},
new TrackedItem("Config", "/Config", true)
diff --git a/uSync8.Core/Tracking/Impliment/LanguageTracker.cs b/uSync8.Core/Tracking/Impliment/LanguageTracker.cs
index 692f501f..3d6273b4 100644
--- a/uSync8.Core/Tracking/Impliment/LanguageTracker.cs
+++ b/uSync8.Core/Tracking/Impliment/LanguageTracker.cs
@@ -16,7 +16,16 @@ public LanguageTracker(ISyncSerializer serializer) : base(serializer)
protected override TrackedItem TrackChanges()
{
- return new TrackedItem(serializer.ItemType);
+ return new TrackedItem(serializer.ItemType, true)
+ {
+ Children = new List()
+ {
+ new TrackedItem("IsoCode", "/IsoCode", true),
+ new TrackedItem("CultureName", "/CultureName", true),
+ new TrackedItem("Mandatory", "/IsMandatory", true),
+ new TrackedItem("Default Lanaguage", "/IsDefault", true),
+ }
+ };
}
}
}
diff --git a/uSync8.Core/Tracking/Impliment/MacroTracker.cs b/uSync8.Core/Tracking/Impliment/MacroTracker.cs
index d6f39769..ec39f088 100644
--- a/uSync8.Core/Tracking/Impliment/MacroTracker.cs
+++ b/uSync8.Core/Tracking/Impliment/MacroTracker.cs
@@ -16,7 +16,40 @@ public MacroTracker(ISyncSerializer serializer) : base(serializer)
protected override TrackedItem TrackChanges()
{
- return new TrackedItem(serializer.ItemType);
+ return new TrackedItem(serializer.ItemType, true)
+ {
+ Children = new List()
+ {
+ new TrackedItem("Name", "/Name", true),
+ new TrackedItem("Source", "/MacroSource", true),
+ new TrackedItem("Type", "/MacroType", true),
+ new TrackedItem("Use In Editor", "/UseInEditor", true),
+ new TrackedItem("Don't Render in Editor", "/DontRender", true),
+ new TrackedItem("Cache By Member", "/CachedByMember", true),
+ new TrackedItem("Cache By Page", "/CachedByPage", true),
+ new TrackedItem("Cache Duration", "/CachedDuration", true),
+
+ new TrackedItem("", "/Properties", false)
+ {
+ Children = new List()
+ {
+ new TrackedItem("Property", "/Property")
+ {
+ Repeating = new RepeatingInfo("Key", "/Property", "Name"),
+ Children = new List()
+ {
+ new TrackedItem("Key", "/Key", true),
+ new TrackedItem("Name", "/Name", true),
+ new TrackedItem("Alias", "/Alias", true),
+ new TrackedItem("SortOrder", "/SortOrder", true),
+ new TrackedItem("EditorAlias", "/EditorAlias", true)
+ }
+ }
+ }
+ }
+ }
+
+ };
}
}
}
diff --git a/uSync8.Core/Tracking/Impliment/MediaTypeTracker.cs b/uSync8.Core/Tracking/Impliment/MediaTypeTracker.cs
index c0eda398..482f232a 100644
--- a/uSync8.Core/Tracking/Impliment/MediaTypeTracker.cs
+++ b/uSync8.Core/Tracking/Impliment/MediaTypeTracker.cs
@@ -8,7 +8,7 @@
namespace uSync8.Core.Tracking.Impliment
{
- public class MediaTypeTracker : SyncBaseTracker, ISyncTracker
+ public class MediaTypeTracker : ContentTypeBaseTracker, ISyncTracker
{
public MediaTypeTracker(ISyncSerializer serializer) : base(serializer)
{
@@ -16,7 +16,21 @@ public MediaTypeTracker(ISyncSerializer serializer) : base(serialize
protected override TrackedItem TrackChanges()
{
- return new TrackedItem(serializer.ItemType);
+ var tracker = base.TrackChanges();
+
+ tracker.Children.Add(
+ new TrackedItem("Structure", "/Structure")
+ {
+ Children = new List()
+ {
+ new TrackedItem("MediaType", "/MediaType")
+ {
+ Repeating = new RepeatingInfo(string.Empty, string.Empty, string.Empty)
+ }
+ }
+ });
+
+ return tracker;
}
}
}
diff --git a/uSync8.Core/Tracking/Impliment/MemberTypeTracker.cs b/uSync8.Core/Tracking/Impliment/MemberTypeTracker.cs
index eed32ea4..c3880c8e 100644
--- a/uSync8.Core/Tracking/Impliment/MemberTypeTracker.cs
+++ b/uSync8.Core/Tracking/Impliment/MemberTypeTracker.cs
@@ -8,7 +8,7 @@
namespace uSync8.Core.Tracking.Impliment
{
- public class MemberTypeTracker : SyncBaseTracker, ISyncTracker
+ public class MemberTypeTracker : ContentTypeBaseTracker, ISyncTracker
{
public MemberTypeTracker(ISyncSerializer serializer) : base(serializer)
{
@@ -16,7 +16,25 @@ public MemberTypeTracker(ISyncSerializer serializer) : base(seriali
protected override TrackedItem TrackChanges()
{
- return new TrackedItem(serializer.ItemType);
+ var tracker = base.TrackChanges();
+
+ // the membership one is a bit of a hack
+ // because we want to add new properties in
+ // the repeating properties, but it works.
+ var properties = tracker.Children.FirstOrDefault(x => x.Path == "/GenericProperties");
+ if (properties != null)
+ {
+ properties.Children[0]
+ .Children.Add(new TrackedItem("CanEdit", "/CanEdit", true));
+ properties.Children[0]
+ .Children.Add(new TrackedItem("CanView", "/CanView", true));
+ properties.Children[0]
+ .Children.Add(new TrackedItem("IsSensitive", "/IsSensitive", true));
+ }
+
+
+
+ return tracker;
}
}
}
diff --git a/uSync8.Core/Tracking/Impliment/TemplateTracker.cs b/uSync8.Core/Tracking/Impliment/TemplateTracker.cs
index 95f5ebb2..b986d660 100644
--- a/uSync8.Core/Tracking/Impliment/TemplateTracker.cs
+++ b/uSync8.Core/Tracking/Impliment/TemplateTracker.cs
@@ -20,7 +20,7 @@ public TemplateTracker(ISyncSerializer serializer)
protected override TrackedItem TrackChanges()
{
- return new TrackedItem(serializer.ItemType)
+ return new TrackedItem(serializer.ItemType, true)
{
Children = new List
{
diff --git a/uSync8.Core/Tracking/SyncBaseTracker.cs b/uSync8.Core/Tracking/SyncBaseTracker.cs
index b06bc0e1..4bff32f8 100644
--- a/uSync8.Core/Tracking/SyncBaseTracker.cs
+++ b/uSync8.Core/Tracking/SyncBaseTracker.cs
@@ -10,7 +10,7 @@
namespace uSync8.Core.Tracking
{
- public abstract class SyncBaseTracker
+ public abstract class SyncBaseTracker
where TObject : IEntity
{
protected readonly ISyncSerializer serializer;
@@ -39,11 +39,12 @@ public virtual IEnumerable GetChanges(XElement node)
var changes = TrackChanges();
var item = serializer.GetItem(node);
- if (item != null) {
+ if (item != null)
+ {
var current = serializer.Serialize(item);
if (current.Success)
{
- return CalculateChanges(changes, current.Item, node);
+ return CalculateChanges(changes, current.Item, node, "", "");
}
}
@@ -51,115 +52,252 @@ public virtual IEnumerable GetChanges(XElement node)
}
- private IEnumerable CalculateChanges(TrackedItem change, XElement current, XElement target)
+ private IEnumerable CalculateChanges(TrackedItem change, XElement current, XElement target, string name, string path)
{
- var updates = new List();
-
if (change == null) return Enumerable.Empty();
- if (string.IsNullOrWhiteSpace(change.Name) || string.IsNullOrWhiteSpace(change.Path))
- return Enumerable.Empty();
+ var changePath = GetChangePath(path, change.Path);
+ var changeName = GetChangeName(name, change.Name);
+
+ if (change.Repeating == null)
+ return CalculateSingleChange(change, current, target, changeName, changePath);
+
- var currentNode = current.XPathSelectElement(change.Path);
- var targetNode = target.XPathSelectElement(change.Path);
+ return CalculateRepeatingChanges(change, current, target, changeName, changePath);
+ }
+
+ private IEnumerable CalculateSingleChange(TrackedItem change, XElement current, XElement target, string name, string path)
+ {
+ var updates = new List();
+
+ var currentNode = current;
+ var targetNode = target;
- if (currentNode == null)
+ if (!string.IsNullOrEmpty(path))
{
- updates.Add(new uSyncChange()
+ currentNode = current.XPathSelectElement(path);
+ targetNode = target.XPathSelectElement(path);
+
+ if (currentNode == null)
{
- Change = ChangeDetailType.Create,
- Path = change.Path,
- Name = change.Name,
- OldValue = change.CompareValue ? targetNode.ValueOrDefault(string.Empty) : "New Property",
- NewValue = ""
- });
- }
+ return uSyncChange.Create(path, name, targetNode.ValueOrDefault(string.Empty), change.CompareValue)
+ .AsEnumerableOfOne();
- if (targetNode == null)
- {
- // its a delete (not in target)
- updates.Add(new uSyncChange()
+ }
+
+ if (targetNode == null)
+ {
+ // its a delete (not in target)
+ return uSyncChange.Delete(path, name, currentNode.ValueOrDefault(string.Empty), change.CompareValue)
+ .AsEnumerableOfOne();
+ }
+
+ // this happens if both exist, we compare values in them.
+
+ if (change.CompareValue)
+ {
+ // actual change
+ updates.AddNotNull(Compare(path, name,
+ currentNode.ValueOrDefault(string.Empty),
+ targetNode.ValueOrDefault(string.Empty)));
+ }
+
+ if (change.Attributes != null && change.Attributes.Any())
{
- Change = ChangeDetailType.Delete,
- Path = change.Path,
- Name = change.Name,
- OldValue = change.CompareValue ? currentNode.ValueOrDefault(string.Empty) : "Missing Property",
- NewValue = ""
- });
+ foreach (var attribute in change.Attributes)
+ {
+ var currentValue = currentNode.Attribute(attribute).ValueOrDefault(string.Empty);
+ var targetValue = targetNode.Attribute(attribute).ValueOrDefault(string.Empty);
+ updates.AddNotNull(Compare(path, $"{name} [{attribute}]", currentValue, targetValue));
+ }
+ }
}
- if (change.CompareValue)
+ if (change.Children != null && change.Children.Any())
{
- // actual change
- updates.AddNotNull(Compare(change.Name, change.Path,
- currentNode.ValueOrDefault(string.Empty),
- targetNode.ValueOrDefault(string.Empty)));
+ foreach (var child in change.Children)
+ {
+ updates.AddRange(CalculateChanges(child, currentNode, targetNode, name, path));
+ }
}
- if (change.Attributes != null && change.Attributes.Any())
+ return updates;
+ }
+
+ ///
+ /// works out changes when we have a repeating block (e.g all the properties on a content type)
+ ///
+ private IEnumerable CalculateRepeatingChanges(TrackedItem change, XElement current, XElement target, string name, string path)
+ {
+ var updates = new List();
+
+ var currentItems = current.XPathSelectElements(path);
+ var targetItems = target.XPathSelectElements(path);
+
+ // loop through the nodes in the current item
+ foreach (var currentNode in currentItems)
{
- foreach(var attribute in change.Attributes)
+ var currentNodePath = path;
+ var currentNodeName = name;
+
+ XElement targetNode = null;
+
+
+ // if the key is blank we just compare the values in the elements
+ if (string.IsNullOrWhiteSpace(change.Repeating.Key))
+ {
+ targetNode = targetItems.FirstOrDefault(x => x.Value == currentNode.Value);
+ }
+ else
+ {
+ // we need to find the current key value
+ var currentKey = GetKeyValue(currentNode, change.Repeating.Key, change.Repeating.KeyIsAttribute);
+ if (currentKey == string.Empty) continue;
+
+ // now we need to make the XPath for the children this will be [key = ''] or [@key ='']
+ // depending if its an attribute or element key
+ currentNodePath += MakeKeyPath(change.Repeating.Key, currentKey, change.Repeating.KeyIsAttribute);
+ if (!string.IsNullOrWhiteSpace(change.Repeating.Name))
+ currentNodeName += $": {currentNode.Element(change.Repeating.Name).ValueOrDefault(change.Repeating.Value)}";
+
+ // now see if we can find that node in the target elements we have loaded
+ targetNode = GetTarget(targetItems, change.Repeating.Key, currentKey, change.Repeating.KeyIsAttribute);
+ }
+
+ if (targetNode == null)
+ {
+ // no target, this element will get deleted
+ var oldValue = currentNode.Value;
+ if (!string.IsNullOrWhiteSpace(change.Repeating.Name))
+ {
+ oldValue = $"{currentNode.Element(change.Repeating.Name).ValueOrDefault(string.Empty)}";
+ }
+
+ updates.Add(uSyncChange.Delete(path, name, oldValue));
+ continue;
+ }
+
+ // check all the children of the current and target for changes
+ if (change.Children != null && change.Children.Any())
{
- var currentValue = currentNode.Attribute(attribute).ValueOrDefault(string.Empty);
- var targetValue = targetNode.Attribute(attribute).ValueOrDefault(string.Empty);
- updates.AddNotNull(Compare($"{change.Name} [{attribute}]", change.Path, currentValue, targetValue));
+ foreach (var child in change.Children)
+ {
+ updates.AddRange(CalculateChanges(child, currentNode, targetNode, currentNodeName, currentNodePath));
+ }
+ }
+ else
+ {
+ // if there are no children, they we are comparing the actual text of the nodes
+ updates.AddNotNull(Compare(path, name,
+ currentNode.ValueOrDefault(string.Empty),
+ targetNode.ValueOrDefault(string.Empty)));
}
}
- if (change.Children != null && change.Children.Any())
+ // look for things in target but not current (for they will be removed)
+ List missing = new List();
+
+ if (string.IsNullOrWhiteSpace(change.Repeating.Key))
+ {
+ missing = targetItems.Where(x => !currentItems.Any(t => t.Value == x.Value))
+ .ToList();
+ }
+ else
{
- foreach(var child in change.Children)
+ missing = targetItems.Where(x =>
+ !currentItems.Any(t => t.Element(change.Repeating.Key).ValueOrDefault(string.Empty) == x.Element(change.Repeating.Key).ValueOrDefault(string.Empty)))
+ .ToList();
+ }
+
+ if (missing.Any())
+ {
+ foreach (var missingItem in missing)
{
- updates.AddRange(CalculateChanges(child, current, target));
+ var oldValue = missingItem.Value;
+ if (!string.IsNullOrWhiteSpace(change.Repeating.Name))
+ oldValue = $"{missingItem.Element(change.Repeating.Name).ValueOrDefault(string.Empty)}";
+
+ updates.Add(uSyncChange.Create(path, name, oldValue));
}
}
return updates;
}
-
- protected uSyncChange Compare(string name, string path, string current, string target)
+ protected uSyncChange Compare(string path, string name, string current, string target)
{
if (current == target) return null;
+ return uSyncChange.Update(path, name, current, target);
+ }
+
+ private uSyncChange Compare(string path, string name, TValue current, TValue target)
+ {
+ if (current.Equals(target)) return null;
+ return Compare(path, name, current.ToString(), target.ToString());
+ }
+
+ private string GetChangePath(string path, string child)
+ {
+ return path + child.Replace("//", "/");
+ }
- return new uSyncChange()
+ private string GetChangeName(string parent, string name)
+ {
+ if (!string.IsNullOrWhiteSpace(parent))
+ return $"{parent}: " + name;
+
+ return name;
+ }
+
+ private string GetKeyValue(XElement node, string key, bool isAttribute)
+ {
+ if (isAttribute)
{
- Name = name,
- Path = path,
- Change = ChangeDetailType.Update,
- NewValue = target,
- OldValue = current
- };
+ return node.Attribute(key).ValueOrDefault(string.Empty);
+ }
+
+ return node.Element(key).ValueOrDefault(string.Empty);
}
- private uSyncChange Compare(string name, string path, TValue current, TValue target)
+ private string MakeKeyPath(string key, string keyValue, bool isAttribute)
{
- if (current.Equals(target)) return null;
+ if (isAttribute)
+ {
+ return $"[@{key} = '{keyValue}']";
+ }
- return Compare(name, path, current.ToString(), target.ToString());
+ return $"[{key} = '{keyValue}']";
}
- protected virtual bool XmlMatches(XElement oldNode, XElement newNode)
+ private XElement GetTarget(IEnumerable items, string key, string value, bool isAttribute)
{
- return false;
+ if (isAttribute)
+ return items.FirstOrDefault(x => x.Attribute(key).ValueOrDefault(string.Empty) == value);
+
+ return items.FirstOrDefault(x => x.Element(key).ValueOrDefault(string.Empty) == value);
}
}
public class TrackedItem
{
- public TrackedItem(string name)
+ private TrackedItem(string name)
{
Name = name;
Path = "/";
+ }
- Attributes = new List
+ public TrackedItem(string name, bool root)
+ : this(name)
+ {
+ if (root == true)
{
- "Key",
- "Alias"
- };
-
- Children = new List();
+ Attributes = new List
+ {
+ "Key",
+ "Alias"
+ };
+ }
}
public TrackedItem(string name, string path)
@@ -170,15 +308,50 @@ public TrackedItem(string name, string path)
}
public TrackedItem(string name, string path, bool compareValue)
- :this(name, path)
+ : this(name, path)
{
CompareValue = compareValue;
}
+ public RepeatingInfo Repeating { get; set; }
+
public bool CompareValue { get; set; }
public string Path { get; set; }
public string Name { get; set; }
- public List Attributes { get; set; }
- public List Children { get; set; }
+ public List Attributes { get; set; } = new List();
+ public List Children { get; set; } = new List();
+ }
+
+ public class RepeatingInfo
+ {
+ public RepeatingInfo(string key, string value, string name)
+ {
+ Key = key;
+ Value = value;
+ Name = name;
+ }
+
+ ///
+ /// Element used to match items in a collection of nodes
+ /// (e.g Key)
+ ///
+ public string Key { get; set; }
+
+ ///
+ /// The repeating element name
+ /// (e.g GenericProperty)
+ ///
+ public string Value { get; set; }
+
+ ///
+ /// the node we use to display the name of any item in the
+ /// repeater (e.g Alias)
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// indicates if the key is actually an attribute on the node.
+ ///
+ public bool KeyIsAttribute { get; set; }
}
}
diff --git a/uSync8.Core/uSync8.Core.csproj b/uSync8.Core/uSync8.Core.csproj
index 4964d6b6..6abdd9b7 100644
--- a/uSync8.Core/uSync8.Core.csproj
+++ b/uSync8.Core/uSync8.Core.csproj
@@ -147,6 +147,7 @@
+
diff --git a/uSync8.Site/App_Plugins/uSync8/actions.html b/uSync8.Site/App_Plugins/uSync8/actions.html
new file mode 100644
index 00000000..aa768c71
--- /dev/null
+++ b/uSync8.Site/App_Plugins/uSync8/actions.html
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{vm.status.Message}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Type
+
+
+ Name
+
+
+ Change
+
+
+ Message
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{vm.getTypeName(result.ItemType)}}
+
+
+ {{result.Name}}
+
+
+ {{result.Change}}
+
+
+ {{result.Message}}
+
+
+
+
+
+
+
+
+
+
+
+
Name
+
Old Value
+
New Value
+
+
+
+
+
+
+
+ {{detail.Name}}
+
+
+ {{detail.OldValue}}
+
+
+ {{detail.NewValue}}
+
+
+ {{detail.Change}}
+
+
+
+
+
+
+
+
+
+
No Changes
+
+
+
+
diff --git a/uSync8.Site/App_Plugins/uSync8/dashboard.html b/uSync8.Site/App_Plugins/uSync8/dashboard.html
index eb4799dc..cda0fd01 100644
--- a/uSync8.Site/App_Plugins/uSync8/dashboard.html
+++ b/uSync8.Site/App_Plugins/uSync8/dashboard.html
@@ -11,145 +11,167 @@ uSync 8
+ action="vm.toggleSettings()"
+ ng-if="!vm.settingsView">
+
+