diff --git a/src/Umbraco.Core/Models/DataTypeDefinition.cs b/src/Umbraco.Core/Models/DataTypeDefinition.cs index 1b7c9254f2..ba36c88a2a 100644 --- a/src/Umbraco.Core/Models/DataTypeDefinition.cs +++ b/src/Umbraco.Core/Models/DataTypeDefinition.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.ComponentModel; using System.Reflection; using System.Runtime.Serialization; +using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Core.Models { @@ -34,8 +36,15 @@ namespace Umbraco.Core.Models public DataTypeDefinition(int parentId, Guid controlId) { _parentId = parentId; - _propertyEditorAlias = LegacyPropertyEditorIdToAliasConverter.GetAliasFromLegacyId(controlId, true); - + + _propertyEditorAlias = LegacyPropertyEditorIdToAliasConverter.GetAliasFromLegacyId(controlId, false); + if (_propertyEditorAlias == null) + { + //convert to Label! + LogHelper.Warn("Could not find a GUID -> Alias mapping for the legacy property editor with id " + controlId + ". The DataType has been converted to a Label."); + _propertyEditorAlias = Constants.PropertyEditors.NoEditAlias; + } + _additionalData = new Dictionary(); } public DataTypeDefinition(int parentId, string propertyEditorAlias) diff --git a/src/Umbraco.Core/Models/PreValue.cs b/src/Umbraco.Core/Models/PreValue.cs index 3d5f13f5ee..05b7a5f5df 100644 --- a/src/Umbraco.Core/Models/PreValue.cs +++ b/src/Umbraco.Core/Models/PreValue.cs @@ -9,7 +9,11 @@ { Value = value; Id = id; + } + public PreValue(string value) + { + Value = value; } /// diff --git a/src/Umbraco.Core/Packaging/PackageBinaryInspector.cs b/src/Umbraco.Core/Packaging/PackageBinaryInspector.cs new file mode 100644 index 0000000000..10450568b0 --- /dev/null +++ b/src/Umbraco.Core/Packaging/PackageBinaryInspector.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Security; +using System.Security.Permissions; +using System.Text; +using System.Threading.Tasks; +using System.Web; + +namespace Umbraco.Core.Packaging +{ + internal class PackageBinaryInspector : MarshalByRefObject + { + /// + /// Entry point to call from your code + /// + /// + /// + /// + /// + /// + /// Will perform the assembly scan in a separate app domain + /// + public static IEnumerable ScanAssembliesForTypeReference(string dllPath, out string[] errorReport) + { + var appDomain = GetTempAppDomain(); + var type = typeof(PackageBinaryInspector); + try + { + var value = (PackageBinaryInspector)appDomain.CreateInstanceAndUnwrap( + type.Assembly.FullName, + type.FullName); + var result = value.PerformScan(dllPath, out errorReport); + return result; + } + finally + { + AppDomain.Unload(appDomain); + } + } + + /// + /// Performs the assembly scanning + /// + /// + /// + /// + /// + /// + /// This method is executed in a separate app domain + /// + internal IEnumerable PerformScan(string dllPath, out string[] errorReport) + { + if (Directory.Exists(dllPath) == false) + { + throw new DirectoryNotFoundException("Could not find directory " + dllPath); + } + + var files = Directory.GetFiles(dllPath, "*.dll"); + var dllsWithReference = new List(); + var errors = new List(); + var assembliesWithErrors = new List(); + + //we need this handler to resolve assembly dependencies below + AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (s, e) => + { + var a = Assembly.ReflectionOnlyLoadFrom(GetAssemblyPath(Assembly.ReflectionOnlyLoad(e.Name))); + if (a == null) throw new TypeLoadException("Could not load assembly " + e.Name); + return a; + }; + + //First load each dll file into the context + foreach (var f in files) Assembly.ReflectionOnlyLoadFrom(f); + + //Then load each referenced assembly into the context + foreach (var f in files) + { + var reflectedAssembly = Assembly.ReflectionOnlyLoadFrom(f); + foreach (var assemblyName in reflectedAssembly.GetReferencedAssemblies()) + { + try + { + Assembly.ReflectionOnlyLoadFrom(GetAssemblyPath(Assembly.ReflectionOnlyLoad(assemblyName.FullName))); + } + catch (FileNotFoundException) + { + //if an exception occurs it means that a referenced assembly could not be found + errors.Add( + string.Concat("This package references the assembly '", + assemblyName.Name, + "' which was not found, this package may have problems running")); + assembliesWithErrors.Add(f); + } + } + } + + var contractType = GetLoadFromContractType(); + + //now that we have all referenced types into the context we can look up stuff + foreach (var f in files.Except(assembliesWithErrors)) + { + //now we need to see if they contain any type 'T' + var reflectedAssembly = Assembly.ReflectionOnlyLoadFrom(f); + + var found = reflectedAssembly.GetExportedTypes() + .Where(contractType.IsAssignableFrom); + + if (found.Any()) + { + dllsWithReference.Add(reflectedAssembly.FullName); + } + } + + errorReport = errors.ToArray(); + return dllsWithReference; + } + + /// + /// In order to compare types, the types must be in the same context, this method will return the type that + /// we are checking against but from the LoadFrom context. + /// + /// + /// + private static Type GetLoadFromContractType() + { + var contractAssemblyLoadFrom = Assembly.ReflectionOnlyLoadFrom( + GetAssemblyPath(Assembly.ReflectionOnlyLoad(typeof (T).Assembly.FullName))); + + var contractType = contractAssemblyLoadFrom.GetExportedTypes() + .FirstOrDefault(x => x.FullName == typeof(T).FullName && x.Assembly.FullName == typeof(T).Assembly.FullName); + + if (contractType == null) + { + throw new InvalidOperationException("Could not find type " + typeof(T) + " in the LoadFrom assemblies"); + } + return contractType; + } + + /// + /// Create an app domain + /// + /// + private static AppDomain GetTempAppDomain() + { + //copy the current app domain setup but don't shadow copy files + var appName = "TempDomain" + Guid.NewGuid(); + var domainSetup = new AppDomainSetup + { + ApplicationName = appName, + ShadowCopyFiles = "false", + ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase, + ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, + DynamicBase = AppDomain.CurrentDomain.SetupInformation.DynamicBase, + LicenseFile = AppDomain.CurrentDomain.SetupInformation.LicenseFile, + LoaderOptimization = AppDomain.CurrentDomain.SetupInformation.LoaderOptimization, + PrivateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath, + PrivateBinPathProbe = AppDomain.CurrentDomain.SetupInformation.PrivateBinPathProbe + }; + + //create new domain with full trust + return AppDomain.CreateDomain( + appName, + AppDomain.CurrentDomain.Evidence, + domainSetup, + new PermissionSet(PermissionState.Unrestricted)); + } + + private static string GetAssemblyPath(Assembly a) + { + var codeBase = a.CodeBase; + var uri = new Uri(codeBase); + return uri.LocalPath; + } + + } +} diff --git a/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs b/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs index 3f25171063..a62ef7b838 100644 --- a/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs @@ -1,203 +1,203 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Newtonsoft.Json; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; - -namespace Umbraco.Core.PropertyEditors -{ - /// - /// Defines a pre-value editor - /// - /// - /// A pre-value editor is made up of multiple pre-value fields, each field defines a key that the value is stored against. - /// Each field can have any editor and the value from each field can store any data such as a simple string or a json structure. - /// - /// The Json serialization attributes are required for manifest property editors to work. - /// - public class PreValueEditor - { - public PreValueEditor() - { - var fields = new List(); - - //the ctor checks if we have PreValueFieldAttributes applied and if so we construct our fields from them - var props = TypeHelper.CachedDiscoverableProperties(GetType()) - .Where(x => x.Name != "Fields"); - foreach (var p in props) - { - var att = p.GetCustomAttributes(typeof (PreValueFieldAttribute), false).OfType().SingleOrDefault(); - if (att != null) - { - if (att.PreValueFieldType != null) - { - //try to create it - try - { - var instance = (PreValueField) Activator.CreateInstance(att.PreValueFieldType); - //overwrite values if they are assigned - if (!att.Key.IsNullOrWhiteSpace()) - { - instance.Key = att.Key; - } - //if the key is still empty then assign it to be the property name - if (instance.Key.IsNullOrWhiteSpace()) - { - instance.Key = p.Name; - } - - if (!att.Name.IsNullOrWhiteSpace()) - instance.Name = att.Name; - if (!att.View.IsNullOrWhiteSpace()) - instance.View = att.View; - if (!att.Description.IsNullOrWhiteSpace()) - instance.Description = att.Description; - if (att.HideLabel) - instance.HideLabel = att.HideLabel; - - //add the custom field - fields.Add(instance); - } - catch (Exception ex) - { - LogHelper.WarnWithException("Could not create an instance of " + att.PreValueFieldType, ex); - } - } - else - { - fields.Add(MapAttributeToField(att, p)); - } - } - } - - Fields = fields; - } - - private static PreValueField MapAttributeToField(PreValueFieldAttribute att, PropertyInfo prop) - { - return new PreValueField - { - //set the key to the property name if it is empty - Key = att.Key.IsNullOrWhiteSpace() ? prop.Name : att.Key, - Name = att.Name, - Description = att.Description, - HideLabel = att.HideLabel, - View = att.View - }; - } - - /// - /// A collection of pre-value fields to be edited - /// - /// - /// If fields are specified then the master View and Validators will be ignored - /// - [JsonProperty("fields")] - public List Fields { get; private set; } - - /// - /// A method to format the posted values from the editor to the values to be persisted - /// - /// - /// - /// The current value that has been persisted to the database for this pre-value editor. This value may be usesful for - /// how the value then get's deserialized again to be re-persisted. In most cases it will probably not be used. - /// - /// - /// - /// By default this will just return the Posted editorValue. - /// - /// This can be overridden if perhaps you have a comma delimited string posted value but want to convert those to individual rows, or to convert - /// a json structure to multiple rows. - /// - public virtual IDictionary ConvertEditorToDb(IDictionary editorValue, PreValueCollection currentValue) - { - //convert to a string based value to be saved in the db - return editorValue.ToDictionary(x => x.Key, x => x.Value == null ? null : x.Value.ToString()); - } - - /// - /// This can be used to re-format the currently saved pre-values that will be passed to the editor, - /// by default this returns the merged default and persisted pre-values. - /// - /// - /// The default/static pre-vals for the property editor - /// - /// - /// The persisted pre-vals for the property editor - /// - /// - /// - /// This is generally not going to be used by anything unless a property editor wants to change the merging - /// functionality or needs to convert some legacy persisted data, or convert the string values to strongly typed values in json (i.e. booleans) - /// - public virtual IDictionary ConvertDbToEditor(IDictionary defaultPreVals, PreValueCollection persistedPreVals) - { - if (defaultPreVals == null) - { - defaultPreVals = new Dictionary(); - } - - if (persistedPreVals.IsDictionaryBased) - { - //we just need to merge the dictionaries now, the persisted will replace default. - foreach (var item in persistedPreVals.PreValuesAsDictionary) - { - //The persisted dictionary contains values of type PreValue which contain the ID and the Value, we don't care - // about the Id, just the value so ignore the id. - defaultPreVals[item.Key] = item.Value.Value; - } - //now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects - // so they can be consumed as real json in angular! - ConvertItemsToJsonIfDetected(defaultPreVals); - - return defaultPreVals; - } - - //it's an array so need to format it - var result = new Dictionary(); - var asArray = persistedPreVals.PreValuesAsArray.ToArray(); - for (var i = 0; i < asArray.Length; i++) - { - //each item is of type PreValue but we don't want the ID, just the value so ignore the ID - result.Add(i.ToInvariantString(), asArray[i].Value); - } - - //now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects - // so they can be consumed as real json in angular! - ConvertItemsToJsonIfDetected(result); - - return result; - } - - private void ConvertItemsToJsonIfDetected(IDictionary result) - { - //now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects - // so they can be consumed as real json in angular! - - var keys = result.Keys.ToArray(); - for (var i = 0; i < keys.Length; i++) - { - if (result[keys[i]] is string) - { - var asString = result[keys[i]].ToString(); - if (asString.DetectIsJson()) - { - try - { - var json = JsonConvert.DeserializeObject(asString); - result[keys[i]] = json; - } - catch - { - //swallow this exception, we thought it was json but it really isn't so continue returning a string - } - } - } - } - } - - } -} \ No newline at end of file +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; + +namespace Umbraco.Core.PropertyEditors +{ + /// + /// Defines a pre-value editor + /// + /// + /// A pre-value editor is made up of multiple pre-value fields, each field defines a key that the value is stored against. + /// Each field can have any editor and the value from each field can store any data such as a simple string or a json structure. + /// + /// The Json serialization attributes are required for manifest property editors to work. + /// + public class PreValueEditor + { + public PreValueEditor() + { + var fields = new List(); + + //the ctor checks if we have PreValueFieldAttributes applied and if so we construct our fields from them + var props = TypeHelper.CachedDiscoverableProperties(GetType()) + .Where(x => x.Name != "Fields"); + foreach (var p in props) + { + var att = p.GetCustomAttributes(typeof (PreValueFieldAttribute), false).OfType().SingleOrDefault(); + if (att != null) + { + if (att.PreValueFieldType != null) + { + //try to create it + try + { + var instance = (PreValueField) Activator.CreateInstance(att.PreValueFieldType); + //overwrite values if they are assigned + if (!att.Key.IsNullOrWhiteSpace()) + { + instance.Key = att.Key; + } + //if the key is still empty then assign it to be the property name + if (instance.Key.IsNullOrWhiteSpace()) + { + instance.Key = p.Name; + } + + if (!att.Name.IsNullOrWhiteSpace()) + instance.Name = att.Name; + if (!att.View.IsNullOrWhiteSpace()) + instance.View = att.View; + if (!att.Description.IsNullOrWhiteSpace()) + instance.Description = att.Description; + if (att.HideLabel) + instance.HideLabel = att.HideLabel; + + //add the custom field + fields.Add(instance); + } + catch (Exception ex) + { + LogHelper.WarnWithException("Could not create an instance of " + att.PreValueFieldType, ex); + } + } + else + { + fields.Add(MapAttributeToField(att, p)); + } + } + } + + Fields = fields; + } + + private static PreValueField MapAttributeToField(PreValueFieldAttribute att, PropertyInfo prop) + { + return new PreValueField + { + //set the key to the property name if it is empty + Key = att.Key.IsNullOrWhiteSpace() ? prop.Name : att.Key, + Name = att.Name, + Description = att.Description, + HideLabel = att.HideLabel, + View = att.View + }; + } + + /// + /// A collection of pre-value fields to be edited + /// + /// + /// If fields are specified then the master View and Validators will be ignored + /// + [JsonProperty("fields")] + public List Fields { get; private set; } + + /// + /// A method to format the posted values from the editor to the values to be persisted + /// + /// + /// + /// The current value that has been persisted to the database for this pre-value editor. This value may be usesful for + /// how the value then get's deserialized again to be re-persisted. In most cases it will probably not be used. + /// + /// + /// + /// By default this will just return the Posted editorValue. + /// + /// This can be overridden if perhaps you have a comma delimited string posted value but want to convert those to individual rows, or to convert + /// a json structure to multiple rows. + /// + public virtual IDictionary ConvertEditorToDb(IDictionary editorValue, PreValueCollection currentValue) + { + //convert to a string based value to be saved in the db + return editorValue.ToDictionary(x => x.Key, x => new PreValue(x.Value == null ? null : x.Value.ToString())); + } + + /// + /// This can be used to re-format the currently saved pre-values that will be passed to the editor, + /// by default this returns the merged default and persisted pre-values. + /// + /// + /// The default/static pre-vals for the property editor + /// + /// + /// The persisted pre-vals for the property editor + /// + /// + /// + /// This is generally not going to be used by anything unless a property editor wants to change the merging + /// functionality or needs to convert some legacy persisted data, or convert the string values to strongly typed values in json (i.e. booleans) + /// + public virtual IDictionary ConvertDbToEditor(IDictionary defaultPreVals, PreValueCollection persistedPreVals) + { + if (defaultPreVals == null) + { + defaultPreVals = new Dictionary(); + } + + if (persistedPreVals.IsDictionaryBased) + { + //we just need to merge the dictionaries now, the persisted will replace default. + foreach (var item in persistedPreVals.PreValuesAsDictionary) + { + //The persisted dictionary contains values of type PreValue which contain the ID and the Value, we don't care + // about the Id, just the value so ignore the id. + defaultPreVals[item.Key] = item.Value.Value; + } + //now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects + // so they can be consumed as real json in angular! + ConvertItemsToJsonIfDetected(defaultPreVals); + + return defaultPreVals; + } + + //it's an array so need to format it + var result = new Dictionary(); + var asArray = persistedPreVals.PreValuesAsArray.ToArray(); + for (var i = 0; i < asArray.Length; i++) + { + //each item is of type PreValue but we don't want the ID, just the value so ignore the ID + result.Add(i.ToInvariantString(), asArray[i].Value); + } + + //now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects + // so they can be consumed as real json in angular! + ConvertItemsToJsonIfDetected(result); + + return result; + } + + private void ConvertItemsToJsonIfDetected(IDictionary result) + { + //now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects + // so they can be consumed as real json in angular! + + var keys = result.Keys.ToArray(); + for (var i = 0; i < keys.Length; i++) + { + if (result[keys[i]] is string) + { + var asString = result[keys[i]].ToString(); + if (asString.DetectIsJson()) + { + try + { + var json = JsonConvert.DeserializeObject(asString); + result[keys[i]] = json; + } + catch + { + //swallow this exception, we thought it was json but it really isn't so continue returning a string + } + } + } + } + } + + } +} diff --git a/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs b/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs index 36b4b2a370..40a5764abf 100644 --- a/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs +++ b/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.Serialization; using System.Web; using System.Web.Security; using Newtonsoft.Json; @@ -11,6 +12,7 @@ namespace Umbraco.Core.Security /// /// All values are lazy loaded for performance reasons as the constructor is called for every single request /// + [Serializable] public class UmbracoBackOfficeIdentity : FormsIdentity { public UmbracoBackOfficeIdentity(FormsAuthenticationTicket ticket) @@ -104,5 +106,6 @@ namespace Umbraco.Core.Security HttpContext.Current.Items[typeof (UmbracoBackOfficeIdentity)] = DeserializedData; } } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Security/UserData.cs b/src/Umbraco.Core/Security/UserData.cs index 5f96143fe4..903d85851f 100644 --- a/src/Umbraco.Core/Security/UserData.cs +++ b/src/Umbraco.Core/Security/UserData.cs @@ -1,4 +1,5 @@ -using System.Runtime.Serialization; +using System; +using System.Runtime.Serialization; namespace Umbraco.Core.Security { @@ -6,6 +7,7 @@ namespace Umbraco.Core.Security /// Data structure used to store information in the authentication cookie /// [DataContract(Name = "userData", Namespace = "")] + [Serializable] internal class UserData { public UserData() diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 230d01cbde..0ea5250ea8 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -217,6 +217,7 @@ namespace Umbraco.Core.Services /// /// Id of the DataTypeDefinition to save PreValues for /// List of string values to save + [Obsolete("This should no longer be used, use the alternative SavePreValues or SaveDataTypeAndPreValues methods instead. This will only insert pre-values without keys")] public void SavePreValues(int id, IEnumerable values) { //TODO: Should we raise an event here since we are really saving values for the data type? @@ -255,9 +256,10 @@ namespace Umbraco.Core.Services /// /// /// - /// We will actually just remove all pre-values and re-insert them in one transaction + /// We need to actually look up each pre-value and maintain it's id if possible - this is because of silly property editors + /// like 'dropdown list publishing keys' /// - internal void SavePreValues(int id, IDictionary values) + public void SavePreValues(int id, IDictionary values) { //TODO: Should we raise an event here since we are really saving values for the data type? @@ -267,22 +269,7 @@ namespace Umbraco.Core.Services { using (var transaction = uow.Database.GetTransaction()) { - uow.Database.Execute("DELETE FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = id }); - - var sortOrder = 1; - foreach (var value in values) - { - var dto = new DataTypePreValueDto - { - DataTypeNodeId = id, - Value = value.Value, - SortOrder = sortOrder, - Alias = value.Key - }; - uow.Database.Insert(dto); - sortOrder++; - } - + AddOrUpdatePreValues(id, values, uow); transaction.Complete(); } } @@ -295,7 +282,7 @@ namespace Umbraco.Core.Services /// /// /// - public void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary values, int userId = 0) + public void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary values, int userId = 0) { if (Saving.IsRaisedEventCancelled(new SaveEventArgs(dataTypeDefinition), this)) return; @@ -309,25 +296,7 @@ namespace Umbraco.Core.Services repository.AddOrUpdate(dataTypeDefinition); //complete the transaction, but run the delegate before the db transaction is finalized - uow.Commit(database => - { - //Execute this before the transaction is completed! - database.Execute("DELETE FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = dataTypeDefinition.Id }); - - var sortOrder = 1; - foreach (var value in values) - { - var dto = new DataTypePreValueDto - { - DataTypeNodeId = dataTypeDefinition.Id, - Value = value.Value, - SortOrder = sortOrder, - Alias = value.Key - }; - database.Insert(dto); - sortOrder++; - } - }); + uow.Commit(database => AddOrUpdatePreValues(dataTypeDefinition.Id, values, uow)); Saved.RaiseEvent(new SaveEventArgs(dataTypeDefinition, false), this); } @@ -336,6 +305,56 @@ namespace Umbraco.Core.Services Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id); } + private void AddOrUpdatePreValues(int id, IDictionary preValueCollection, IDatabaseUnitOfWork uow) + { + //first just get all pre-values for this data type so we can compare them to see if we need to insert or update or replace + var sql = new Sql().Select("*") + .From() + .Where(dto => dto.DataTypeNodeId == id) + .OrderBy(dto => dto.SortOrder); + var currentVals = uow.Database.Fetch(sql).ToArray(); + + //already existing, need to be updated + var valueIds = preValueCollection.Where(x => x.Value.Id > 0).Select(x => x.Value.Id).ToArray(); + var existingByIds = currentVals.Where(x => valueIds.Contains(x.Id)).ToArray(); + + //These ones need to be removed from the db, they no longer exist in the new values + var deleteById = currentVals.Where(x => valueIds.Contains(x.Id) == false); + + foreach (var d in deleteById) + { + uow.Database.Execute( + "DELETE FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId AND id=@Id", + new { DataTypeId = id, Id = d.Id }); + } + + var sortOrder = 1; + + foreach (var pre in preValueCollection) + { + var existing = existingByIds.FirstOrDefault(valueDto => valueDto.Id == pre.Value.Id); + if (existing != null) + { + existing.Value = pre.Value.Value; + existing.SortOrder = sortOrder; + uow.Database.Update(existing); + } + else + { + var dto = new DataTypePreValueDto + { + DataTypeNodeId = id, + Value = pre.Value.Value, + SortOrder = sortOrder, + Alias = pre.Key + }; + uow.Database.Insert(dto); + } + + sortOrder++; + } + } + /// /// Deletes an /// diff --git a/src/Umbraco.Core/Services/IDataTypeService.cs b/src/Umbraco.Core/Services/IDataTypeService.cs index 9b6f23bce3..e57d9016e4 100644 --- a/src/Umbraco.Core/Services/IDataTypeService.cs +++ b/src/Umbraco.Core/Services/IDataTypeService.cs @@ -10,8 +10,6 @@ namespace Umbraco.Core.Services /// public interface IDataTypeService : IService { - void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary values, int userId = 0); - /// /// Gets a by its Id /// @@ -107,8 +105,24 @@ namespace Umbraco.Core.Services /// /// Id of the DataTypeDefinition to save PreValues for /// List of string values to save + [Obsolete("This should no longer be used, use the alternative SavePreValues or SaveDataTypeAndPreValues methods instead. This will only insert pre-values without keys")] void SavePreValues(int id, IEnumerable values); + /// + /// Saves a list of PreValues for a given DataTypeDefinition + /// + /// Id of the DataTypeDefinition to save PreValues for + /// List of key/value pairs to save + void SavePreValues(int id, IDictionary values); + + /// + /// Saves the data type and it's prevalues + /// + /// + /// + /// + void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary values, int userId = 0); + /// /// Gets a specific PreValue by its Id /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 7e547d0988..0ded0c0d5e 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -326,6 +326,7 @@ + @@ -1083,7 +1084,6 @@ - diff --git a/src/Umbraco.Tests/PluginManagerTests.cs b/src/Umbraco.Tests/PluginManagerTests.cs index df7ede9de5..6f72b9d5ef 100644 --- a/src/Umbraco.Tests/PluginManagerTests.cs +++ b/src/Umbraco.Tests/PluginManagerTests.cs @@ -306,13 +306,6 @@ namespace Umbraco.Tests Assert.AreEqual(7, apps.Count()); } - [Test] - public void Resolves_Action_Handlers() - { - var types = PluginManager.Current.ResolveActionHandlers(); - Assert.AreEqual(1, types.Count()); - } - [Test] public void Resolves_DataTypes() { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index c39b56a5e9..9de4e0c541 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -32,7 +32,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ if (key === null || val === null) { throw "The object in the array was not formatted as a key/value pair"; } - return key + "=" + val; + return encodeURIComponent(key) + "=" + encodeURIComponent(val); }).join("&"); } diff --git a/src/Umbraco.Web.UI.Client/src/views/datatype/edit.html b/src/Umbraco.Web.UI.Client/src/views/datatype/edit.html index cf34e6c003..7e2484c0f4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/datatype/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/datatype/edit.html @@ -59,4 +59,4 @@ - \ No newline at end of file + diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/multivalues.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/multivalues.controller.js index bdddef9af4..c8d3c3c4a5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/multivalues.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/multivalues.controller.js @@ -10,7 +10,10 @@ angular.module("umbraco").controller("Umbraco.Editors.MultiValuesController", //make an array from the dictionary var items = []; for (var i in $scope.model.value) { - items.push({value: $scope.model.value[i]}); + items.push({ + value: $scope.model.value[i], + id: i + }); } //now make the editor model the array $scope.model.value = items; diff --git a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_archive.png b/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_archive.png deleted file mode 100644 index 8443c23eb9..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_archive.png and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_datasource.gif b/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_datasource.gif deleted file mode 100644 index eff4528415..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_datasource.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_entries.gif b/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_entries.gif deleted file mode 100644 index dcf36d972e..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_entries.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_exportform.gif b/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_exportform.gif deleted file mode 100644 index 385e077d65..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_exportform.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_form.gif b/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_form.gif deleted file mode 100644 index 2b49b1eb22..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_form.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_importform.gif b/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_importform.gif deleted file mode 100644 index ac86897f75..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_importform.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_prevaluesource.gif b/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_prevaluesource.gif deleted file mode 100644 index d40f332f55..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_prevaluesource.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_workflow.gif b/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_workflow.gif deleted file mode 100644 index befcf396d3..0000000000 Binary files a/src/Umbraco.Web.UI/Umbraco/Images/umbraco/icon_workflow.gif and /dev/null differ diff --git a/src/Umbraco.Web.UI/Umbraco/xslt/templates/Schema2/UmbracoContourListComments.xslt b/src/Umbraco.Web.UI/Umbraco/xslt/templates/Schema2/UmbracoContourListComments.xslt deleted file mode 100644 index 606a171ebe..0000000000 --- a/src/Umbraco.Web.UI/Umbraco/xslt/templates/Schema2/UmbracoContourListComments.xslt +++ /dev/null @@ -1,65 +0,0 @@ - - -]> - - - - - - - - - - - - - - - - -
- - - No comments - - - 1 comment - - - comments - - - -
- -
- - - -
- - - - Says:
- - - - -
- - -
-
-
- -
- -
- -
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco/xslt/templates/UmbracoContourListComments.xslt b/src/Umbraco.Web.UI/Umbraco/xslt/templates/UmbracoContourListComments.xslt deleted file mode 100644 index e08ee63b4f..0000000000 --- a/src/Umbraco.Web.UI/Umbraco/xslt/templates/UmbracoContourListComments.xslt +++ /dev/null @@ -1,59 +0,0 @@ - - ]> - - - - - - - - - - - - - - - - -
- - - No comments - - - 1 comment - - - comments - - - -
- -
- - - -
- - Says:
- - -
- - -
-
-
- -
- -
- -
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/config/applications.config b/src/Umbraco.Web.UI/config/applications.config index b0b3ed2300..2a6da37bae 100644 --- a/src/Umbraco.Web.UI/config/applications.config +++ b/src/Umbraco.Web.UI/config/applications.config @@ -7,5 +7,4 @@ - \ No newline at end of file diff --git a/src/Umbraco.Web.UI/config/splashes/noNodes.aspx b/src/Umbraco.Web.UI/config/splashes/noNodes.aspx index 6a71a740cb..be53c864fa 100644 --- a/src/Umbraco.Web.UI/config/splashes/noNodes.aspx +++ b/src/Umbraco.Web.UI/config/splashes/noNodes.aspx @@ -85,7 +85,7 @@ So get rid of this page by starting umbraco and publishing some content. You can do this by clicking the "set up your new website" button below.

diff --git a/src/Umbraco.Web.UI/umbraco/config/create/UI.xml b/src/Umbraco.Web.UI/umbraco/config/create/UI.xml index d1934d069b..c5e973f06e 100644 --- a/src/Umbraco.Web.UI/umbraco/config/create/UI.xml +++ b/src/Umbraco.Web.UI/umbraco/config/create/UI.xml @@ -338,4 +338,4 @@ - + diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index 6654ba0f28..d47adfef15 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -661,7 +661,7 @@ Mange hilsner fra umbraco robotten Download XML DTD Felter Inkluder undersider - Hej %0%. Dette er en automatisk mail sendt for at informere dig om at dokumentet '%1' har en forespørgsel omkring oversættelse til '%5%' af %2%. Gå til http://%3%/umbraco/translation/details.aspx?id=%4% for at redigere. Eller log ind i umbraco for at få en oversigt over dine oversættelsesopgaver: http://%3%/umbraco/umbraco.aspx Hav en god dag! Mange hilsner umbraco-robotten + Hej %0%. Dette er en automatisk mail sendt for at informere dig om at dokumentet '%1' har en forespørgsel omkring oversættelse til '%5%' af %2%. Gå til http://%3%/umbraco/translation/details.aspx?id=%4% for at redigere. Eller log ind i umbraco for at få en oversigt over dine oversættelsesopgaver: http://%3%/umbraco Hav en god dag! Mange hilsner umbraco-robotten [%0%] Oversættelsesopgave for %1% Ingen oversættelsesbrugere er fundet. Opret venligst en oversættelsesbruger før du begynder at sende indhold til oversættelse Opgaver oprettet af dig diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/de.xml b/src/Umbraco.Web.UI/umbraco/config/lang/de.xml index ad26262d2e..d2a16639ad 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/de.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/de.xml @@ -754,7 +754,7 @@ das Dokument '%1%' wurde von '%2%' zur Übersetzung in '%5%' freigegeben. Zum Bearbeiten verwenden Sie bitte diesen Link: http://%3%/umbraco/translation/details.aspx?id=%4%. -Sie können sich auch alle anstehenden Übersetzungen gesammelt im Umbraco-Verwaltungsbereich anzeigen lassen: http://%3%/umbraco/umbraco.aspx +Sie können sich auch alle anstehenden Übersetzungen gesammelt im Umbraco-Verwaltungsbereich anzeigen lassen: http://%3%/umbraco Einen schönen Tag wünscht Ihr freundlicher Umbraco-Robot diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index bbd044cb4c..8adf63406e 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -880,7 +880,7 @@ To manage your website, simply open the umbraco back office and start adding con Go to http://%3%/translation/details.aspx?id=%4% to edit. Or log into umbraco to get an overview of your translation tasks - http://%3%/umbraco.aspx + http://%3% Have a nice day! diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index d622cf8f19..37d514652b 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -907,7 +907,7 @@ To manage your website, simply open the umbraco back office and start adding con Go to http://%3%/translation/details.aspx?id=%4% to edit. Or log into umbraco to get an overview of your translation tasks - http://%3%/umbraco.aspx + http://%3% Have a nice day! diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/es.xml b/src/Umbraco.Web.UI/umbraco/config/lang/es.xml index c69b42522c..30bc95d93c 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/es.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/es.xml @@ -658,7 +658,7 @@ However, Runway offers an easy foundation based on best practices to get you sta Descargar xml DTD Campos Incluir subpáginas - Hola %0%. Este email se ha generado automáticamente para informale que %2% ha solicitado que el documento '%1%' sea traducido en '%5%'. Para editarlo, vaya a la dirección http://%3%/umbraco/translation/details.aspx?id=%4% o inicie la sesión en umbraco y vaya a http://%3%/umbraco/umbraco.aspx para ver las tareas pendientes de traducir. Espero que tenga un buen dia. Saludos de parte de el robot de umbraco + Hola %0%. Este email se ha generado automáticamente para informale que %2% ha solicitado que el documento '%1%' sea traducido en '%5%'. Para editarlo, vaya a la dirección http://%3%/umbraco/translation/details.aspx?id=%4% o inicie la sesión en umbraco y vaya a http://%3%/umbraco para ver las tareas pendientes de traducir. Espero que tenga un buen dia. Saludos de parte de el robot de umbraco Tarea para tradudir [%0%] por %1% No se encontraron usuarios traductores. Por favor, crea un usuario traductor antes de empezar a mandar contenido para su traducción Tareas creadas por ti diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/he.xml b/src/Umbraco.Web.UI/umbraco/config/lang/he.xml index 21c6cfe9f0..201001ffbc 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/he.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/he.xml @@ -775,7 +775,7 @@ To manage your website, simply open the umbraco back office and start adding con לעריכה, לחץ על הלינק הבא: http://%3%/translation/details.aspx?id=%4% . באפשרותך גם להיכנס למערכת על מנת לראות את כל משימות התירגום - http://%3%/umbraco.aspx + http://%3% המשך יום נעים. diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/it.xml b/src/Umbraco.Web.UI/umbraco/config/lang/it.xml index 8cecd7bbb7..10a670378a 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/it.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/it.xml @@ -747,7 +747,7 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i Vai al http://%3%/translation/details.aspx?id=%4% per effettuare la modifica. Oppure effettua il login in Umbraco per avere una panoramica delle attività di traduzione - http://%3%/umbraco.aspx + http://%3% Buona giornata! diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml index 330886f493..2cea7d7838 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml @@ -787,7 +787,7 @@ Runwayをインストールして作られた新しいウェブサイトがど 編集はこちらから: http://%3%/translation/details.aspx?id=%4% - また、翻訳タスクの概況はこちらから: http://%3%/umbraco.aspx + また、翻訳タスクの概況はこちらから: http://%3% 早々 @@ -887,4 +887,4 @@ Runwayをインストールして作られた新しいウェブサイトがど ユーザーの種類 投稿者 - + diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml index 0212898dff..0a7ba87cff 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml @@ -752,7 +752,7 @@ 편집하시려면 http://%3%/translation/details.aspx?id=%4% 로 번역작업을 전반적으로 보시려면 Umbraco에 로그인 하세요 - http://%3%/umbraco.aspx + http://%3% 좋은 하루 되세요! ]]> diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml b/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml index 65ecae12a3..6db3d9e2a5 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml @@ -651,7 +651,7 @@ Miłego dnia!]]> Pobierz XML DTD Pola Włączając podstrony - to jest automatyczny mail informujący że dokument %1% został zgłoszony jako wymagający tłumaczenia na '%5%' przez %2%. Wejdź na http://%3%/translation/details.aspx?id=%4% aby edytować. Lub zaloguj się do umbraco aby zobaczyć wszystkie zadania do tłumaczenia http://%3%/umbraco.aspx.
Życzę miłego dnia! Umbraco robot]]>
+ to jest automatyczny mail informujący że dokument %1% został zgłoszony jako wymagający tłumaczenia na '%5%' przez %2%. Wejdź na http://%3%/translation/details.aspx?id=%4% aby edytować. Lub zaloguj się do umbraco aby zobaczyć wszystkie zadania do tłumaczenia http://%3%.
Życzę miłego dnia! Umbraco robot]]>
[%0%] Tłumaczeń dla %1% Nie znaleziono tłumaczy. Proszę utwórz tłumacza przed wysłaniem zawartości do tłumaczenia Zadania stworzone przez Ciebie diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml b/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml index f795e16d3c..ec10a7bdce 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml @@ -737,7 +737,7 @@ Para fechar a tarefa de tradução vá até os detalhes e clique no botão "Fech Vá para http://%3%/translation/details.aspx?id=%4% para editar. Ou visite o umbraco para ter uma visão geral das tarefas de tradução - http://%3%/umbraco.aspx + http://%3% Tenha um bom dia! diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml index 2bbadf234a..d21847c9f8 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml @@ -819,7 +819,7 @@ Перейдите по ссылке http://%3%/translation/details.aspx?id=%4% для редактирования. Или авторизуйтесь для общего обзора Ваших заданий по переводу - http://%3%/umbraco.aspx. + http://%3%. Удачи! diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml b/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml index 99f34163b5..4c57efb4bb 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml @@ -684,7 +684,7 @@ Ladda hem DTD för XML Fält Inkludera undersidor - Hej %0%. Detta är ett automatisk mail skickat for att informera dig om att det finns en översättningsförfrågan på dokument '%1' till '{5}' skickad av {2}. För att redigere, besök http://{3}/translation/details.aspx?id={4}. För att få en översikt över dina översättningsuppgigter loggar du in i umbraco på: http://{3}/umbraco.aspx + Hej %0%. Detta är ett automatisk mail skickat for att informera dig om att det finns en översättningsförfrågan på dokument '%1' till '{5}' skickad av {2}. För att redigere, besök http://{3}/translation/details.aspx?id={4}. För att få en översikt över dina översättningsuppgigter loggar du in i umbraco på: http://{3} [%0%] Översättningsuppgit för %1% Hittade inga användare som är översättare. Vänligen skapa en användare som är översättare innan du börjar skicka innehåll för översättning Arbetsuppgifter som du har skapat diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml index 49213b98c9..abe7e71f97 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml @@ -784,7 +784,7 @@ 转到 http://%3%/translation/details.aspx?id=%4% 进行编辑 - 或登录http://%3%/umbraco.aspx查看任务 + 或登录http://%3%查看任务 祝好运!]]> [%0%]翻译任务:%1% diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/installer.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/installer.aspx index e271bf7413..a6e4dd873c 100644 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/installer.aspx +++ b/src/Umbraco.Web.UI/umbraco/developer/Packages/installer.aspx @@ -18,6 +18,12 @@ else b.attr("disabled", true); } + + $(document).ready(function () { + $('.toggle-report').click(function () { + $(this).next().toggle(); + }); + }); @@ -112,10 +118,8 @@

Binary files in the package!

-

- Read more... -

- + +
+

+ Legacy Property editors detected

+ Read more... +
+

+ This package contains legacy property editors which are not compatible with Umbraco 7

+

+ This package may not function correctly if the package developer has not indicated that + it is compatible with version 7. Any DataTypes this package creates that do not have + a Version 7 compatible property editor will be converted to use a Label/NoEdit property editor. +

+
+
+
+ +
+

+ Binary file errors detected

+ Read more... +
+

+ This package contains .NET binary files that might not be compatible with this version of Umbraco. + If you aren't sure what these errors mean or why they are listed please contact the package creator. +

+

+ Error report
+

    + +
+

+
+
+

Macro Conflicts in the package!

-

- Read more... -

-