diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs index d018dddfbf..b99fc2695e 100644 --- a/src/Umbraco.Core/UriExtensions.cs +++ b/src/Umbraco.Core/UriExtensions.cs @@ -30,6 +30,7 @@ namespace Umbraco.Core /// These are def back office: /// /Umbraco/RestServices = back office /// /Umbraco/BackOffice = back office + /// /Umbraco/Preview = back office /// If it's not any of the above, and there's no extension then we cannot determine if it's back office or front-end /// so we can only assume that it is not back office. This will occur if people use an UmbracoApiController for the backoffice /// but do not inherit from UmbracoAuthorizedApiController and do not use [IsBackOffice] attribute. @@ -77,7 +78,8 @@ namespace Umbraco.Core //check for special back office paths if (urlPath.InvariantStartsWith("/" + globalSettings.GetUmbracoMvcArea() + "/BackOffice/") - || urlPath.InvariantStartsWith("/" + globalSettings.GetUmbracoMvcArea() + "/RestServices/")) + || urlPath.InvariantStartsWith("/" + globalSettings.GetUmbracoMvcArea() + "/RestServices/") + || urlPath.InvariantStartsWith("/" + globalSettings.GetUmbracoMvcArea() + "/Preview/")) { return true; } diff --git a/src/Umbraco.Web.UI.Client/src/canvasdesigner/canvasdesigner.controller.js b/src/Umbraco.Web.UI.Client/src/canvasdesigner/canvasdesigner.controller.js index 25c616814f..697599b97d 100644 --- a/src/Umbraco.Web.UI.Client/src/canvasdesigner/canvasdesigner.controller.js +++ b/src/Umbraco.Web.UI.Client/src/canvasdesigner/canvasdesigner.controller.js @@ -5,113 +5,146 @@ var app = angular.module("Umbraco.canvasdesigner", ['umbraco.resources', 'umbraco.services']) -.controller("Umbraco.canvasdesignerController", function ($scope, $http, $window, $timeout, $location, dialogService) { + .controller("Umbraco.canvasdesignerController", function ($scope, $http, $window, $timeout, $location, dialogService) { - var isInit = $location.search().init; - if (isInit === "true") { - //do not continue, this is the first load of this new window, if this is passed in it means it's been - //initialized by the content editor and then the content editor will actually re-load this window without - //this flag. This is a required trick to get around chrome popup mgr. We don't want to double load preview.aspx - //since that will double prepare the preview documents - return; - } + //gets a real query string value + function getParameterByName(name, url) { + if (!url) url = $window.location.href; + name = name.replace(/[\[\]]/g, '\\$&'); + var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), + results = regex.exec(url); + if (!results) return null; + if (!results[2]) return ''; + return decodeURIComponent(results[2].replace(/\+/g, ' ')); + } - $scope.isOpen = false; - $scope.frameLoaded = false; - var pageId = $location.search().id; - $scope.pageId = pageId; - $scope.pageUrl = "frame?id=" + pageId; - $scope.valueAreLoaded = false; - $scope.devices = [ - { name: "desktop", css: "desktop", icon: "icon-display", title: "Desktop" }, - { name: "laptop - 1366px", css: "laptop border", icon: "icon-laptop", title: "Laptop" }, - { name: "iPad portrait - 768px", css: "iPad-portrait border", icon: "icon-ipad", title: "Tablet portrait" }, - { name: "iPad landscape - 1024px", css: "iPad-landscape border", icon: "icon-ipad flip", title: "Tablet landscape" }, - { name: "smartphone portrait - 480px", css: "smartphone-portrait border", icon: "icon-iphone", title: "Smartphone portrait" }, - { name: "smartphone landscape - 320px", css: "smartphone-landscape border", icon: "icon-iphone flip", title: "Smartphone landscape" } - ]; - $scope.previewDevice = $scope.devices[0]; - - /*****************************************************************************/ - /* Preview devices */ - /*****************************************************************************/ - - // Set preview device - $scope.updatePreviewDevice = function (device) { - $scope.previewDevice = device; - }; - - /*****************************************************************************/ - /* Exit Preview */ - /*****************************************************************************/ - - $scope.exitPreview = function () { - window.top.location.href = "../endPreview.aspx?redir=%2f" + $scope.pageId; - }; - - - - /*****************************************************************************/ - /* Panel managment */ - /*****************************************************************************/ - - $scope.openPreviewDevice = function () { - $scope.showDevicesPreview = true; - $scope.closeIntelCanvasdesigner(); - } - - /*****************************************************************************/ - /* Call function into the front-end */ - /*****************************************************************************/ - - - var hideUmbracoPreviewBadge = function () { - var iframe = (document.getElementById("resultFrame").contentWindow || document.getElementById("resultFrame").contentDocument); - if(iframe.document.getElementById("umbracoPreviewBadge")) - iframe.document.getElementById("umbracoPreviewBadge").style.display = "none"; - }; - - /*****************************************************************************/ - /* Init */ - /*****************************************************************************/ - - - // signalr hub - var previewHub = $.connection.previewHub; - - previewHub.client.refreshed = function (message, sender) { - console.log("Notified by SignalR preview hub (" + message+ ")."); - - if ($scope.pageId != message) { - console.log("Not a notification for us (" + $scope.pageId + ")."); + var isInit = $location.search().init; + if (isInit === "true") { + //do not continue, this is the first load of this new window, if this is passed in it means it's been + //initialized by the content editor and then the content editor will actually re-load this window without + //this flag. This is a required trick to get around chrome popup mgr. return; } - var resultFrame = document.getElementById("resultFrame"); - var iframe = (resultFrame.contentWindow || resultFrame.contentDocument); - //setTimeout(function() { iframe.location.reload(); }, 1000); - iframe.location.reload(); - }; + var pageId = $location.search().id; - $.connection.hub.start() - .done(function () { console.log("Connected to SignalR preview hub (ID=" + $.connection.hub.id + ")"); }) - .fail(function () { console.log("Could not connect to SignalR preview hub."); }); -}) - - -.directive('iframeIsLoaded', function ($timeout) { - return { - restrict: 'A', - link: function (scope, element, attr) { - element.load(function () { - var iframe = (element.context.contentWindow || element.context.contentDocument); - if(iframe && iframe.document.getElementById("umbracoPreviewBadge")) - iframe.document.getElementById("umbracoPreviewBadge").style.display = "none"; - if (!document.getElementById("resultFrame").contentWindow.refreshLayout) { - scope.frameLoaded = true; - scope.$apply(); - } - }); + //there is no page id query string hash so check if its part of a 'real' query string + //and if so, reload with the query string hash + if (!pageId) { + var queryStringPageId = getParameterByName("id"); + if (queryStringPageId) { + $location.search("id", queryStringPageId); + $window.location.reload(); + return; + } } - }; -}) + + + $scope.isOpen = false; + $scope.frameLoaded = false; + + $scope.pageId = pageId; + $scope.pageUrl = "frame?id=" + pageId; + $scope.valueAreLoaded = false; + $scope.devices = [ + { name: "desktop", css: "desktop", icon: "icon-display", title: "Desktop" }, + { name: "laptop - 1366px", css: "laptop border", icon: "icon-laptop", title: "Laptop" }, + { name: "iPad portrait - 768px", css: "iPad-portrait border", icon: "icon-ipad", title: "Tablet portrait" }, + { name: "iPad landscape - 1024px", css: "iPad-landscape border", icon: "icon-ipad flip", title: "Tablet landscape" }, + { name: "smartphone portrait - 480px", css: "smartphone-portrait border", icon: "icon-iphone", title: "Smartphone portrait" }, + { name: "smartphone landscape - 320px", css: "smartphone-landscape border", icon: "icon-iphone flip", title: "Smartphone landscape" } + ]; + $scope.previewDevice = $scope.devices[0]; + + /*****************************************************************************/ + /* Preview devices */ + /*****************************************************************************/ + + // Set preview device + $scope.updatePreviewDevice = function (device) { + $scope.previewDevice = device; + }; + + /*****************************************************************************/ + /* Exit Preview */ + /*****************************************************************************/ + + $scope.exitPreview = function () { + window.top.location.href = "../endPreview.aspx?redir=%2f" + $scope.pageId; + }; + + $scope.onFrameLoaded = function () { + $scope.frameLoaded = true; + } + + /*****************************************************************************/ + /* Panel managment */ + /*****************************************************************************/ + + $scope.openPreviewDevice = function () { + $scope.showDevicesPreview = true; + $scope.closeIntelCanvasdesigner(); + } + + }) + + + .component('previewIFrame', { + + template: "
", + controller: function ($element) { + + var vm = this; + + vm.$onInit = function () { + + ////TODO: Move this to the callback on the controller + + //// signalr hub + //var previewHub = $.connection.previewHub; + + //previewHub.client.refreshed = function (message, sender) { + // console.log("Notified by SignalR preview hub (" + message + ")."); + + // if ($scope.pageId != message) { + // console.log("Not a notification for us (" + $scope.pageId + ")."); + // return; + // } + + // var iframe = ($element.context.contentWindow || $element.context.contentDocument); + // iframe.location.reload(); + //}; + + //$.connection.hub.start() + // .done(function () { console.log("Connected to SignalR preview hub (ID=" + $.connection.hub.id + ")"); }) + // .fail(function () { console.log("Could not connect to SignalR preview hub."); }); + }; + + vm.$postLink = function () { + $element.find("#resultFrame").on("load", function () { + var iframe = $element.find("#resultFrame").get(0); + hideUmbracoPreviewBadge(iframe); + vm.onLoaded(); + scope.$apply(); + }); + }; + + function hideUmbracoPreviewBadge (iframe) { + if (iframe && iframe.document.getElementById("umbracoPreviewBadge")) { + iframe.document.getElementById("umbracoPreviewBadge").style.display = "none"; + } + }; + + }, + controllerAs: "vm", + bindings: { + src: "@", + onLoaded: "&" + } + + }) + + .config(function ($locationProvider) { + $locationProvider.html5Mode(false); //turn html5 mode off + $locationProvider.hashPrefix(''); + }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index 2b41089722..afc3e45be7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -471,10 +471,10 @@ // Chromes popup blocker will kick in if a window is opened // without the initial scoped request. This trick will fix that. // - var previewWindow = $window.open('preview/?init=true&id=' + content.id, 'umbpreview'); + var previewWindow = $window.open('preview/#?init=true', 'umbpreview'); // Build the correct path so both /#/ and #/ work. - var redirect = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/?id=' + content.id; + var redirect = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/#?id=' + content.id; //The user cannot save if they don't have access to do that, in which case we just want to preview //and that's it otherwise they'll get an unauthorized access message diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml index 5316b448be..21b7d3cbb2 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml @@ -18,8 +18,8 @@ @Html.Partial(Model.PreviewExtendedHeaderView) } -
- +
+
diff --git a/src/Umbraco.Web/Editors/PreviewController.cs b/src/Umbraco.Web/Editors/PreviewController.cs index d2f955c1e8..f5e9074e7d 100644 --- a/src/Umbraco.Web/Editors/PreviewController.cs +++ b/src/Umbraco.Web/Editors/PreviewController.cs @@ -68,6 +68,7 @@ namespace Umbraco.Web.Editors return null; } + //fixme: not sure we need this anymore since there is no canvas editing - then we can remove that route too public ActionResult Editors(string editor) { if (string.IsNullOrEmpty(editor)) throw new ArgumentNullException(nameof(editor));