Skip to content
This repository was archived by the owner on Feb 10, 2024. It is now read-only.

Preparing 1.2.0 #184

Merged
merged 12 commits into from
Apr 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ A grid editor for Umbraco 8 that allows you to use Doc Types as a blue print for

### Installation

> *Note:* Doc Type Grid Editor has been developed against **Umbraco v8.1.0** and will support that version and above.
> *Note:* Doc Type Grid Editor has been developed against **Umbraco v8.6.0** and will support that version and above.

Doc Type Grid Editor can be installed from either Our Umbraco package repository, or build manually from the source-code.

Expand Down Expand Up @@ -60,8 +60,6 @@ Please be aware that not all property-editors will work within Doc Type Grid Edi
* Tags
* Upload

Another known issue is that validation of property-editors within the overlay do not always work. For editors that use client-side (HTML5) validation, this may appear to work, (e.g. text input require attribute is added), but server-side validation does not work.

---

## Contributing to this project
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
image: Visual Studio 2017

# version format
version: 1.1.0.{build}
version: 1.2.0.{build}

# UMBRACO_PACKAGE_PRERELEASE_SUFFIX if a rtm release build this should be blank, otherwise if empty will default to alpha
# example UMBRACO_PACKAGE_PRERELEASE_SUFFIX=beta
Expand Down
2 changes: 1 addition & 1 deletion build/package.proj
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<PropertyGroup>
<ProjectName>Our.Umbraco.DocTypeGridEditor</ProjectName>
<PackageName>Doc Type Grid Editor</PackageName>
<MinUmbracoVersion>8.1.0</MinUmbracoVersion>
<MinUmbracoVersion>8.6.0</MinUmbracoVersion>
<Readme>Doc Type Grid Editor is an advanced grid editor for Umbraco 8</Readme>
<AuthorName>Matt Brailsford, Lee Kelleher, Søren Kottal</AuthorName>
<AuthorUrl>https://github.com/umco/umbraco-doc-type-grid-editor/graphs/contributors</AuthorUrl>
Expand Down
41 changes: 41 additions & 0 deletions docs/developers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,47 @@ By inheriting from the `DocTypeGridEditorSurfaceController` base class, you'll a

---

### Value Processors
Since Doc Type Grid Editor stores the data for each property as a JSON-blob, we're not processing the values in the same way as Umbraco-core before storing it. This also means that the values that comes back and are passed into a Property Value Converter might be in of a type/format that that Property Value Convert can't handle.

We've added something that we call "ValueProcessors" and these can be used to modify the raw property value before we send it to the property value converter. One example of where this is needed is the Tags-editor.

If you need to perform some processing of a value before it's sent to the property value converter you can add your own ValueProcessor.

```csharp
public class UmbracoColorPickerValueProcessor : IDocTypeGridEditorValueProcessor
{
public bool IsProcessorFor(string propertyEditorAlias)
=> propertyEditorAlias.Equals(Constants.PropertyEditors.Aliases.ColorPicker);

public object ProcessValue(object value)
{
// Do something with the value
return value;
}
}
```

Then register this during composition withing IUserComposer,
```csharp
public class MyCustomDocTypeGridEditorComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.DocTypeGridEditorValueProcessors()
.Append<UmbracoColorPickerValueProcessor>();
}
}
```

Dot Type Grid editor ships with a ValueProcessor for the Umbraco-Tags property.

**Note:** When using a Tag-editor inside a DTGE this would not create any relationship between the current node and that tag, if you need to tag a node you should use the Tags-editor as a property directly on the document type.





### Useful Links

* [Source Code](https://github.com/skttl/umbraco-doc-type-grid-editor)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Our.Umbraco.DocTypeGridEditor.Extensions;
using Our.Umbraco.DocTypeGridEditor.ValueProcessing;
using Umbraco.Core;
using Umbraco.Core.Composing;

namespace Our.Umbraco.DocTypeGridEditor.Composing
{
/// <summary>
/// Composes defaults for Doc Type Grid Editor
/// </summary>
public class DocTypeGridEditorComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.DocTypeGridEditorValueProcessors().Append<UmbracoTagsValueProcessor>();
composition.DataValueReferenceFactories().Append<DocTypeGridEditorDataValueReference>();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Our.Umbraco.DocTypeGridEditor.ValueProcessing.Collections;
using Umbraco.Core.Composing;

namespace Our.Umbraco.DocTypeGridEditor.Extensions
{
public static class CompositionExtensions
{
/// <summary>
/// Used to modify the collection of Value Processors for Doc Type Grid Editor
/// </summary>
/// <param name="composition"></param>
/// <returns></returns>
public static DocTypeGridEditorValueProcessorsCollectionBuilder DocTypeGridEditorValueProcessors(this Composition composition)
=> composition.WithCollectionBuilder<DocTypeGridEditorValueProcessorsCollectionBuilder>();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Our.Umbraco.DocTypeGridEditor.Extensions;
using Our.Umbraco.DocTypeGridEditor.Models;
using Our.Umbraco.DocTypeGridEditor.ValueProcessing;
using Our.Umbraco.DocTypeGridEditor.ValueProcessing.Collections;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Web.Composing;
Expand Down Expand Up @@ -64,6 +67,14 @@ private static IPublishedElement ConvertValue(string id, string contentTypeAlias

var newValue = propEditor.GetValueEditor().FromEditor(contentPropData, jProp.Value);

// Performing "ValueProcessing" if any ValueProcessor is configured for this Property Editor-alias.
var processorsCollection = Current.Factory.GetInstance<DocTypeGridEditorValueProcessorsCollection>();
var processor = processorsCollection.FirstOrDefault(x => x.IsProcessorFor(propEditor.Alias));
if (processor != null)
{
newValue = processor.ProcessValue(newValue);
}

/* Now that we have the DB stored value, we actually need to then convert it into its
* XML serialized state as expected by the published property by calling ConvertDbToString
*/
Expand Down
20 changes: 20 additions & 0 deletions src/Our.Umbraco.DocTypeGridEditor/Models/DocTypeGridEditorValue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Our.Umbraco.DocTypeGridEditor.Models
{
public class DocTypeGridEditorValue
{
[JsonProperty("value")]
public JObject Value { get; set; }
[JsonProperty("dtgeContentTypeAlias")]
public string ContentTypeAlias { get; set; }
[JsonProperty("id")]
public Guid Id { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,17 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.9.9.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.9\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core.Mvc, Version=1.9.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency-Mvc5.1.9.3\lib\net45\ClientDependency.Core.Mvc.dll</HintPath>
</Reference>
<Reference Include="CSharpTest.Net.Collections, Version=14.906.1403.1082, Culture=neutral, PublicKeyToken=06aee00cce822474, processorArchitecture=MSIL">
<HintPath>..\packages\CSharpTest.Net.Collections.14.906.1403.1082\lib\net40\CSharpTest.Net.Collections.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.1.0.0\lib\net452\Examine.dll</HintPath>
<Reference Include="Examine, Version=1.0.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.1.0.2\lib\net452\Examine.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.8.14.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.8.14\lib\Net45\HtmlAgilityPack.dll</HintPath>
Expand Down Expand Up @@ -206,21 +212,26 @@
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="Umbraco.Core, Version=8.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UmbracoCms.Core.8.1.0\lib\net472\Umbraco.Core.dll</HintPath>
<HintPath>..\packages\UmbracoCms.Core.8.6.0\lib\net472\Umbraco.Core.dll</HintPath>
</Reference>
<Reference Include="Umbraco.Examine, Version=8.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UmbracoCms.Web.8.1.0\lib\net472\Umbraco.Examine.dll</HintPath>
<HintPath>..\packages\UmbracoCms.Web.8.6.0\lib\net472\Umbraco.Examine.dll</HintPath>
</Reference>
<Reference Include="Umbraco.ModelsBuilder.Embedded, Version=8.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UmbracoCms.Web.8.6.0\lib\net472\Umbraco.ModelsBuilder.Embedded.dll</HintPath>
</Reference>
<Reference Include="Umbraco.Web, Version=8.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UmbracoCms.Web.8.1.0\lib\net472\Umbraco.Web.dll</HintPath>
<HintPath>..\packages\UmbracoCms.Web.8.6.0\lib\net472\Umbraco.Web.dll</HintPath>
</Reference>
<Reference Include="Umbraco.Web.UI, Version=8.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UmbracoCms.Web.8.1.0\lib\net472\Umbraco.Web.UI.dll</HintPath>
<HintPath>..\packages\UmbracoCms.Web.8.6.0\lib\net472\Umbraco.Web.UI.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Bootstrap.cs" />
<Compile Include="Composing\Current.cs" />
<Compile Include="Models\DocTypeGridEditorValue.cs" />
<Compile Include="ValueProcessing\DocTypeGridEditorDataValueReference.cs" />
<Compile Include="Extensions\JsonExtensions.cs" />
<Compile Include="Helpers\DocTypeGridEditorHelper.cs" />
<Compile Include="Helpers\XmlHelper.cs" />
Expand All @@ -231,6 +242,12 @@
<Compile Include="Models\UnpublishedProperty.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\VersionInfo.cs" />
<Compile Include="Composing\DocTypeGridEditorComposer.cs" />
<Compile Include="Extensions\CompositionExtensions.cs" />
<Compile Include="ValueProcessing\Collections\DocTypeGridEditorValueProcessorsCollection.cs" />
<Compile Include="ValueProcessing\Collections\DocTypeGridEditorValueProcessorsCollectionBuilder.cs" />
<Compile Include="ValueProcessing\IDocTypeGridEditorValueProcessor.cs" />
<Compile Include="ValueProcessing\UmbracoTagsValueProcessor.cs" />
<Compile Include="Web\Controllers\DocTypeGridEditorApiController.cs" />
<Compile Include="Extensions\ContentTypeServiceExtensions.cs" />
<Compile Include="Web\Controllers\DocTypeGridEditorSurfaceController.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Collections.Generic;
using Umbraco.Core.Composing;

namespace Our.Umbraco.DocTypeGridEditor.ValueProcessing.Collections
{
/// <summary>
/// Collection to hold references to Value Processors to be used with Doc Type Grid Editor. <see cref="IDocTypeGridEditorValueProcessor"/>
/// </summary>
public class DocTypeGridEditorValueProcessorsCollection : BuilderCollectionBase<IDocTypeGridEditorValueProcessor>
{
public DocTypeGridEditorValueProcessorsCollection(IEnumerable<IDocTypeGridEditorValueProcessor> items) : base(items)
{ }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Umbraco.Core.Composing;

namespace Our.Umbraco.DocTypeGridEditor.ValueProcessing.Collections
{
/// <summary>
/// Collection builder for Value Processors <see cref="IDocTypeGridEditorValueProcessor"/>
/// </summary>
public class DocTypeGridEditorValueProcessorsCollectionBuilder : OrderedCollectionBuilderBase<DocTypeGridEditorValueProcessorsCollectionBuilder, DocTypeGridEditorValueProcessorsCollection, IDocTypeGridEditorValueProcessor>
{
protected override DocTypeGridEditorValueProcessorsCollectionBuilder This => this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Newtonsoft.Json;
using Our.Umbraco.DocTypeGridEditor.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.PropertyEditors;

namespace Our.Umbraco.DocTypeGridEditor.ValueProcessing
{
public class DocTypeGridEditorDataValueReference : IDataValueReferenceFactory, IDataValueReference
{
private readonly Lazy<Dictionary<string, IContentType>> _contentTypes;

public IDataValueReference GetDataValueReference() => this;

public bool IsForEditor(IDataEditor dataEditor) => dataEditor.Alias.InvariantEquals(Constants.PropertyEditors.Aliases.Grid);


public DocTypeGridEditorDataValueReference()
{
_contentTypes = new Lazy<Dictionary<string, IContentType>>(() => Current.Services.ContentTypeService.GetAll().ToDictionary(c => c.Alias));
}

public IEnumerable<UmbracoEntityReference> GetReferences(object value)
{
var result = new List<UmbracoEntityReference>();
var _propertyEditors = Current.PropertyEditors;
var rawJson = value == null ? string.Empty : value is string str ? str : value.ToString();
DeserializeGridValue(rawJson, out var dtgeValues);

foreach (var control in dtgeValues)
{
if (_contentTypes.Value.TryGetValue(control.ContentTypeAlias, out var contentType))
{
var propertyTypes = contentType.CompositionPropertyTypes.ToDictionary(x => x.Alias, x => x);
var properties = control.Value.Properties();

foreach (var property in properties)
{
if (propertyTypes.TryGetValue(property.Name, out var propertyType))
{
if (_propertyEditors.TryGet(propertyType.PropertyEditorAlias, out var propertyEditor))
{
if (propertyEditor.GetValueEditor() is IDataValueReference reference)
{
var propertyValue = property.Value.ToString();
var refs = reference.GetReferences(propertyValue);
result.AddRange(refs);
}
}
}
}
}
}
return result;

}

internal GridValue DeserializeGridValue(string rawJson, out IEnumerable<DocTypeGridEditorValue> dtgeValues)
{
var grid = JsonConvert.DeserializeObject<GridValue>(rawJson);

// Find all controls that uses DTGE editor
var controls = grid.Sections.SelectMany(x => x.Rows.SelectMany(r => r.Areas).SelectMany(a => a.Controls)).ToArray();
dtgeValues = controls.Where(x => x.Editor.Alias.ToLowerInvariant() == "doctype").Select(x => x.Value.ToObject<DocTypeGridEditorValue>());

return grid;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Our.Umbraco.DocTypeGridEditor.ValueProcessing
{
/// <summary>
/// Abstracts a ValueProcessor that is used to modify a property value before it's sent to a Property Value Converter
/// These are useful when the data format stored for DTGE is different from what the PVC expects ie. like Umbraco.Tags
/// </summary>
public interface IDocTypeGridEditorValueProcessor
{
/// <summary>
/// Returns if this processor can handle a certain property editor based on the property editors alias.
/// </summary>
/// <param name="propertyEditorAlias">Contains the alias of the property editor ie. "Umbraco.Tags" or "Umbraco.Picker".</param>
/// <returns></returns>
bool IsProcessorFor(string propertyEditorAlias);

/// <summary>
/// Processes the value to de desired format/type. Most of the time this is to make sure that the object passed to the property value converters is
/// of the correct type and in the correct format for the property value converter to handle.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
object ProcessValue(object value);
}
}
Loading