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

Commit 7fbbe60

Browse files
committed
Further work on the replacement preview mechanism
- Strongly-typed the preview data - Extended the `PreviewModel` to be a full `IPublishedContent` - Re-added support for UnpublishedContent nodes - Removed the preview action-filter (again) - Added support for backwards-compatibility
1 parent fa3facc commit 7fbbe60

File tree

12 files changed

+416
-56
lines changed

12 files changed

+416
-56
lines changed

src/Our.Umbraco.DocTypeGridEditor/Bootstrap.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
using System;
2-
using System.Web.Mvc;
32
using Newtonsoft.Json;
4-
using Our.Umbraco.DocTypeGridEditor.Web.Attributes;
53
using Our.Umbraco.DocTypeGridEditor.Web.Mvc;
64
using Umbraco.Core;
75
using Umbraco.Core.Sync;
86
using Umbraco.Web.Cache;
9-
using Umbraco.Web.Routing;
107

118
namespace Our.Umbraco.DocTypeGridEditor
129
{
1310
internal class Bootstrap : ApplicationEventHandler
1411
{
1512
protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
1613
{
17-
GlobalFilters.Filters.Add(new DocTypeGridEditorPreviewAttribute());
18-
1914
if (DefaultDocTypeGridEditorSurfaceControllerResolver.HasCurrent == false)
2015
{
2116
DefaultDocTypeGridEditorSurfaceControllerResolver.Current = new DefaultDocTypeGridEditorSurfaceControllerResolver();
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Umbraco.Core;
5+
using Umbraco.Core.Models;
6+
using Umbraco.Core.Models.PublishedContent;
7+
using Umbraco.Core.PropertyEditors;
8+
using Umbraco.Core.Services;
9+
using Umbraco.Web.Models;
10+
11+
namespace Our.Umbraco.DocTypeGridEditor.Models
12+
{
13+
internal class UnpublishedContent : PublishedContentWithKeyBase
14+
{
15+
private readonly IContent content;
16+
17+
private readonly Lazy<IEnumerable<IPublishedContent>> children;
18+
private readonly Lazy<PublishedContentType> contentType;
19+
private readonly Lazy<string> creatorName;
20+
private readonly Lazy<IPublishedContent> parent;
21+
private readonly Lazy<Dictionary<string, IPublishedProperty>> properties;
22+
private readonly Lazy<string> urlName;
23+
private readonly Lazy<string> writerName;
24+
25+
public UnpublishedContent(int id, ServiceContext serviceContext)
26+
: this(serviceContext.ContentService.GetById(id), serviceContext)
27+
{ }
28+
29+
public UnpublishedContent(IContent content, ServiceContext serviceContext)
30+
: base()
31+
{
32+
Mandate.ParameterNotNull(content, nameof(content));
33+
Mandate.ParameterNotNull(serviceContext, nameof(serviceContext));
34+
35+
var userService = new Lazy<IUserService>(() => serviceContext.UserService);
36+
37+
this.content = content;
38+
39+
this.children = new Lazy<IEnumerable<IPublishedContent>>(() => this.content.Children().Select(x => new UnpublishedContent(x, serviceContext)).ToList());
40+
this.contentType = new Lazy<PublishedContentType>(() => PublishedContentType.Get(this.ItemType, this.DocumentTypeAlias));
41+
this.creatorName = new Lazy<string>(() => this.content.GetCreatorProfile(userService.Value).Name);
42+
this.parent = new Lazy<IPublishedContent>(() => new UnpublishedContent(this.content.Parent(), serviceContext));
43+
this.properties = new Lazy<Dictionary<string, IPublishedProperty>>(() => MapProperties(PropertyEditorResolver.Current, serviceContext));
44+
this.urlName = new Lazy<string>(() => this.content.Name.ToUrlSegment());
45+
this.writerName = new Lazy<string>(() => this.content.GetWriterProfile(userService.Value).Name);
46+
}
47+
48+
public override Guid Key => this.content.Key;
49+
50+
public override PublishedItemType ItemType => PublishedItemType.Content;
51+
52+
public override int Id => this.content.Id;
53+
54+
public override int TemplateId => this.content.Template?.Id ?? default(int);
55+
56+
public override int SortOrder => this.content.SortOrder;
57+
58+
public override string Name => this.content.Name;
59+
60+
public override string UrlName => this.urlName.Value;
61+
62+
public override string DocumentTypeAlias => this.content.ContentType?.Alias;
63+
64+
public override int DocumentTypeId => this.content.ContentType?.Id ?? default(int);
65+
66+
public override string WriterName => this.writerName.Value;
67+
68+
public override string CreatorName => this.creatorName.Value;
69+
70+
public override int WriterId => this.content.WriterId;
71+
72+
public override int CreatorId => this.content.CreatorId;
73+
74+
public override string Path => this.content.Path;
75+
76+
public override DateTime CreateDate => this.content.CreateDate;
77+
78+
public override DateTime UpdateDate => this.content.UpdateDate;
79+
80+
public override Guid Version => this.content.Version;
81+
82+
public override int Level => this.content.Level;
83+
84+
public override bool IsDraft => true;
85+
86+
public override IPublishedContent Parent => this.parent.Value;
87+
88+
public override IEnumerable<IPublishedContent> Children => this.children.Value;
89+
90+
public override PublishedContentType ContentType => this.contentType.Value;
91+
92+
public override ICollection<IPublishedProperty> Properties => this.properties.Value.Values;
93+
94+
public override IPublishedProperty GetProperty(string alias)
95+
{
96+
return this.properties.Value.TryGetValue(alias, out IPublishedProperty property) ? property : null;
97+
}
98+
99+
private Dictionary<string, IPublishedProperty> MapProperties(PropertyEditorResolver resolver, ServiceContext services)
100+
{
101+
var contentType = this.contentType.Value;
102+
var properties = this.content.Properties;
103+
104+
var items = new Dictionary<string, IPublishedProperty>(StringComparer.InvariantCultureIgnoreCase);
105+
106+
foreach (var propertyType in contentType.PropertyTypes)
107+
{
108+
var property = properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyType.PropertyTypeAlias));
109+
var value = property?.Value;
110+
if (value != null)
111+
{
112+
var propertyEditor = resolver.GetByAlias(propertyType.PropertyEditorAlias);
113+
if (propertyEditor != null)
114+
{
115+
value = propertyEditor.ValueEditor.ConvertDbToString(property, property.PropertyType, services.DataTypeService);
116+
}
117+
}
118+
119+
items.Add(propertyType.PropertyTypeAlias, new UnpublishedProperty(propertyType, value));
120+
}
121+
122+
return items;
123+
}
124+
}
125+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using Umbraco.Core.Models;
3+
using Umbraco.Core.Models.PublishedContent;
4+
5+
namespace Our.Umbraco.DocTypeGridEditor.Models
6+
{
7+
internal class UnpublishedProperty : IPublishedProperty
8+
{
9+
private readonly PublishedPropertyType propertyType;
10+
private readonly object dataValue;
11+
private readonly Lazy<bool> hasValue;
12+
private readonly Lazy<object> sourceValue;
13+
private readonly Lazy<object> objectValue;
14+
private readonly Lazy<object> xpathValue;
15+
16+
public UnpublishedProperty(PublishedPropertyType propertyType, object value)
17+
{
18+
this.propertyType = propertyType;
19+
20+
this.dataValue = value;
21+
this.hasValue = new Lazy<bool>(() => value != null && value.ToString().Trim().Length > 0);
22+
23+
this.sourceValue = new Lazy<object>(() => this.propertyType.ConvertDataToSource(this.dataValue, true));
24+
this.objectValue = new Lazy<object>(() => this.propertyType.ConvertSourceToObject(this.sourceValue.Value, true));
25+
this.xpathValue = new Lazy<object>(() => this.propertyType.ConvertSourceToXPath(this.sourceValue.Value, true));
26+
}
27+
28+
public string PropertyTypeAlias => this.propertyType.PropertyTypeAlias;
29+
30+
public bool HasValue => this.hasValue.Value;
31+
32+
public object DataValue => this.dataValue;
33+
34+
public object Value => this.objectValue.Value;
35+
36+
public object XPathValue => this.xpathValue.Value;
37+
}
38+
}

src/Our.Umbraco.DocTypeGridEditor/Our.Umbraco.DocTypeGridEditor.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070
</Reference>
7171
<Reference Include="System" />
7272
<Reference Include="System.Core" />
73+
<Reference Include="System.Net.Http" />
74+
<Reference Include="System.Runtime.Serialization" />
7375
<Reference Include="System.Web" />
7476
<Reference Include="System.Web.Http, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
7577
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath>
@@ -100,15 +102,19 @@
100102
<Compile Include="Models\DetachedPublishedContent.cs" />
101103
<Compile Include="Models\DetachedPublishedProperty.cs" />
102104
<Compile Include="Models\JsonDbRow.cs" />
105+
<Compile Include="Models\UnpublishedContent.cs" />
106+
<Compile Include="Models\UnpublishedProperty.cs" />
103107
<Compile Include="PackageActions\AddObjectToJsonArray.cs" />
104108
<Compile Include="Properties\AssemblyInfo.cs" />
105109
<Compile Include="Properties\VersionInfo.cs" />
106-
<Compile Include="Web\Attributes\DocTypeGridEditorPreviewAttribute.cs" />
107110
<Compile Include="Web\Controllers\DocTypeGridEditorApiController.cs" />
108111
<Compile Include="Extensions\ContentTypeServiceExtensions.cs" />
109112
<Compile Include="Web\Controllers\DocTypeGridEditorSurfaceController.cs" />
110113
<Compile Include="Web\Extensions\HtmlHelperExtensions.cs" />
111114
<Compile Include="Web\Helpers\SurfaceControllerHelper.cs" />
115+
<Compile Include="Web\Helpers\ViewHelper.cs" />
116+
<Compile Include="Web\Models\PreviewData.cs" />
117+
<Compile Include="Web\Models\PreviewModel.cs" />
112118
<Compile Include="Web\Mvc\DefaultDocTypeGridEditorSurfaceControllerResolver.cs" />
113119
</ItemGroup>
114120
<ItemGroup>

src/Our.Umbraco.DocTypeGridEditor/Web/Attributes/DocTypeGridEditorPreviewAttribute.cs

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/Our.Umbraco.DocTypeGridEditor/Web/Controllers/DocTypeGridEditorApiController.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Net.Http;
5+
using System.Net.Http.Headers;
6+
using System.Net.Mime;
47
using System.Text.RegularExpressions;
58
using System.Web.Http;
69
using System.Web.Http.ModelBinding;
710
using Our.Umbraco.DocTypeGridEditor.Extensions;
11+
using Our.Umbraco.DocTypeGridEditor.Helpers;
12+
using Our.Umbraco.DocTypeGridEditor.Models;
13+
using Umbraco.Core.Configuration;
814
using Umbraco.Core.Models;
915
using Umbraco.Core.PropertyEditors;
16+
using Umbraco.Web;
1017
using Umbraco.Web.Editors;
18+
using Umbraco.Web.Models;
1119
using Umbraco.Web.Mvc;
20+
using Umbraco.Web.Routing;
1221

1322
namespace Our.Umbraco.DocTypeGridEditor.Web.Controllers
1423
{
@@ -86,5 +95,73 @@ public object GetDataTypePreValues(string dtdId)
8695
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
8796
return propEditor.PreValueEditor.ConvertDbToEditor(propEditor.DefaultPreValues, preValue);
8897
}
98+
99+
[HttpPost]
100+
public HttpResponseMessage GetPreviewMarkup([FromBody] PreviewData data, [FromUri] int pageId)
101+
{
102+
var page = default(IPublishedContent);
103+
104+
// If the page is new, then the ID will be zero
105+
if (pageId > 0)
106+
{
107+
// Get page container node
108+
page = UmbracoContext.ContentCache.GetById(pageId);
109+
if (page == null)
110+
{
111+
// If unpublished, then fake PublishedContent (with IContent object)
112+
page = new UnpublishedContent(pageId, Services);
113+
}
114+
}
115+
116+
// NOTE: The previous previewer had a content node associated with the request,
117+
// meaning that an implementation may have used this to traverse the content-tree.
118+
// In order to maintain backward-compatibility, we must ensure the PublishedContentRequest context.
119+
if (UmbracoContext.PublishedContentRequest == null)
120+
{
121+
UmbracoContext.PublishedContentRequest = new PublishedContentRequest(
122+
Request.RequestUri,
123+
UmbracoContext.RoutingContext,
124+
UmbracoConfig.For.UmbracoSettings().WebRouting,
125+
null)
126+
{
127+
PublishedContent = page
128+
};
129+
}
130+
131+
// TODO: Review this, the call feels heavy.
132+
if (page != null)
133+
{
134+
var culture = page.GetCulture();
135+
System.Threading.Thread.CurrentThread.CurrentCulture = culture;
136+
System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
137+
}
138+
139+
// Get content node object
140+
var content = DocTypeGridEditorHelper.ConvertValueToContent(data.Id, data.ContentTypeAlias, data.Value);
141+
142+
// Construct preview model
143+
var model = new PreviewModel
144+
{
145+
Page = page,
146+
Item = content,
147+
EditorAlias = data.EditorAlias,
148+
PreviewViewPath = data.PreviewViewPath,
149+
ViewPath = data.ViewPath
150+
};
151+
152+
// Render view
153+
var partialName = "~/App_Plugins/DocTypeGridEditor/Render/DocTypeGridEditorPreviewer.cshtml";
154+
var markup = Helpers.ViewHelper.RenderPartial(partialName, model, UmbracoContext.HttpContext);
155+
156+
// Return response
157+
var response = new HttpResponseMessage
158+
{
159+
Content = new StringContent(markup ?? string.Empty)
160+
};
161+
162+
response.Content.Headers.ContentType = new MediaTypeHeaderValue(MediaTypeNames.Text.Html);
163+
164+
return response;
165+
}
89166
}
90167
}

src/Our.Umbraco.DocTypeGridEditor/Web/Extensions/HtmlHelperExtensions.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ namespace Our.Umbraco.DocTypeGridEditor.Web.Extensions
1212
{
1313
public static class HtmlHelperExtensions
1414
{
15+
// HACK: This is to ensure backwards-compatibility for existing websites.
16+
// TODO: Once we bump the major version number, we can remove this stub method.
17+
public static HtmlString RenderDocTypeGridEditorItem(
18+
this HtmlHelper helper,
19+
IPublishedContent content,
20+
string editorAlias,
21+
string viewPath,
22+
string previewViewPath)
23+
{
24+
return helper.RenderDocTypeGridEditorItem(content, editorAlias, viewPath, previewViewPath, false);
25+
}
26+
1527
public static HtmlString RenderDocTypeGridEditorItem(
1628
this HtmlHelper helper,
1729
IPublishedContent content,

0 commit comments

Comments
 (0)