Live preview feature (Orchard.ContentPreview back-port; Lombiq Technologies: WESD-1) (#8260)

This commit is contained in:
Zoltán Lehóczky
2019-08-15 21:21:45 +02:00
committed by Sébastien Ros
parent bbc86d38cd
commit 638a588101
25 changed files with 911 additions and 11 deletions

View File

@@ -0,0 +1,77 @@
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
using Orchard.Core.Common.Models;
using Orchard.Localization;
using Orchard.Mvc;
using Orchard.Security;
using Orchard.Services;
using Orchard.Themes;
using Orchard.UI.Notify;
namespace Orchard.ContentPreview.Controllers {
[Themed]
public class PreviewController : Controller, IUpdateModel {
private readonly IContentManager _contentManager;
private readonly INotifier _notifier;
private readonly IClock _clock;
private readonly IAuthorizer _authorizer;
private readonly IHttpContextAccessor _hca;
public PreviewController(
IContentManager contentManager,
INotifier notifier,
IClock clock,
IAuthorizer authorizer,
IHttpContextAccessor hca) {
_clock = clock;
_notifier = notifier;
_contentManager = contentManager;
_authorizer = authorizer;
_hca = hca;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public ActionResult Index() => View();
[HttpPost]
[ValidateInput(false)]
public ActionResult Render() {
if (!_authorizer.Authorize(Permissions.ContentPreview)) {
return new HttpUnauthorizedResult();
}
var contentItemType = _hca.Current().Request.Form["ContentItemType"];
var contentItem = _contentManager.New(contentItemType);
contentItem.VersionRecord = new ContentItemVersionRecord();
var commonPart = contentItem.As<CommonPart>();
if (commonPart != null) {
commonPart.CreatedUtc = commonPart.ModifiedUtc = commonPart.PublishedUtc = _clock.UtcNow;
}
var model = _contentManager.UpdateEditor(contentItem, this);
if (!ModelState.IsValid) {
return View();
}
_notifier.Warning(T("The Content Preview feature doesn't support properties where there are relationships to ContentPartRecord (e.g. Taxonomies, Tags). These won't update in the preview windows but otherwise keep working."));
model = _contentManager.BuildDisplay(contentItem, "Detail");
return View(model);
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) =>
TryUpdateModel(model, prefix, includeProperties, excludeProperties);
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) =>
ModelState.AddModelError(key, errorMessage.ToString());
}
}

View File

@@ -0,0 +1,9 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
namespace Orchard.ContentPreview.Drivers {
public class ContentPreviewDriver : ContentPartDriver<ContentPart> {
protected override DriverResult Editor(ContentPart part, dynamic shapeHelper) =>
ContentShape("ContentPreview_Button", () => shapeHelper.ContentPreview_Button(Model: part.ContentItem));
}
}

View File

@@ -0,0 +1,12 @@
Name: Content Preview
AntiForgery: enabled
Author: The Orchard Team
Website: https://orchardproject.net
Version: 1.0
OrchardVersion: 1.10.3
Description: The content Preview module enables live content editing and content preview.
Features:
Orchard.ContentPreview:
Description: The content Preview module enables live content editing and content preview.
Category: Content
Dependencies: Contents

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Orchard.ContentPreview</RootNamespace>
<AssemblyName>Orchard.ContentPreview</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>4.0</OldToolsVersion>
<UpgradeBackupLocation />
<TargetFrameworkProfile />
<UseIISExpress>false</UseIISExpress>
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<Use64BitIISExpress />
<UseGlobalApplicationHostFile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>latest</LangVersion>
<CodeAnalysisRuleSet>..\..\..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>latest</LangVersion>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Web" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="Controllers\PreviewController.cs" />
<Compile Include="Drivers\ContentPreviewDriver.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\contentpreview.edit.js" />
<Content Include="Scripts\js.cookie.js" />
<Content Include="packages.config" />
<Content Include="Web.config" />
<Content Include="Scripts\Web.config" />
<Content Include="Module.txt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
<Private>$(MvcBuildViews)</Private>
</ProjectReference>
<ProjectReference Include="..\..\Core\Orchard.Core.csproj">
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
<Name>Orchard.Core</Name>
<Private>$(MvcBuildViews)</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Placement.info">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Views\ContentPreview.Button.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Preview\Index.cshtml" />
<Content Include="Views\Preview\Render.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="README.md" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)" />
</Target>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>45979</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>https://github.com/OrchardCMS/Orchard</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
using Orchard.Environment.Extensions.Models;
using Orchard.Security.Permissions;
namespace Orchard.ContentPreview {
public class Permissions : IPermissionProvider {
public static readonly Permission ContentPreview =
new Permission { Name = nameof(ContentPreview), Description = "Display content preview" };
public virtual Feature Feature { get; set; }
public IEnumerable<Permission> GetPermissions() => new[] { ContentPreview };
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() =>
new[] {
new PermissionStereotype {
Name = "Administrator",
Permissions = new[] { ContentPreview }
}
};
}
}

View File

@@ -0,0 +1,14 @@
<Placement>
<!-- By default only enabling the content preview for content types where it most possibly makes sens. -->
<Match Path="~/Admin/Contents/*">
<Place ContentPreview_Button="Sidebar:27" />
</Match>
<Match Path="~/Admin/Blogs/*">
<Place ContentPreview_Button="Sidebar:27" />
</Match>
<Match Path="~/Admin/Widgets/*">
<Place ContentPreview_Button="Sidebar:27" />
</Match>
</Placement>

View File

@@ -0,0 +1,37 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Orchard.ContentPreview")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("Orchard")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b17d5d22-4512-4102-a2e0-2546ca6a962c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.10.3")]
[assembly: AssemblyFileVersion("1.10.3")]

View File

@@ -0,0 +1,14 @@
# Content Preview (Orchard.ContentPreview)
Content preview allows you to display the result that will be rendered on the frontend in a separate window, while you are editing a content item in the admin.
A `Preview` button is available in the action buttons when you create or edit a content item.
## CREDITS
### JavaScript Cookie
<https://github.com/js-cookie/js-cookie>
Copyright 2006, 2015 Klaus Hartl & Fagner Brack
Released under the MIT license

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
<handlers accessPolicy="Script,Read">
<!-- For any request to a file exists on disk, return it via native http module. AccessPolicy="Script" above is to allow for a managed 404 page. -->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,75 @@
$(function () {
$(document)
.on('input change propertychange', 'form input', function () {
$(document).trigger('contentpreview:render');
})
.on('keyup', 'form input', function (event) {
// handle backspace
if (event.keyCode == 46 || event.ctrlKey) {
$(document).trigger('contentpreview:render');
}
});
$('.layout-data-field').change(function () {
$(document).trigger('contentpreview:render');
});
if (typeof (tinyMCE) !== "undefined") {
tinyMCE.activeEditor.on('change keyup', function (e) {
this.targetElm.value = this.getContent();
$(document).trigger('contentpreview:render');
});
}
});
var previewButton, contentItemType, previewId, previewContentItemId, previewContentItemVersionId, form, formData;
$(function () {
function serializeLayoutHandler() {
$.event.trigger({
type: "serializelayout"
});
};
$(document).on("layouteditor:edited", serializeLayoutHandler);
previewButton = document.getElementById('previewButton');
contentItemType = $(document.getElementById('contentItemType')).data('value');
previewId = $(document.getElementById('previewId')).data('value');
form = $(previewButton).closest('form');
sendFormData = function () {
formData = form.serializeArray(); // convert form to array
formData.push({ name: "ContentItemType", value: contentItemType });
formData.push({ name: "PreviewId", value: previewId });
var foundIndex = formData.findIndex(data => data.name === "AutoroutePart.CurrentUrl");
if (foundIndex > -1) {
formData[foundIndex].value += "-preview";
}
// store the form data to pass it in the event handler
localStorage.setItem('contentpreview:' + previewId, JSON.stringify($.param(formData)));
}
$(document).on('contentpreview:render', function () {
sendFormData();
});
$(window).on('storage', function (ev) {
if (ev.originalEvent.key != 'contentpreview:ready:' + previewId) return; // ignore other keys
// triggered by the preview window the first time it is loaded in order
// to pre-render the view even if no contentpreview:render is already sent
sendFormData();
});
$(window).on('unload', function () {
localStorage.removeItem('contentpreview:' + previewId);
// this will raise an event in the preview window to notify that the live preview is no longer active.
localStorage.setItem('contentpreview:not-connected:' + previewId, '');
localStorage.removeItem('contentpreview:not-connected:' + previewId);
});
});

View File

@@ -0,0 +1,165 @@
/*!
* JavaScript Cookie v2.1.4
* https://github.com/js-cookie/js-cookie
*
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
* Released under the MIT license
*/
;(function (factory) {
var registeredInModuleLoader = false;
if (typeof define === 'function' && define.amd) {
define(factory);
registeredInModuleLoader = true;
}
if (typeof exports === 'object') {
module.exports = factory();
registeredInModuleLoader = true;
}
if (!registeredInModuleLoader) {
var OldCookies = window.Cookies;
var api = window.Cookies = factory();
api.noConflict = function () {
window.Cookies = OldCookies;
return api;
};
}
}(function () {
function extend () {
var i = 0;
var result = {};
for (; i < arguments.length; i++) {
var attributes = arguments[ i ];
for (var key in attributes) {
result[key] = attributes[key];
}
}
return result;
}
function init (converter) {
function api (key, value, attributes) {
var result;
if (typeof document === 'undefined') {
return;
}
// Write
if (arguments.length > 1) {
attributes = extend({
path: '/'
}, api.defaults, attributes);
if (typeof attributes.expires === 'number') {
var expires = new Date();
expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
attributes.expires = expires;
}
// We're using "expires" because "max-age" is not supported by IE
attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
try {
result = JSON.stringify(value);
if (/^[\{\[]/.test(result)) {
value = result;
}
} catch (e) {}
if (!converter.write) {
value = encodeURIComponent(String(value))
.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
} else {
value = converter.write(value, key);
}
key = encodeURIComponent(String(key));
key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
key = key.replace(/[\(\)]/g, escape);
var stringifiedAttributes = '';
for (var attributeName in attributes) {
if (!attributes[attributeName]) {
continue;
}
stringifiedAttributes += '; ' + attributeName;
if (attributes[attributeName] === true) {
continue;
}
stringifiedAttributes += '=' + attributes[attributeName];
}
return (document.cookie = key + '=' + value + stringifiedAttributes);
}
// Read
if (!key) {
result = {};
}
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling "get()"
var cookies = document.cookie ? document.cookie.split('; ') : [];
var rdecode = /(%[0-9A-Z]{2})+/g;
var i = 0;
for (; i < cookies.length; i++) {
var parts = cookies[i].split('=');
var cookie = parts.slice(1).join('=');
if (cookie.charAt(0) === '"') {
cookie = cookie.slice(1, -1);
}
try {
var name = parts[0].replace(rdecode, decodeURIComponent);
cookie = converter.read ?
converter.read(cookie, name) : converter(cookie, name) ||
cookie.replace(rdecode, decodeURIComponent);
if (this.json) {
try {
cookie = JSON.parse(cookie);
} catch (e) {}
}
if (key === name) {
result = cookie;
break;
}
if (!key) {
result[name] = cookie;
}
} catch (e) {}
}
return result;
}
api.set = api;
api.get = function (key) {
return api.call(api, key);
};
api.getJSON = function () {
return api.apply({
json: true
}, [].slice.call(arguments));
};
api.defaults = {};
api.remove = function (key, attributes) {
api(key, '', extend(attributes, {
expires: -1
}));
};
api.withConverter = init;
return api;
}
return init(function () {});
}));

View File

@@ -0,0 +1,16 @@
@using Orchard.ContentManagement
@{
var contentItem = Model.ContentItem as ContentItem;
var previewId = Guid.NewGuid();
Script.Include("contentpreview.edit.js");
}
<fieldset>
<a id="previewButton" target="_blank" class="button" href="@Url.Action("Index", "Preview", new { area = "Orchard.ContentPreview", id = previewId })">@T("Preview")</a>
<div id="renderPreviewUrl" style="display:none" data-value="@Url.Action("Render", "Preview", new { area = "Orchard.ContentPreview" })"></div>
<div id="contentItemType" style="display:none" data-value="@contentItem.ContentType"></div>
<div id="previewId" style="display:none" data-value="@previewId"></div>
</fieldset>

View File

@@ -0,0 +1,135 @@
@using Orchard.UI.Resources
@{
var previewId = ViewContext.RouteData.Values["id"];
Script.Require("jQuery").AtHead();
Script.Include("js.cookie.js").AtHead();
}
<iframe id="iframe" style="display:none; position:fixed; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden;z-index:999990;">
@T("Your browser doesn't support iframes")
</iframe>
<iframe id="iframe2" style="display:none; position:fixed; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden;z-index:999990;">
@T("Your browser doesn't support iframes")
</iframe>
<div id="notConnectedWarning" class="message message-Error" role="alert" style="position:fixed; height:36px; top:10px;right:40px; display:none; z-index:999999;">
<button type="button" id="close-connect-warning" class="close" aria-label="Close" style="position: relative; padding: 0 7px; border-radius: 7px; font-size:21px;">
<span aria-hidden="true">&times;</span>
</button>
<span>@T("Preview Disconnected") </span>
</div>
<div id="renderPreviewUrl" style="display:none" data-value="@Url.Action("Render", "Preview", new { area = "Orchard.ContentPreview" })"></div>
<script type="text/javascript">
; (function ($) {
$(function () {
var renderPreviewUrl = $(document.getElementById('renderPreviewUrl')).data('value');
var iframe = document.getElementById('iframe');
var iframe2 = document.getElementById('iframe2');
var previewEventTimer = null;
var previewRenderTimer = null;
$(function () {
$(window).on('storage', function (ev) {
if (ev.key.indexOf('contentpreview:not-connected:') !== -1) {
$(notConnectedWarning).show();
}
else if (ev.key.indexOf('contentpreview:') !== -1) {
if (ev.originalEvent.newValue != null) {
// Smooth event cascading
clearTimeout(previewEventTimer);
previewEventTimer = setTimeout(function () { renderPreview(ev.originalEvent.newValue); }, 150);
$(notConnectedWarning).hide();
}
}
});
// override default behaviour of Bootstrap's. We only hide, not remove the alert.
$('#close-connect-warning').on('click', function(){
$('#notConnectedWarning').hide();
});
var preview = localStorage.getItem('contentpreview:@previewId');
if (preview == null) {
// notify the editor to render the preview
localStorage.setItem('contentpreview:ready:@previewId', '');
localStorage.removeItem('contentpreview:ready:@previewId');
}
else {
renderPreview(preview);
}
});
iframe.onload = function () {
if (previewRendering) {
this.style.display = 'block';
$(this.contentWindow).scrollTop(scrollTop);
if (iframe2 && iframe2.contentWindow) {
iframe2.style.display = 'none';
iframe2.contentWindow.document.open();
iframe2.contentWindow.document.write(previewRenderData);
iframe2.contentWindow.document.close();
}
previewRendering = false;
}
}
var previewRendering;
var previewRenderData;
var scrollTop = 0;
function renderPreview(value) {
if (previewRendering) {
// Defer the last rendering
clearTimeout(previewRenderTimer);
previewRenderTimer = setTimeout(function () { renderPreview(value); }, 100);
return;
}
previewRendering = true;
clearTimeout(previewRenderTimer);
try {
var formData = JSON.parse(value);
if (!formData) {
previewRendering = false;
return;
}
$.post(renderPreviewUrl, formData)
.done(function (data) {
if (iframe && iframe.contentWindow && iframe2 && iframe2.contentWindow) {
// A full writing of the frame document causes the iframe to be re-loaded.
// So, better to update the scroll position on the related 'onload' event.
// Then, we use 2 frames to cancel the flicker that this deferring causes.
scrollTop = $(iframe.contentWindow).scrollTop();
iframe2.style.display = 'block';
$(iframe2.contentWindow).scrollTop(scrollTop);
iframe.style.display = 'none';
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(data);
iframe.contentWindow.document.close();
previewRenderData = data;
}
})
.fail(function (data) {
previewRendering = false;
});
}
catch (e) {
previewRendering = false;
console.log('Error while previewing: ' + e);
}
}
});
})(jQuery);
</script>

View File

@@ -0,0 +1,3 @@
@Html.ValidationSummary()
@Display(Model)

View File

@@ -0,0 +1,67 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false"/>
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false"/>
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<pages pageBaseType="Orchard.Mvc.ViewEngines.Razor.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Web.WebPages"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web.webPages.razor>
<!-- Registering Roslyn as a compiler for Razor IntelliSense. -->
<appSettings>
<add key="aspnet:RoslynCompilerLocation" value="..\..\bin\roslyn" />
</appSettings>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:latest" />
</compilers>
</system.codedom>
<system.web>
<compilation targetFramework="4.5.2">
<assemblies>
<add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Mvc, Version=5.2.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="Orchard.Framework,Culture=neutral, PublicKeyToken=null"/>
<add assembly="Orchard.Core,Culture=neutral, PublicKeyToken=null"/>
</assemblies>
</compilation>
</system.web>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30AD4FE6B2A6AEED" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="NHibernate" publicKeyToken="AA95F207798DFDB4" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.4000" newVersion="4.0.0.4000"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Iesi.Collections" publicKeyToken="AA95F207798DFDB4" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Autofac" publicKeyToken="17863AF14B0044DA" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.5.0.0" newVersion="3.5.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net452" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net452" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" />
</packages>

View File

@@ -97,6 +97,9 @@
break;
case "paste":
focusedElement.paste(e.originalEvent.clipboardData);
$.event.trigger({
type: "layouteditor:edited"
});
break;
}
});

View File

@@ -149,11 +149,14 @@
$scope.delete = function (element) {
element.delete();
$.event.trigger({
type: "layouteditor:edited"
});
}
if ($scope.element.hasEditor) {
$scope.edit = function () {
$scope.$root.editElement($scope.element).then(function (args) {
$scope.$root.editElement($scope.element).done(function (args) {
$scope.$apply(function () {
if (args.cancel)
return;
@@ -255,7 +258,7 @@
receivedElement.setParent(element);
if (!!receivedElement.hasEditor) {
$scope.$root.editElement(receivedElement).then(function (args) {
$scope.$root.editElement(receivedElement).done(function (args) {
if (!args.cancel) {
receivedElement.data = args.element.data;
receivedElement.applyElementEditorModel(args.elementEditorModel);
@@ -281,6 +284,10 @@
element.setIsDropTarget(false);
if (!!receivedElement)
receivedElement.setIsFocused();
$scope.$root.addElement(receivedElement).done(function () {
return;
});
});
});
}

View File

@@ -92,6 +92,9 @@
return;
var index = _(this.children).indexOf(child);
this.children.move(index, index - 1);
$.event.trigger({
type: "layouteditor:edited"
});
};
this.moveChildDown = function (child) {
@@ -99,6 +102,9 @@
return;
var index = _(this.children).indexOf(child);
this.children.move(index, index + 1);
$.event.trigger({
type: "layouteditor:edited"
});
};
this.canMoveChildUp = function (child) {

View File

@@ -4,6 +4,13 @@
this.element = element;
this.element.data("layout-designer-host", this);
this.editor = layoutEditor;
function serializelayoutHandler() {
serializeLayout();
};
$(document).on("serializelayout", serializelayoutHandler);
this.settings = {
antiForgeryToken: self.element.data("anti-forgery-token"),
editorDialogTitleFormat: self.element.data("editor-dialog-title-format"),
@@ -20,6 +27,16 @@
}
};
this.addElement = function (contentType) {
var deferred = new $.Deferred();
deferred.resolve();
$.event.trigger({
type: "layouteditor:edited"
});
return deferred.promise();
};
this.editElement = function (element) {
var deferred = new $.Deferred();
@@ -39,10 +56,13 @@
dialog.element.on("command", function (e, args) {
switch(args.command) {
switch (args.command) {
case "update":
deferred.resolve(args);
dialog.close();
$.event.trigger({
type: "layouteditor:edited"
});
break;
case "cancel":
case "close":
@@ -98,7 +118,7 @@
var layoutDataDataJson = serializeCanvas();
var recycleBinDataJson = serializeRecycleBin();
layoutDataField.val(layoutDataDataJson);
layoutDataField.val(layoutDataDataJson).trigger("change");
recycleBinDataField.val(recycleBinDataJson);
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -94,6 +94,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Web", "Orchard.Web\
{6BD8B2FA-F2E3-4AC8-A4C3-2925A653889A} = {6BD8B2FA-F2E3-4AC8-A4C3-2925A653889A}
{14C049FD-B35B-415A-A824-87F26B26E7FD} = {14C049FD-B35B-415A-A824-87F26B26E7FD}
{085948FF-0E9B-4A9A-B564-F8B8B4BDDDBC} = {085948FF-0E9B-4A9A-B564-F8B8B4BDDDBC}
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD} = {A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}
{8EE141BE-7217-4F5B-8214-3146BEFA07E3} = {8EE141BE-7217-4F5B-8214-3146BEFA07E3}
EndProjectSection
EndProject
@@ -286,6 +287,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.OpenId", "Orchard.W
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Glimpse", "Orchard.Web\Modules\Orchard.Glimpse\Orchard.Glimpse.csproj", "{71E17466-D937-49D7-8C7D-77CCBAB8CCF4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.ContentPreview", "Orchard.Web\Modules\Orchard.ContentPreview\Orchard.ContentPreview.csproj", "{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.MediaLibrary.WebSearch", "Orchard.Web\Modules\Orchard.MediaLibrary.WebSearch\Orchard.MediaLibrary.WebSearch.csproj", "{8EE141BE-7217-4F5B-8214-3146BEFA07E3}"
EndProject
Global
@@ -1141,6 +1144,16 @@ Global
{71E17466-D937-49D7-8C7D-77CCBAB8CCF4}.FxCop|Any CPU.Build.0 = Release|Any CPU
{71E17466-D937-49D7-8C7D-77CCBAB8CCF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71E17466-D937-49D7-8C7D-77CCBAB8CCF4}.Release|Any CPU.Build.0 = Release|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.Coverage|Any CPU.Build.0 = Release|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.FxCop|Any CPU.Build.0 = Release|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD}.Release|Any CPU.Build.0 = Release|Any CPU
{8EE141BE-7217-4F5B-8214-3146BEFA07E3}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU
{8EE141BE-7217-4F5B-8214-3146BEFA07E3}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU
{8EE141BE-7217-4F5B-8214-3146BEFA07E3}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
@@ -1241,6 +1254,7 @@ Global
{1CC62F45-E6FF-43D5-84BF-509A1085D994} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
{42E217C1-E163-4B6B-9E8F-42BEE21B6896} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
{71E17466-D937-49D7-8C7D-77CCBAB8CCF4} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
{A17BE797-D4AF-4CB4-A9FD-AE7BA09A95BD} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
{8EE141BE-7217-4F5B-8214-3146BEFA07E3} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution