Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e9da0aa351 | |||
| b42e411e49 | |||
| 4c4b09b187 | |||
| 43a72ed5e5 | |||
| 709198f943 | |||
| 77f72ed72e | |||
| a03fe3af32 | |||
| 697a797c7e | |||
| cfe014ee45 | |||
| d62fa05ab5 | |||
| 662cf4c3bf | |||
| d0b8314134 | |||
| 8eb4786976 | |||
| 20155b5ca6 | |||
| 16c310f3c6 | |||
| 99d570dc97 | |||
| 2ae3e3ade9 | |||
| 1cbb7b3173 | |||
| 71be453ada | |||
| efae05b3ae | |||
| 84acd43ccf | |||
| 9fe756bacb | |||
| cd03b5a4f9 | |||
| 07a62d7edf | |||
| a6c166d926 | |||
| c1bc555443 | |||
| d4166f33e8 |
@@ -8,6 +8,9 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.Editors;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Archetype.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Archetype.Api
|
||||
{
|
||||
@@ -19,7 +22,7 @@ namespace Archetype.Api
|
||||
{
|
||||
return
|
||||
global::Umbraco.Core.PropertyEditors.PropertyEditorResolver.Current.PropertyEditors
|
||||
.Select(x => new {defaultPreValues = x.DefaultPreValues, alias = x.Alias, view = x.ValueEditor.View});
|
||||
.Select(x => new {defaultPreValues = x.DefaultPreValuesForArchetype(), alias = x.Alias, view = x.ValueEditor.View});
|
||||
}
|
||||
|
||||
public object GetAll()
|
||||
@@ -35,6 +38,7 @@ namespace Archetype.Api
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var dataTypeDisplay = Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType);
|
||||
return new { selectedEditor = dataTypeDisplay.SelectedEditor, preValues = dataTypeDisplay.PreValues };
|
||||
}
|
||||
|
||||
@@ -234,6 +234,7 @@
|
||||
<Compile Include="Extensions\ArchetypeHelper.cs" />
|
||||
<Compile Include="Extensions\HtmlHelperExtensions.cs" />
|
||||
<Compile Include="Extensions\ArchetypePropertyModelExtensions.cs" />
|
||||
<Compile Include="Extensions\PropertyEditorExtensions.cs" />
|
||||
<Compile Include="Extensions\StringExtensions.cs" />
|
||||
<Compile Include="Models\ArchetypeModel.cs" />
|
||||
<Compile Include="Models\ArchetypePreValue.cs" />
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Archetype.Extensions
|
||||
{
|
||||
public static class PropertyEditorExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Formats the default prevalues for a property editor for use within an Archetype clientside context
|
||||
/// </summary>
|
||||
/// <param name="propertyEditor">The property editor</param>
|
||||
/// <returns>The formatted default prevalues</returns>
|
||||
public static IDictionary<string, object> DefaultPreValuesForArchetype(this PropertyEditor propertyEditor)
|
||||
{
|
||||
if (propertyEditor.DefaultPreValues == null || propertyEditor.DefaultPreValues.Any() == false)
|
||||
{
|
||||
return propertyEditor.DefaultPreValues;
|
||||
}
|
||||
var view = propertyEditor.ValueEditor.View.ToLowerInvariant();
|
||||
|
||||
// This is the extension point for default prevalues formatting, in case we need to handle any other
|
||||
// property editors later on. It should be replaced with a switch statement by then, or maybe some fancy
|
||||
// auto discovery of formatters :)
|
||||
if (view == "imagecropper")
|
||||
{
|
||||
propertyEditor.FormatImageCropperDefaultPreValuesForArchetype();
|
||||
}
|
||||
return propertyEditor.DefaultPreValues;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format the default prevalues of the image cropper property editor
|
||||
/// </summary>
|
||||
/// <param name="propertyEditor"></param>
|
||||
/// <remarks>
|
||||
/// In order for the image cropper to work clientside, we need to make sure it's default prevalue "focalpoint" is returned
|
||||
/// as a JSON object and not as the string it's defined as on the image cropper property editor.
|
||||
/// </remarks>
|
||||
private static void FormatImageCropperDefaultPreValuesForArchetype(this PropertyEditor propertyEditor)
|
||||
{
|
||||
const string focalPointKey = "focalPoint";
|
||||
|
||||
if (propertyEditor.DefaultPreValues.ContainsKey(focalPointKey) == false || propertyEditor.DefaultPreValues[focalPointKey] == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var focalPoint = propertyEditor.DefaultPreValues[focalPointKey].ToString();
|
||||
if (string.IsNullOrEmpty(focalPoint))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// translate the JSON string to a JSON object
|
||||
propertyEditor.DefaultPreValues[focalPointKey] = JsonConvert.DeserializeObject(focalPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using System;
|
||||
|
||||
namespace Archetype.Models
|
||||
{
|
||||
@@ -16,6 +17,9 @@ namespace Archetype.Models
|
||||
[JsonProperty("properties")]
|
||||
public IEnumerable<ArchetypePropertyModel> Properties;
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public ArchetypeFieldsetModel()
|
||||
{
|
||||
Properties = new List<ArchetypePropertyModel>();
|
||||
@@ -84,4 +88,4 @@ namespace Archetype.Models
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
@@ -30,15 +30,22 @@ namespace Archetype.Models
|
||||
|
||||
public string SerializeForPersistence()
|
||||
{
|
||||
// clear the editor state before serializing (it's temporary state data)
|
||||
foreach(var property in Fieldsets.SelectMany(f => f.Properties.Where(p => p.EditorState != null)).ToList())
|
||||
{
|
||||
property.EditorState = null;
|
||||
}
|
||||
|
||||
var json = JObject.Parse(JsonConvert.SerializeObject(this, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }));
|
||||
|
||||
var propertiesToRemove = new String[] { "propertyEditorAlias", "dataTypeId", "dataTypeGuid", "hostContentType" };
|
||||
|
||||
json.Descendants().OfType<JProperty>()
|
||||
.Where(p => propertiesToRemove.Contains(p.Name))
|
||||
.ToList()
|
||||
.ForEach(x => x.Remove());
|
||||
|
||||
return json.ToString(Formatting.None);
|
||||
.ForEach(x => x.Remove());
|
||||
|
||||
return json.ToString(Formatting.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ namespace Archetype.Models
|
||||
[JsonProperty("hidePropertyLabel")]
|
||||
public bool HidePropertyLabel { get; set; }
|
||||
|
||||
[JsonProperty("minFieldsets", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public int MinFieldsets { get; set; }
|
||||
|
||||
[JsonProperty("maxFieldsets", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public int MaxFieldsets { get; set; }
|
||||
|
||||
|
||||
@@ -26,12 +26,15 @@ namespace Archetype.Models
|
||||
[JsonProperty("dataTypeGuid")]
|
||||
internal string DataTypeGuid { get; set; }
|
||||
|
||||
// container for temporary editor state from the Umbraco backend
|
||||
[JsonProperty("editorState")]
|
||||
internal UmbracoEditorState EditorState { get; set; }
|
||||
|
||||
[JsonProperty("hostContentType")]
|
||||
internal PublishedContentType HostContentType { get; set; }
|
||||
|
||||
public T GetValue<T>()
|
||||
{
|
||||
|
||||
// Try Umbraco's PropertyValueConverters
|
||||
var converters = UmbracoContext.Current != null ? PropertyValueConvertersResolver.Current.Converters : Enumerable.Empty<IPropertyValueConverter>();
|
||||
if (!string.IsNullOrWhiteSpace(this.PropertyEditorAlias) && converters.Any())
|
||||
@@ -88,5 +91,12 @@ namespace Archetype.Models
|
||||
|
||||
return Attempt<T>.Fail();
|
||||
}
|
||||
|
||||
internal class UmbracoEditorState
|
||||
{
|
||||
// container for the names of any files selected for a property in the Umbraco backend
|
||||
[JsonProperty("fileNames")]
|
||||
public IEnumerable<string> FileNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("1.8.1")]
|
||||
[assembly: AssemblyFileVersion("1.8.1")]
|
||||
[assembly: AssemblyVersion("1.9")]
|
||||
[assembly: AssemblyFileVersion("1.9")]
|
||||
|
||||
@@ -1,155 +1,191 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Archetype.Extensions;
|
||||
using ClientDependency.Core;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
|
||||
namespace Archetype.PropertyEditors
|
||||
{
|
||||
[PropertyEditorAsset(ClientDependencyType.Javascript, "~/App_Plugins/Archetype/js/archetype.js")]
|
||||
[PropertyEditor(Constants.PropertyEditorAlias, "Archetype", "~/App_Plugins/Archetype/views/archetype.html", ValueType = "JSON")]
|
||||
public class ArchetypePropertyEditor : PropertyEditor
|
||||
{
|
||||
#region Pre Value Editor
|
||||
|
||||
protected override PreValueEditor CreatePreValueEditor()
|
||||
{
|
||||
return new ArchetypePreValueEditor();
|
||||
}
|
||||
|
||||
internal class ArchetypePreValueEditor : PreValueEditor
|
||||
{
|
||||
[PreValueField("archetypeConfig", "Config", "~/App_Plugins/Archetype/views/archetype.config.html",
|
||||
Description = "(Required) Describe your Archetype.")]
|
||||
public string Config { get; set; }
|
||||
|
||||
[PreValueField("hideLabel", "Hide Label", "boolean",
|
||||
Description = "Hide the Umbraco property title and description, making the Archetype span the entire page width")]
|
||||
public bool HideLabel { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Value Editor
|
||||
|
||||
protected override PropertyValueEditor CreateValueEditor()
|
||||
{
|
||||
return new ArchetypePropertyValueEditor(base.CreateValueEditor());
|
||||
}
|
||||
|
||||
internal class ArchetypePropertyValueEditor : PropertyValueEditorWrapper
|
||||
{
|
||||
protected JsonSerializerSettings _jsonSettings;
|
||||
|
||||
public ArchetypePropertyValueEditor(PropertyValueEditor wrapped)
|
||||
: base(wrapped) { }
|
||||
|
||||
public override string ConvertDbToString(Property property, PropertyType propertyType, IDataTypeService dataTypeService)
|
||||
{
|
||||
if (property.Value == null || property.Value.ToString() == "")
|
||||
return string.Empty;
|
||||
|
||||
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(property.Value.ToString(), propertyType.DataTypeDefinitionId);
|
||||
|
||||
foreach (var fieldset in archetype.Fieldsets)
|
||||
{
|
||||
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
|
||||
{
|
||||
try
|
||||
{
|
||||
if(propDef == null || propDef.DataTypeGuid == null) continue;
|
||||
var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid));
|
||||
var propType = new PropertyType(dtd) { Alias = propDef.Alias };
|
||||
var prop = new Property(propType, propDef.Value);
|
||||
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
|
||||
propDef.Value = propEditor.ValueEditor.ConvertDbToString(prop, propType, dataTypeService);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return archetype.SerializeForPersistence();
|
||||
}
|
||||
|
||||
public override object ConvertDbToEditor(Property property, PropertyType propertyType, IDataTypeService dataTypeService)
|
||||
{
|
||||
if (property.Value == null || property.Value.ToString() == "")
|
||||
return string.Empty;;
|
||||
|
||||
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(property.Value.ToString(), propertyType.DataTypeDefinitionId);
|
||||
|
||||
foreach (var fieldset in archetype.Fieldsets)
|
||||
{
|
||||
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
|
||||
{
|
||||
try
|
||||
{
|
||||
var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid));
|
||||
var propType = new PropertyType(dtd) { Alias = propDef.Alias };
|
||||
var prop = new Property(propType, propDef.Value);
|
||||
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
|
||||
propDef.Value = propEditor.ValueEditor.ConvertDbToEditor(prop, propType, dataTypeService);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return archetype;
|
||||
}
|
||||
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue)
|
||||
{
|
||||
if (editorValue.Value == null || editorValue.Value.ToString() == "")
|
||||
return string.Empty;
|
||||
|
||||
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(editorValue.Value.ToString(), editorValue.PreValues);
|
||||
|
||||
foreach (var fieldset in archetype.Fieldsets)
|
||||
{
|
||||
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
|
||||
{
|
||||
try
|
||||
{
|
||||
var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid));
|
||||
var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(dtd.Id);
|
||||
var propData = new ContentPropertyData(propDef.Value, preValues, new Dictionary<string, object>());
|
||||
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
|
||||
propDef.Value = propEditor.ValueEditor.ConvertEditorToDb(propData, propDef.Value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return archetype.SerializeForPersistence();
|
||||
}
|
||||
|
||||
internal virtual PropertyEditor GetPropertyEditor(IDataTypeDefinition dtd)
|
||||
{
|
||||
if (dtd.Id != 0)
|
||||
return PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
|
||||
|
||||
return dtd.PropertyEditorAlias.Equals(Constants.PropertyEditorAlias)
|
||||
? new ArchetypePropertyEditor()
|
||||
: (PropertyEditor)new TextboxPropertyEditor();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Archetype.Extensions;
|
||||
using ClientDependency.Core;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Archetype.PropertyEditors
|
||||
{
|
||||
[PropertyEditorAsset(ClientDependencyType.Javascript, "../App_Plugins/Archetype/js/archetype.js")]
|
||||
[PropertyEditor(Constants.PropertyEditorAlias, "Archetype", "../App_Plugins/Archetype/views/archetype.html", ValueType = "JSON")]
|
||||
public class ArchetypePropertyEditor : PropertyEditor
|
||||
{
|
||||
#region Pre Value Editor
|
||||
|
||||
protected override PreValueEditor CreatePreValueEditor()
|
||||
{
|
||||
return new ArchetypePreValueEditor();
|
||||
}
|
||||
|
||||
internal class ArchetypePreValueEditor : PreValueEditor
|
||||
{
|
||||
[PreValueField("archetypeConfig", "Config", "../App_Plugins/Archetype/views/archetype.config.html",
|
||||
Description = "(Required) Describe your Archetype.")]
|
||||
public string Config { get; set; }
|
||||
|
||||
[PreValueField("hideLabel", "Hide Label", "boolean",
|
||||
Description = "Hide the Umbraco property title and description, making the Archetype span the entire page width")]
|
||||
public bool HideLabel { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Value Editor
|
||||
|
||||
protected override PropertyValueEditor CreateValueEditor()
|
||||
{
|
||||
return new ArchetypePropertyValueEditor(base.CreateValueEditor());
|
||||
}
|
||||
|
||||
internal class ArchetypePropertyValueEditor : PropertyValueEditorWrapper
|
||||
{
|
||||
protected JsonSerializerSettings _jsonSettings;
|
||||
|
||||
public ArchetypePropertyValueEditor(PropertyValueEditor wrapped)
|
||||
: base(wrapped)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ConvertDbToString(Property property, PropertyType propertyType, IDataTypeService dataTypeService)
|
||||
{
|
||||
if(property.Value == null || property.Value.ToString() == "")
|
||||
return string.Empty;
|
||||
|
||||
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(property.Value.ToString(), propertyType.DataTypeDefinitionId);
|
||||
|
||||
foreach (var fieldset in archetype.Fieldsets)
|
||||
{
|
||||
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
|
||||
{
|
||||
try
|
||||
{
|
||||
if(propDef == null || propDef.DataTypeGuid == null) continue;
|
||||
var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid));
|
||||
var propType = new PropertyType(dtd) {Alias = propDef.Alias};
|
||||
var prop = new Property(propType, propDef.Value);
|
||||
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
|
||||
propDef.Value = propEditor.ValueEditor.ConvertDbToString(prop, propType, dataTypeService);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return archetype.SerializeForPersistence();
|
||||
}
|
||||
|
||||
public override object ConvertDbToEditor(Property property, PropertyType propertyType, IDataTypeService dataTypeService)
|
||||
{
|
||||
if(property.Value == null || property.Value.ToString() == "")
|
||||
return string.Empty;
|
||||
|
||||
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(property.Value.ToString(), propertyType.DataTypeDefinitionId);
|
||||
|
||||
foreach (var fieldset in archetype.Fieldsets)
|
||||
{
|
||||
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
|
||||
{
|
||||
try
|
||||
{
|
||||
var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid));
|
||||
var propType = new PropertyType(dtd) {Alias = propDef.Alias};
|
||||
var prop = new Property(propType, propDef.Value);
|
||||
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
|
||||
propDef.Value = propEditor.ValueEditor.ConvertDbToEditor(prop, propType, dataTypeService);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return archetype;
|
||||
}
|
||||
|
||||
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue)
|
||||
{
|
||||
if(editorValue.Value == null || editorValue.Value.ToString() == "")
|
||||
return string.Empty;
|
||||
|
||||
// attempt to deserialize the current property value as an Archetype
|
||||
var currentArchetype = currentValue != null ? ArchetypeHelper.Instance.DeserializeJsonToArchetype(currentValue.ToString(), editorValue.PreValues) : null;
|
||||
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(editorValue.Value.ToString(), editorValue.PreValues);
|
||||
|
||||
// get all files uploaded via the file manager (if any)
|
||||
var uploadedFiles = editorValue.AdditionalData.ContainsKey("files") ? editorValue.AdditionalData["files"] as IEnumerable<ContentItemFile> : null;
|
||||
foreach (var fieldset in archetype.Fieldsets)
|
||||
{
|
||||
// assign an id to the fieldset if it has none (e.g. newly created fieldset)
|
||||
fieldset.Id = fieldset.Id == Guid.Empty ? Guid.NewGuid() : fieldset.Id;
|
||||
// find the corresponding fieldset in the current Archetype value (if any)
|
||||
var currentFieldset = currentArchetype != null ? currentArchetype.Fieldsets.FirstOrDefault(f => f.Id == fieldset.Id) : null;
|
||||
foreach (var propDef in fieldset.Properties)
|
||||
{
|
||||
try
|
||||
{
|
||||
// find the corresponding property in the current Archetype value (if any)
|
||||
var currentProperty = currentFieldset != null ? currentFieldset.Properties.FirstOrDefault(p => p.Alias == propDef.Alias) : null;
|
||||
var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid));
|
||||
var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(dtd.Id);
|
||||
|
||||
var additionalData = new Dictionary<string, object>();
|
||||
|
||||
// figure out if we need to pass a files collection in the additional data to the property value editor
|
||||
if(uploadedFiles != null)
|
||||
{
|
||||
if(dtd.PropertyEditorAlias == Constants.PropertyEditorAlias)
|
||||
{
|
||||
// it's a nested Archetype - just pass all uploaded files to the value editor
|
||||
additionalData["files"] = uploadedFiles.ToList();
|
||||
}
|
||||
else if (propDef.EditorState != null && propDef.EditorState.FileNames != null && propDef.EditorState.FileNames.Any())
|
||||
{
|
||||
// pass the uploaded files that belongs to this property (if any) to the value editor
|
||||
var propertyFiles = propDef.EditorState.FileNames.Select(f => uploadedFiles.FirstOrDefault(u => u.FileName == f)).Where(f => f != null).ToList();
|
||||
if(propertyFiles.Any())
|
||||
{
|
||||
additionalData["files"] = propertyFiles;
|
||||
}
|
||||
}
|
||||
}
|
||||
var propData = new ContentPropertyData(propDef.Value, preValues, additionalData);
|
||||
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
|
||||
// make sure to send the current property value (if any) to the PE ValueEditor
|
||||
propDef.Value = propEditor.ValueEditor.ConvertEditorToDb(propData, currentProperty != null ? currentProperty.Value : null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return archetype.SerializeForPersistence();
|
||||
}
|
||||
|
||||
internal virtual PropertyEditor GetPropertyEditor(IDataTypeDefinition dtd)
|
||||
{
|
||||
if(dtd.Id != 0)
|
||||
return PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
|
||||
|
||||
return dtd.PropertyEditorAlias.Equals(Constants.PropertyEditorAlias)
|
||||
? new ArchetypePropertyEditor()
|
||||
: (PropertyEditor) new TextboxPropertyEditor();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
|
||||
//define empty items
|
||||
var newPropertyModel = '{"alias": "", "remove": false, "collapse": false, "label": "", "helpText": "", "dataTypeGuid": "0cc0eba1-9960-42c9-bf9b-60e150b429ae", "value": ""}';
|
||||
var newFieldsetModel = '{"alias": "", "remove": false, "collapse": false, "labelTemplate": "", "icon": "", "label": "", "properties": [' + newPropertyModel + ']}';
|
||||
var defaultFieldsetConfigModel = JSON.parse('{"showAdvancedOptions": false, "startWithAddButton": false, "hideFieldsetToolbar": false, "enableMultipleFieldsets": false, "hideFieldsetControls": false, "hidePropertyLabel": false, "maxFieldsets": null, "enableCollapsing": true, "enableCloning": false, "enableDisabling": true, "enableDeepDatatypeRequests": false, "fieldsets": [' + newFieldsetModel + ']}');
|
||||
var defaultFieldsetConfigModel = JSON.parse('{"showAdvancedOptions": false, "startWithAddButton": false, "hideFieldsetToolbar": false, "enableMultipleFieldsets": false, "hideFieldsetControls": false, "hidePropertyLabel": false, "minFieldsets": null, "maxFieldsets": null, "enableCollapsing": true, "enableCloning": false, "enableDisabling": true, "enableDeepDatatypeRequests": false, "fieldsets": [' + newFieldsetModel + ']}');
|
||||
|
||||
//ini the model
|
||||
$scope.model.value = $scope.model.value || defaultFieldsetConfigModel;
|
||||
@@ -104,7 +104,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
|
||||
|
||||
//ini the properties
|
||||
_.each($scope.archetypeConfigRenderModel.fieldsets, function(fieldset){
|
||||
$scope.focusProperty(fieldset.properties);
|
||||
$scope.focusProperty(fieldset.properties);
|
||||
});
|
||||
|
||||
//setup JSON.stringify helpers
|
||||
@@ -290,5 +290,5 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
|
||||
}
|
||||
|
||||
//archetype css
|
||||
assetsService.loadCss("/App_Plugins/Archetype/css/archetype.css");
|
||||
assetsService.loadCss("../App_Plugins/Archetype/css/archetype.css");
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, assetsService, angularHelper, notificationsService, $timeout, entityResource, archetypeService, archetypeLabelService, archetypeCacheService, archetypePropertyEditorResource) {
|
||||
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, assetsService, angularHelper, notificationsService, $timeout, fileManager, entityResource, archetypeService, archetypeLabelService, archetypeCacheService, archetypePropertyEditorResource) {
|
||||
|
||||
//$scope.model.value = "";
|
||||
$scope.model.hideLabel = $scope.model.config.hideLabel == 1;
|
||||
@@ -88,8 +88,11 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
$scope.model.value.fieldsets.push(newFieldset);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.setDirty();
|
||||
|
||||
$scope.$broadcast("archetypeAddFieldset", {index: $index, visible: countVisible()});
|
||||
|
||||
newFieldset.collapse = $scope.model.config.enableCollapsing ? true : false;
|
||||
$scope.focusFieldset(newFieldset);
|
||||
}
|
||||
@@ -100,7 +103,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
if (confirm('Are you sure you want to remove this?')) {
|
||||
$scope.setDirty();
|
||||
$scope.model.value.fieldsets.splice($index, 1);
|
||||
$scope.$broadcast("archetypeRemoveFieldset", {index: $index});
|
||||
$scope.$broadcast("archetypeRemoveFieldset", {index: $index, visible: countVisible()});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,11 +255,36 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
//developerMode helpers
|
||||
$scope.model.value.toString = stringify;
|
||||
|
||||
// issue 114: register handler for file selection
|
||||
$scope.model.value.setFiles = setFiles;
|
||||
|
||||
//encapsulate stringify (should be built into browsers, not sure of IE support)
|
||||
function stringify() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
|
||||
// issue 114: handler for file selection
|
||||
function setFiles(files) {
|
||||
// get all currently selected files from file manager
|
||||
var currentFiles = fileManager.getFiles();
|
||||
|
||||
// get the files already selected for this archetype (by alias)
|
||||
var archetypeFiles = [];
|
||||
_.each(currentFiles, function (item) {
|
||||
if (item.alias === $scope.model.alias) {
|
||||
archetypeFiles.push(item.file);
|
||||
}
|
||||
});
|
||||
|
||||
// add the newly selected files
|
||||
_.each(files, function (file) {
|
||||
archetypeFiles.push(file);
|
||||
});
|
||||
|
||||
// update the selected files for this archetype (by alias)
|
||||
fileManager.setFiles($scope.model.alias, archetypeFiles);
|
||||
}
|
||||
|
||||
//watch for changes
|
||||
$scope.$watch('model.value', function (v) {
|
||||
if ($scope.model.config.developerMode) {
|
||||
@@ -266,6 +294,11 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
$scope.model.value.toString = stringify;
|
||||
}
|
||||
}
|
||||
|
||||
// issue 114: re-register handler for files selection and reset the currently selected files on the file manager
|
||||
$scope.model.value.setFiles = setFiles;
|
||||
fileManager.setFiles($scope.model.alias, []);
|
||||
|
||||
// reset submit watcher counter on save
|
||||
$scope.activeSubmitWatcher = 0;
|
||||
});
|
||||
@@ -334,6 +367,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
|
||||
// recursive validation of nested fieldsets
|
||||
var nestedFieldsetsValid = true;
|
||||
|
||||
_.each(fieldset.properties, function (property) {
|
||||
if (property != null && property.value != null && property.propertyEditorAlias == "Imulus.Archetype") {
|
||||
_.each(property.value.fieldsets, function (inner) {
|
||||
@@ -360,7 +394,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
}
|
||||
|
||||
//archetype css
|
||||
assetsService.loadCss("/App_Plugins/Archetype/css/archetype.css");
|
||||
assetsService.loadCss("../App_Plugins/Archetype/css/archetype.css");
|
||||
|
||||
//custom css
|
||||
if($scope.model.config.customCssPath)
|
||||
@@ -373,10 +407,12 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
// we need to monitor the "formSubmitting" event from a custom property and broadcast our own event
|
||||
// to forcefully update the appropriate model.value's
|
||||
$scope.activeSubmitWatcher = 0;
|
||||
|
||||
$scope.submitWatcherOnLoad = function () {
|
||||
$scope.activeSubmitWatcher++;
|
||||
return $scope.activeSubmitWatcher;
|
||||
}
|
||||
|
||||
$scope.submitWatcherOnSubmit = function () {
|
||||
$scope.$broadcast("archetypeFormSubmitting");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q, editorState, archetypeService, archetypeCacheService) {
|
||||
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q, fileManager, editorState, archetypeService, archetypeCacheService, notificationsService) {
|
||||
|
||||
var linker = function (scope, element, attrs, ngModelCtrl) {
|
||||
var configFieldsetModel = archetypeService.getFieldsetByAlias(scope.archetypeConfig.fieldsets, scope.fieldset.alias);
|
||||
@@ -40,64 +40,12 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
|
||||
|
||||
var mergedConfig = _.extend(defaultConfigObj, config);
|
||||
|
||||
loadView(pathToView, mergedConfig, defaultValue, alias, propertyAlias, scope, element, ngModelCtrl, propertyValueChanged);
|
||||
loadView(pathToView, mergedConfig, defaultValue, alias, propertyAlias, scope, element, ngModelCtrl, configFieldsetModel);
|
||||
});
|
||||
});
|
||||
|
||||
scope.$on("archetypeFormSubmitting", function (ev, args) {
|
||||
// validate all fieldset properties
|
||||
_.each(scope.fieldset.properties, function (property) {
|
||||
validateProperty(scope.fieldset, property);
|
||||
});
|
||||
|
||||
var validationKey = "validation-f" + scope.fieldsetIndex;
|
||||
ngModelCtrl.$setValidity(validationKey, scope.fieldset.isValid);
|
||||
});
|
||||
|
||||
scope.$on("archetypeRemoveFieldset", function (ev, args) {
|
||||
var validationKey = "validation-f" + args.index;
|
||||
ngModelCtrl.$setValidity(validationKey, true);
|
||||
});
|
||||
|
||||
|
||||
// called when the value of any property in a fieldset changes
|
||||
function propertyValueChanged(fieldset, property) {
|
||||
// it's the Umbraco way to hide the invalid state when altering an invalid property, even if the new value isn't valid either
|
||||
property.isValid = true;
|
||||
setFieldsetValidity(fieldset);
|
||||
}
|
||||
|
||||
// validate a property in a fieldset
|
||||
function validateProperty(fieldset, property) {
|
||||
var propertyConfig = archetypeService.getPropertyByAlias(configFieldsetModel, property.alias);
|
||||
if (propertyConfig) {
|
||||
// use property.value !== property.value to check for NaN values on numeric inputs
|
||||
if (propertyConfig.required && (property.value == null || property.value === "" || property.value !== property.value)) {
|
||||
property.isValid = false;
|
||||
}
|
||||
// issue 116: RegEx validate property value
|
||||
// Only validate the property value if anything has been entered - RegEx is considered a supplement to "required".
|
||||
if (property.isValid == true && propertyConfig.regEx && property.value) {
|
||||
var regEx = new RegExp(propertyConfig.regEx);
|
||||
if (regEx.test(property.value) == false) {
|
||||
property.isValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setFieldsetValidity(fieldset);
|
||||
}
|
||||
|
||||
function setFieldsetValidity(fieldset) {
|
||||
// mark the entire fieldset as invalid if there are any invalid properties in the fieldset, otherwise mark it as valid
|
||||
fieldset.isValid =
|
||||
_.find(fieldset.properties, function (property) {
|
||||
return property.isValid == false
|
||||
}) == null;
|
||||
}
|
||||
}
|
||||
|
||||
function loadView(view, config, defaultValue, alias, propertyAlias, scope, element, ngModelCtrl, propertyValueChanged) {
|
||||
function loadView(view, config, defaultValue, alias, propertyAlias, scope, element, ngModelCtrl, configFieldsetModel) {
|
||||
if (view)
|
||||
{
|
||||
$http.get(view, { cache: true }).success(function (data) {
|
||||
@@ -120,9 +68,13 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
|
||||
archetypeService.getFieldset(scope).properties.push(JSON.parse('{"alias": "' + alias + '", "value": "' + defaultValue + '"}'));
|
||||
scope.renderModelPropertyIndex = archetypeService.getPropertyIndexByAlias(archetypeService.getFieldset(scope).properties, alias);
|
||||
}
|
||||
|
||||
scope.renderModel = {};
|
||||
scope.model.value = archetypeService.getFieldsetProperty(scope).value;
|
||||
|
||||
//init the property editor state
|
||||
archetypeService.getFieldsetProperty(scope).editorState = {};
|
||||
|
||||
//set the config from the prevalues
|
||||
scope.model.config = config;
|
||||
|
||||
@@ -141,18 +93,42 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
|
||||
}
|
||||
}
|
||||
|
||||
//upload datatype hack
|
||||
if(view.indexOf('fileupload.html') != -1) {
|
||||
scope.propertyForm = scope.form;
|
||||
scope.model.validation = {};
|
||||
scope.model.validation.mandatory = 0;
|
||||
}
|
||||
|
||||
//some items need an alias
|
||||
scope.model.alias = "archetype-property-" + propertyAlias;
|
||||
//some items also need an id (file upload for example)
|
||||
scope.model.id = propertyAlias;
|
||||
|
||||
//watch for changes since there is no two-way binding with the local model.value
|
||||
scope.$watch('model.value', function (newValue, oldValue) {
|
||||
|
||||
archetypeService.getFieldsetProperty(scope).value = newValue;
|
||||
|
||||
// notify the linker that the property value changed
|
||||
propertyValueChanged(archetypeService.getFieldset(scope), archetypeService.getFieldsetProperty(scope));
|
||||
archetypeService.propertyValueChanged(archetypeService.getFieldset(scope), archetypeService.getFieldsetProperty(scope));
|
||||
});
|
||||
|
||||
scope.$on('formSubmitting', function(ev, args){
|
||||
archetypeCacheService.clearInvalidations();
|
||||
archetypeCacheService.clearNotifications();
|
||||
});
|
||||
|
||||
scope.$on('archetypeFormSubmitting', function (ev, args) {
|
||||
// validate all fieldset properties
|
||||
_.each(scope.fieldset.properties, function (property) {
|
||||
archetypeService.validateProperty(scope.fieldset, property, configFieldsetModel);
|
||||
});
|
||||
|
||||
var validationKey = "validation-f" + scope.fieldsetIndex;
|
||||
|
||||
ngModelCtrl.$setValidity(validationKey, scope.fieldset.isValid);
|
||||
|
||||
// did the value change (if it did, it most likely did so during the "formSubmitting" event)
|
||||
var property = archetypeService.getFieldsetProperty(scope);
|
||||
|
||||
@@ -162,8 +138,44 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
|
||||
archetypeService.getFieldsetProperty(scope).value = scope.model.value;
|
||||
|
||||
// notify the linker that the property value changed
|
||||
propertyValueChanged(archetypeService.getFieldset(scope), archetypeService.getFieldsetProperty(scope));
|
||||
archetypeService.propertyValueChanged(archetypeService.getFieldset(scope), archetypeService.getFieldsetProperty(scope));
|
||||
}
|
||||
|
||||
archetypeService.validateMinFieldsets(scope);
|
||||
|
||||
archetypeCacheService.notifyEditor();
|
||||
});
|
||||
|
||||
// issue 114: handle file selection on property editors
|
||||
scope.$on("filesSelected", function (event, args) {
|
||||
// populate the fileNames collection on the property editor state
|
||||
var property = archetypeService.getFieldsetProperty(scope);
|
||||
|
||||
property.editorState.fileNames = [];
|
||||
|
||||
_.each(args.files, function (item) {
|
||||
property.editorState.fileNames.push(item.name);
|
||||
});
|
||||
|
||||
// remove the files set for this property
|
||||
// NOTE: we can't use property.alias because the file manager registers the selected files on the assigned Archetype property alias (e.g. "archetype-property-archetype-property-archetype-property-content-0-2-0-1-0-0")
|
||||
fileManager.setFiles(scope.model.alias, []);
|
||||
|
||||
// now tell the containing Archetype to pick up the selected files
|
||||
scope.archetypeRenderModel.setFiles(args.files);
|
||||
});
|
||||
|
||||
scope.$on("archetypeRemoveFieldset", function (ev, args) {
|
||||
var validationKey = "validation-f" + args.index;
|
||||
ngModelCtrl.$setValidity(validationKey, true);
|
||||
|
||||
scope.archetypeRenderModel.fieldsets.length = args.visible;
|
||||
|
||||
archetypeService.validateMinFieldsets(scope);
|
||||
});
|
||||
|
||||
scope.$on("archetypeAddFieldset", function (ev, args) {
|
||||
archetypeService.validateMinFieldsets(scope);
|
||||
});
|
||||
|
||||
element.html(data).show();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"toggleAdvancedDescription": "Show advanced options.",
|
||||
"hidePropertyLabels": "Hide Property Labels?",
|
||||
"hidePropertyLabelsDescription": "Hides the property labels.",
|
||||
"minFieldsets": "Min Fieldsets",
|
||||
"maxFieldsets": "Max Fieldsets",
|
||||
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
|
||||
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"toggleAdvancedDescription": "Show advanced options.",
|
||||
"hidePropertyLabels": "Hide Property Labels?",
|
||||
"hidePropertyLabelsDescription": "Hides the property labels.",
|
||||
"minFieldsets": "Min Fieldsets",
|
||||
"maxFieldsets": "Max Fieldsets",
|
||||
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
|
||||
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"toggleAdvancedDescription": "Show advanced options.",
|
||||
"hidePropertyLabels": "Hide Property Labels?",
|
||||
"hidePropertyLabelsDescription": "Hides the property labels.",
|
||||
"minFieldsets": "Min Fieldsets",
|
||||
"maxFieldsets": "Max Fieldsets",
|
||||
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
|
||||
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
|
||||
|
||||
@@ -325,7 +325,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.archetypeMaxFieldsets{
|
||||
.archetypeMaxFieldsets, .archetypeMinFieldsets {
|
||||
border: 1px solid #ddd;
|
||||
width: 40px;
|
||||
text-align: right;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module('umbraco.services').factory('archetypeCacheService', function (archetypePropertyEditorResource) {
|
||||
angular.module('umbraco.services').factory('archetypeCacheService', function (archetypePropertyEditorResource, notificationsService) {
|
||||
//private
|
||||
|
||||
var isEntityLookupLoading = false;
|
||||
@@ -7,7 +7,78 @@ angular.module('umbraco.services').factory('archetypeCacheService', function (ar
|
||||
var isDatatypeLookupLoading = false;
|
||||
var datatypeCache = [];
|
||||
|
||||
var notificationQueue = [];
|
||||
var notificationCache = [];
|
||||
|
||||
var invalidationCache = [];
|
||||
|
||||
function findItem(array, item) {
|
||||
return _.find(array, function(value){
|
||||
return value == item;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
notifyEditor: function() {
|
||||
console.log("queue-v");
|
||||
console.log(notificationQueue);
|
||||
console.log("sent-v");
|
||||
console.log(notificationCache);
|
||||
|
||||
if(this.shouldBeNotified("minFieldsets") && !this.hasBeenNotified("minFieldsets")) {
|
||||
notificationsService.error("Error", "Some of your properties do not contain enough fieldsets.");
|
||||
|
||||
this.removeNotification("minFieldsets");
|
||||
|
||||
notificationCache.push("minFieldsets");
|
||||
}
|
||||
},
|
||||
|
||||
clearInvalidations: function() {
|
||||
invalidationCache = [];
|
||||
},
|
||||
|
||||
addInvalidation: function(key) {
|
||||
if(!this.hasBeenInvalidated(invalidationCache, key)) {
|
||||
invalidationCache.push(key);
|
||||
}
|
||||
},
|
||||
|
||||
removeInvalidation: function(key) {
|
||||
invalidationCache = _.reject(invalidationCache, function(value){
|
||||
return value == key;
|
||||
});
|
||||
},
|
||||
|
||||
hasBeenInvalidated: function(key) {
|
||||
return (typeof findItem(invalidationCache, key) != 'undefined');
|
||||
},
|
||||
|
||||
clearNotifications: function() {
|
||||
notificationCache = [];
|
||||
|
||||
},
|
||||
|
||||
addNotification: function(key) {
|
||||
if(!this.shouldBeNotified(key) && !this.hasBeenNotified(notificationCache, key)) {
|
||||
notificationQueue.push(key);
|
||||
}
|
||||
},
|
||||
|
||||
removeNotification: function(key) {
|
||||
notificationQueue = _.reject(notificationQueue, function(value){
|
||||
return value == key;
|
||||
});
|
||||
},
|
||||
|
||||
shouldBeNotified: function(key) {
|
||||
return (typeof findItem(notificationQueue, key) != 'undefined');
|
||||
},
|
||||
|
||||
hasBeenNotified: function(key) {
|
||||
return (typeof findItem(notificationCache, key) != 'undefined');
|
||||
},
|
||||
|
||||
getDataTypeFromCache: function(guid) {
|
||||
return _.find(datatypeCache, function (dt){
|
||||
return dt.dataTypeGuid == guid;
|
||||
|
||||
@@ -24,7 +24,7 @@ angular.module('umbraco.services').factory('archetypeLocalizationService', funct
|
||||
initLocalizedResources:function () {
|
||||
var deferred = $q.defer();
|
||||
userService.getCurrentUser().then(function(user){
|
||||
$http.get("/App_plugins/Archetype/langs/" + user.locale + ".js", { cache: true })
|
||||
$http.get("../App_plugins/Archetype/langs/" + user.locale + ".js", { cache: true })
|
||||
.then(function(response){
|
||||
service.resourceFileLoaded = true;
|
||||
service.dictionary = response.data;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
angular.module('umbraco.services').factory('archetypeService', function () {
|
||||
|
||||
angular.module('umbraco.services').factory('archetypeService', function (archetypeCacheService) {
|
||||
//public
|
||||
return {
|
||||
//helper that returns a JS ojbect from 'value' string or the original string
|
||||
@@ -67,6 +66,49 @@ angular.module('umbraco.services').factory('archetypeService', function () {
|
||||
},
|
||||
getFieldsetProperty: function (scope) {
|
||||
return this.getFieldset(scope).properties[scope.renderModelPropertyIndex];
|
||||
},
|
||||
setFieldsetValidity: function (fieldset) {
|
||||
// mark the entire fieldset as invalid if there are any invalid properties in the fieldset, otherwise mark it as valid
|
||||
fieldset.isValid =
|
||||
_.find(fieldset.properties, function (property) {
|
||||
return property.isValid == false
|
||||
}) == null;
|
||||
},
|
||||
validateProperty: function (fieldset, property, configFieldsetModel) {
|
||||
var propertyConfig = this.getPropertyByAlias(configFieldsetModel, property.alias);
|
||||
|
||||
if (propertyConfig) {
|
||||
// use property.value !== property.value to check for NaN values on numeric inputs
|
||||
if (propertyConfig.required && (property.value == null || property.value === "" || property.value !== property.value)) {
|
||||
property.isValid = false;
|
||||
}
|
||||
// issue 116: RegEx validate property value
|
||||
// Only validate the property value if anything has been entered - RegEx is considered a supplement to "required".
|
||||
if (property.isValid == true && propertyConfig.regEx && property.value) {
|
||||
var regEx = new RegExp(propertyConfig.regEx);
|
||||
if (regEx.test(property.value) == false) {
|
||||
property.isValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setFieldsetValidity(fieldset);
|
||||
},
|
||||
// called when the value of any property in a fieldset changes
|
||||
propertyValueChanged: function (fieldset, property) {
|
||||
// it's the Umbraco way to hide the invalid state when altering an invalid property, even if the new value isn't valid either
|
||||
property.isValid = true;
|
||||
this.setFieldsetValidity(fieldset);
|
||||
},
|
||||
validateMinFieldsets: function(scope) {
|
||||
//ngModelCtrl.$setValidity('propertyForm', true);
|
||||
archetypeCacheService.removeInvalidation("minFieldsets");
|
||||
|
||||
if(scope.archetypeConfig.minFieldsets && scope.archetypeRenderModel.fieldsets.length < scope.archetypeConfig.minFieldsets) {
|
||||
//ngModelCtrl.$setValidity('propertyForm', false);
|
||||
archetypeCacheService.addInvalidation("minFieldsets");
|
||||
archetypeCacheService.addNotification("minFieldsets");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -97,6 +97,10 @@
|
||||
<label for="archetypeAdvancedOptionsHideLabels"><archetype-localize key="hidePropertyLabels">Hide Property Labels?</archetype-localize><small><archetype-localize key="hidePropertyLabelsDescription">Hides the property labels.</archetype-localize></small></label>
|
||||
<input type="checkbox" id="archetypeAdvancedOptionsHideLabels" ng-model="archetypeConfigRenderModel.hidePropertyLabels"/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="archetypeAdvancedOptionsMinFieldsets"><archetype-localize key="minFieldsets">Min Fieldsets</archetype-localize><small><archetype-localize key="minFieldsetsDescription">How many Fieldsets are required? Leaving blank will disable the control. Default is unlimited.</archetype-localize></small></label>
|
||||
<input type="number" id="archetypeAdvancedOptionsMinFieldsets" class="archetypeMinFieldsets" ng-model="archetypeConfigRenderModel.minFieldsets"/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="archetypeAdvancedOptionsMaxFieldsets"><archetype-localize key="maxFieldsets">Max Fieldsets</archetype-localize><small><archetype-localize key="maxFieldsetsDescription">How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.</archetype-localize></small></label>
|
||||
<input type="number" id="archetypeAdvancedOptionsMaxFieldsets" class="archetypeMaxFieldsets" ng-model="archetypeConfigRenderModel.maxFieldsets"/>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Archetype",
|
||||
"version": "1.8",
|
||||
"version": "1.9",
|
||||
"url": "http://github.com/imulus/archetype/",
|
||||
"author": "Imulus - Kevin Giszewski - Tom Fulton - Lee Kelleher - Matt Brailsford - Kenn Jacobsen - Et. Al.",
|
||||
"authorUrl": "http://imulus.com/",
|
||||
|
||||
Reference in New Issue
Block a user