Add WebCms
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
// Umbraco SpeechBubble Javascript
|
||||
|
||||
// Dependency Loader Constructor
|
||||
function UmbracoSpeechBubble(id) {
|
||||
this.id = id;
|
||||
this.ie = document.all ? true : false;
|
||||
|
||||
this.GenerateSpeechBubble();
|
||||
}
|
||||
|
||||
UmbracoSpeechBubble.prototype.GenerateSpeechBubble = function() {
|
||||
|
||||
theBody = document.getElementsByTagName('BODY')[0];
|
||||
sbHtml = document.createElement('div');
|
||||
sbHtml.id = this.id + 'Container';
|
||||
sbHtml.innerHTML = '' +
|
||||
'<div id="' + this.id + '" style="z-index: 10; filter: Alpha(Opacity=0); background-image: url(/umbraco/images/speechbubble/speechbubble.gif); visibility: hidden; width: 231px; position: absolute; height: 84px">' +
|
||||
'<div id="' + this.id + 'Icon" style="left: 10px; position: absolute; top: 16px">' +
|
||||
'<img src="/umbraco/images/speechBubble/info.gif" alt="Info" width="30" height="30" id="' + this.id + 'IconSrc"></div>' +
|
||||
' <div id="speechClose" style="left: 208px; position: absolute; top: 6px">' +
|
||||
' <a href="javascript:UmbSpeechBubble.Hide(100)">' +
|
||||
' <img src="/umbraco/images/speechbubble/speechBubble_close.gif" width="18" height="18" border="0" alt="Close"' +
|
||||
' onmouseover="this.src = \'/umbraco/images/speechbubble/speechBubble_close_over.gif\';" onmouseout="this.src=\'images/speechbubble/speechBubble_close.gif\';"></a></div>' +
|
||||
' <div id="' + this.id + 'Header" style="font-family: Segoe UI; lucida sans; sans serif; font-size: 16px; font-weight: 100; color: #0033aa; left: 50px;' +
|
||||
' position: absolute; top: 6px">' +
|
||||
' Data gemt!</div>' +
|
||||
' <div id="' + this.id + 'Message" style="font-size: 11px; font-weight: normal; color: #000; text-align: left; left: 50px; width: 180px; position: absolute;' +
|
||||
' top: 28px">' +
|
||||
' Default Text Container!</div>' +
|
||||
' </div>';
|
||||
theBody.appendChild(sbHtml);
|
||||
}
|
||||
|
||||
UmbracoSpeechBubble.prototype.ShowMessage = function(icon, header, message) {
|
||||
var speechBubble = document.getElementById(this.id);
|
||||
|
||||
document.getElementById(this.id + "Header").innerHTML = header;
|
||||
document.getElementById(this.id + "Message").innerHTML = message;
|
||||
document.getElementById(this.id + "IconSrc").src = '/umbraco/images/speechBubble/' + icon + '.png';
|
||||
|
||||
speechBubble.style.right = "20px";
|
||||
speechBubble.style.bottom = "20px";
|
||||
speechBubble.style.visibility = 'visible';
|
||||
this.Show(0);
|
||||
}
|
||||
|
||||
UmbracoSpeechBubble.prototype.Show = function(opacity) {
|
||||
document.getElementById(this.id).style.filter = 'Alpha(Opacity=' + opacity + ')';
|
||||
|
||||
opacity = parseInt(opacity) + 10;
|
||||
|
||||
var _self = this;
|
||||
if (opacity < 101) {
|
||||
setTimeout(function() {_self.Show(opacity+10);}, 50);
|
||||
} else {
|
||||
setTimeout(function() {_self.Hide(100);}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
UmbracoSpeechBubble.prototype.Hide = function(opacity) {
|
||||
document.getElementById(this.id).style.filter = 'Alpha(Opacity=' + opacity + ')';
|
||||
|
||||
var _self = this;
|
||||
opacity = parseInt(opacity) - 10;
|
||||
if (opacity > 1)
|
||||
setTimeout(function() {_self.Hide(opacity-10);}, 50);
|
||||
else {
|
||||
document.getElementById(this.id).style.visibility = 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize
|
||||
var UmbSpeechBubble = null
|
||||
function InitUmbracoSpeechBubble() {
|
||||
if (UmbSpeechBubble == null)
|
||||
UmbSpeechBubble = new UmbracoSpeechBubble("defaultSpeechbubble");
|
||||
}
|
||||
|
||||
//if (typeof(addEvent) !== 'undefined') {
|
||||
// addEvent(window, "load", InitUmbracoSpeechBubble);
|
||||
//}else if (Sys != undefined) {
|
||||
// Sys.Application.add_load(InitUmbracoSpeechBubble);
|
||||
//}
|
||||
@@ -0,0 +1,68 @@
|
||||
// Umbraco SpeechBubble Javascript
|
||||
|
||||
// Dependency Loader Constructor
|
||||
function UmbracoSpeechBubble(id) {
|
||||
this.id = id;
|
||||
this.ie = document.all ? true : false;
|
||||
|
||||
this.GenerateSpeechBubble();
|
||||
}
|
||||
|
||||
UmbracoSpeechBubble.prototype.GenerateSpeechBubble = function() {
|
||||
|
||||
var sbHtml = document.getElementById(this.id);
|
||||
|
||||
sbHtml.innerHTML = '' +
|
||||
'<div class="speechBubbleTop"></div>' +
|
||||
'<div class="speechBubbleContent">' +
|
||||
'<img id="' + this.id + 'Icon" style="float: left; margin: 0px 5px 10px 3px;" />' +
|
||||
' <img class="speechClose" onClick="UmbSpeechBubble.Hide();" id="' + this.id + 'close" src="/umbraco/images/speechBubble/speechBubble_close.gif" width="18" height="18" border="0" alt="Close"' +
|
||||
' onmouseover="this.src = \'/umbraco/images/speechBubble/speechBubble_close_over.gif\';" onmouseout="this.src=\'images/speechBubble/speechBubble_close.gif\';">' +
|
||||
' <div style="float: right; width: 186px; margin-right: 10px;"><h3 id="' + this.id + 'Header">The header!</h3>' +
|
||||
' <p style="width: 185px" id="' + this.id + 'Message">Default Text Container!<br /></p></div><br style="clear: both" />' +
|
||||
'</div>' +
|
||||
'<div class="speechBubbleBottom"></div>'
|
||||
}
|
||||
|
||||
UmbracoSpeechBubble.prototype.ShowMessage = function (icon, header, message, dontAutoHide) {
|
||||
var speechBubble = jQuery("#" + this.id);
|
||||
jQuery("#" + this.id + "Header").html(header);
|
||||
jQuery("#" + this.id + "Message").html(message);
|
||||
jQuery("#" + this.id + "Icon").attr('src', 'images/speechBubble/' + icon + '.png');
|
||||
|
||||
if (!this.ie) {
|
||||
if (!dontAutoHide) {
|
||||
jQuery("#" + this.id).fadeIn("slow").animate({ opacity: 1.0 }, 5000).fadeOut("fast");
|
||||
} else {
|
||||
jQuery(".speechClose").show();
|
||||
jQuery("#" + this.id).fadeIn("slow");
|
||||
}
|
||||
} else {
|
||||
// this is special for IE as it handles fades with pngs very ugly
|
||||
jQuery("#" + this.id).show();
|
||||
if (!dontAutoHide) {
|
||||
setTimeout('UmbSpeechBubble.Hide();', 5000);
|
||||
} else {
|
||||
jQuery(".speechClose").show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UmbracoSpeechBubble.prototype.Hide = function () {
|
||||
if (!this.ie) {
|
||||
jQuery("#" + this.id).fadeOut("slow");
|
||||
} else {
|
||||
jQuery("#" + this.id).hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize
|
||||
var UmbSpeechBubble = null
|
||||
function InitUmbracoSpeechBubble() {
|
||||
if (UmbSpeechBubble == null)
|
||||
UmbSpeechBubble = new UmbracoSpeechBubble("defaultSpeechbubble");
|
||||
}
|
||||
|
||||
jQuery(document).ready(function() {
|
||||
InitUmbracoSpeechBubble();
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
//used by live editing to ensure the speech bubble is initialized after the main js file has been lazy loaded.
|
||||
//alert("Speech Bubble init: " + InitUmbracoSpeechBubble);
|
||||
InitUmbracoSpeechBubble();
|
||||
@@ -0,0 +1,61 @@
|
||||
var app = angular.module('umbraco', [
|
||||
'umbraco.filters',
|
||||
'umbraco.directives',
|
||||
'umbraco.resources',
|
||||
'umbraco.services',
|
||||
'umbraco.packages',
|
||||
'umbraco.views',
|
||||
|
||||
'ngCookies',
|
||||
'ngSanitize',
|
||||
'ngMobile',
|
||||
'tmh.dynamicLocale',
|
||||
'ngFileUpload',
|
||||
'LocalStorageModule'
|
||||
]);
|
||||
|
||||
var packages = angular.module("umbraco.packages", []);
|
||||
|
||||
//this ensures we can inject our own views into templateCache and clear
|
||||
//the entire cache before the app runs, due to the module
|
||||
//order, clearing will always happen before umbraco.views and umbraco
|
||||
//module is initilized.
|
||||
angular.module("umbraco.views", ["umbraco.viewcache"]);
|
||||
angular.module("umbraco.viewcache", [])
|
||||
.run(function($rootScope, $templateCache) {
|
||||
/** For debug mode, always clear template cache to cut down on
|
||||
dev frustration and chrome cache on templates */
|
||||
if (Umbraco.Sys.ServerVariables.isDebuggingEnabled) {
|
||||
$templateCache.removeAll();
|
||||
}
|
||||
})
|
||||
.config([
|
||||
//This ensures that all of our angular views are cache busted, if the path starts with views/ and ends with .html, then
|
||||
// we will append the cache busting value to it. This way all upgraded sites will not have to worry about browser cache.
|
||||
"$provide", function($provide) {
|
||||
return $provide.decorator("$http", [
|
||||
"$delegate", function($delegate) {
|
||||
var get = $delegate.get;
|
||||
$delegate.get = function (url, config) {
|
||||
|
||||
if (Umbraco.Sys.ServerVariables.application && url.startsWith("views/") && url.endsWith(".html")) {
|
||||
var rnd = Umbraco.Sys.ServerVariables.application.version + "." + Umbraco.Sys.ServerVariables.application.cdf;
|
||||
var _op = (url.indexOf("?") > 0) ? "&" : "?";
|
||||
url += _op + "umb__rnd=" + rnd;
|
||||
}
|
||||
|
||||
return get(url, config);
|
||||
};
|
||||
return $delegate;
|
||||
}
|
||||
]);
|
||||
}
|
||||
]);
|
||||
|
||||
//Call a document callback if defined, this is sort of a dodgy hack to
|
||||
// be able to configure angular values in the Default.cshtml
|
||||
// view which is much easier to do that configuring values by injecting them in the back office controller
|
||||
// to follow through to the js initialization stuff
|
||||
if (angular.isFunction(document.angularReady)) {
|
||||
document.angularReady.apply(this, [app]);
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
|
||||
/*********************************************************************************************************/
|
||||
/* Canvasdesigner setting panel config */
|
||||
/*********************************************************************************************************/
|
||||
|
||||
var canvasdesignerConfig = {
|
||||
configs: [{
|
||||
name: "Body",
|
||||
schema: "body",
|
||||
selector: "body",
|
||||
editors: [
|
||||
{
|
||||
type: "background",
|
||||
category: "Color",
|
||||
name: "Background",
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Font",
|
||||
name: "Font Color (main)",
|
||||
css: "color",
|
||||
schema: "body, h1, h2, h3, h4, h5, h6, h7, #nav li a"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Font",
|
||||
name: "Font Color (secondary)",
|
||||
css: "color",
|
||||
schema: "ul.meta, .byline"
|
||||
},
|
||||
{
|
||||
type: "googlefontpicker",
|
||||
category: "Font",
|
||||
name: "Font Family",
|
||||
css: "color",
|
||||
schema: "body, h1, h2, h3, h4, h5, h6, h7, .byline, #nav, .button"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Nav",
|
||||
schema: "#nav",
|
||||
selector: "nav",
|
||||
editors: [
|
||||
{
|
||||
type: "background",
|
||||
category: "Color",
|
||||
name: "Background",
|
||||
},
|
||||
{
|
||||
type: "border",
|
||||
category: "Color",
|
||||
name: "Border",
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Nav",
|
||||
name: "Font Color",
|
||||
css: "color",
|
||||
schema: "#nav li a"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Nav",
|
||||
name: "Font Color (hover / selected)",
|
||||
css: "color",
|
||||
schema: "#nav li:hover a"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Nav",
|
||||
name: "Background Color (hover)",
|
||||
css: "background-color",
|
||||
schema: "#nav li:hover a"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Nav",
|
||||
name: "Background Color (selected)",
|
||||
css: "background-color",
|
||||
schema: "#nav li.current_page_item a"
|
||||
},
|
||||
{
|
||||
type: "googlefontpicker",
|
||||
category: "Font",
|
||||
name: "Font familly",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Logo",
|
||||
schema: "#header .logo div",
|
||||
selector: "#header .logo div",
|
||||
editors: [
|
||||
{
|
||||
type: "color",
|
||||
category: "Color",
|
||||
name: "Border color",
|
||||
css: "border-top-color",
|
||||
schema: "#header .logo"
|
||||
},
|
||||
{
|
||||
type: "padding",
|
||||
category: "Position",
|
||||
name: "Margin",
|
||||
enable: ["top", "bottom"],
|
||||
schema: "#header"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "h2",
|
||||
schema: "h2",
|
||||
selector: "h2 span",
|
||||
editors: [
|
||||
{
|
||||
type: "color",
|
||||
category: "Color",
|
||||
name: "Border color",
|
||||
css: "border-top-color",
|
||||
schema: "h2.major"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Font",
|
||||
name: "Font color",
|
||||
css: "color",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "h3",
|
||||
schema: "h3",
|
||||
selector: "h3",
|
||||
editors: [
|
||||
{
|
||||
type: "color",
|
||||
category: "Font",
|
||||
name: "Font color",
|
||||
css: "color",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Banner Title",
|
||||
schema: "#banner h2",
|
||||
selector: "#banner h2",
|
||||
editors: [
|
||||
{
|
||||
type: "color",
|
||||
category: "Font",
|
||||
name: "Font color",
|
||||
css: "color",
|
||||
},
|
||||
{
|
||||
type: "slider",
|
||||
category: "Font",
|
||||
name: "Font size",
|
||||
css: "font-size",
|
||||
min: 18,
|
||||
max: 100
|
||||
},
|
||||
{
|
||||
type: "margin",
|
||||
category: "Position",
|
||||
name: "Margin",
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Banner Sub-title",
|
||||
schema: "#banner .byline",
|
||||
selector: "#banner .byline",
|
||||
editors: [
|
||||
{
|
||||
type: "color",
|
||||
category: "Font",
|
||||
name: "Font color",
|
||||
css: "color",
|
||||
},
|
||||
{
|
||||
type: "slider",
|
||||
category: "Font",
|
||||
name: "Font size",
|
||||
css: "font-size",
|
||||
min: 18,
|
||||
max: 100
|
||||
},
|
||||
{
|
||||
type: "margin",
|
||||
category: "Position",
|
||||
name: "Margin",
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Banner",
|
||||
schema: "#banner",
|
||||
selector: "#banner",
|
||||
editors: [
|
||||
{
|
||||
type: "background",
|
||||
category: "Color",
|
||||
name: "Background",
|
||||
css: "color"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Banner-wrapper",
|
||||
schema: "#banner-wrapper",
|
||||
selector: "#banner-wrapper",
|
||||
editors: [
|
||||
{
|
||||
type: "background",
|
||||
category: "Color",
|
||||
name: "Background",
|
||||
},
|
||||
{
|
||||
type: "padding",
|
||||
category: "Position",
|
||||
name: "Padding",
|
||||
enable: ["top", "bottom"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "#main-wrapper",
|
||||
schema: "#main-wrapper",
|
||||
selector: "#main-wrapper",
|
||||
editors: [
|
||||
{
|
||||
type: "border",
|
||||
category: "Styling",
|
||||
name: "Border",
|
||||
enable: ["top", "bottom"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Image",
|
||||
schema: ".image,.image img,.image:before",
|
||||
selector: ".image",
|
||||
editors: [
|
||||
{
|
||||
type: "radius",
|
||||
category: "Styling",
|
||||
name: "Radius"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Button",
|
||||
schema: ".button",
|
||||
selector: ".button",
|
||||
editors: [
|
||||
{
|
||||
type: "color",
|
||||
category: "Color",
|
||||
name: "Color",
|
||||
css: "color"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Color",
|
||||
name: "Background",
|
||||
css: "background"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Color",
|
||||
name: "Background Hover",
|
||||
css: "background",
|
||||
schema: ".button:hover"
|
||||
},
|
||||
{
|
||||
type: "radius",
|
||||
category: "Styling",
|
||||
name: "Radius"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Button Alt",
|
||||
schema: ".button-alt",
|
||||
selector: ".button-alt",
|
||||
editors: [
|
||||
{
|
||||
type: "color",
|
||||
category: "Color",
|
||||
name: "Color",
|
||||
css: "color"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Color",
|
||||
name: "Background",
|
||||
css: "background"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
category: "Color",
|
||||
name: "Background Hover",
|
||||
css: "background",
|
||||
schema: ".button-alt:hover"
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
/*********************************************************************************************************/
|
||||
/* Global function and variable for panel/page com */
|
||||
/*********************************************************************************************************/
|
||||
|
||||
var currentTarget = undefined;
|
||||
|
||||
var refreshLayout = function (parameters) {
|
||||
|
||||
// hide preview badget
|
||||
$("#umbracoPreviewBadge").hide();
|
||||
|
||||
var string = "less.modifyVars({" + parameters.join(",") + "})";
|
||||
eval(string);
|
||||
}
|
||||
|
||||
/* Fonts loaded in the Canvasdesigner panel need to be loaded independently in
|
||||
* the content iframe to allow live previewing.
|
||||
*/
|
||||
var webFontScriptLoaded = false;
|
||||
var getFont = function (font) {
|
||||
if (!webFontScriptLoaded) {
|
||||
$.getScript('https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js')
|
||||
.done(function () {
|
||||
webFontScriptLoaded = true;
|
||||
// Recursively call once webfont script is available.
|
||||
getFont(font);
|
||||
})
|
||||
.fail(function () {
|
||||
console.log('error loading webfont');
|
||||
});
|
||||
}
|
||||
else {
|
||||
WebFont.load({
|
||||
google: {
|
||||
families: [font]
|
||||
},
|
||||
loading: function () {
|
||||
//console.log('loading font' + font + ' in iframe');
|
||||
},
|
||||
active: function () {
|
||||
//console.log('loaded font ' + font + ' in iframe');
|
||||
},
|
||||
inactive: function () {
|
||||
//console.log('error loading font ' + font + ' in iframe');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var closeIntelCanvasdesigner = function (canvasdesignerModel) {
|
||||
|
||||
if (canvasdesignerModel) {
|
||||
|
||||
$.each(canvasdesignerModel.configs, function (indexConfig, config) {
|
||||
if (config.schema) {
|
||||
$(config.schema).unbind();
|
||||
$(config.schema).removeAttr("canvasdesigner-over");
|
||||
}
|
||||
});
|
||||
|
||||
initBodyClickEvent();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var initBodyClickEvent = function () {
|
||||
$("body").on("click", function () {
|
||||
if (parent.iframeBodyClick) {
|
||||
parent.iframeBodyClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var initIntelCanvasdesigner = function (canvasdesignerModel) {
|
||||
|
||||
if (canvasdesignerModel) {
|
||||
|
||||
// Add canvasdesigner-over attr for each schema from config
|
||||
$.each(canvasdesignerModel.configs, function (indexConfig, config) {
|
||||
var schema = config.selector ? config.selector : config.schema;
|
||||
if (schema) {
|
||||
$(schema).attr("canvasdesigner-over", config.schema);
|
||||
$(schema).attr("canvasdesigner-over-name", config.name);
|
||||
$(schema).css("cursor", "default");
|
||||
}
|
||||
});
|
||||
|
||||
// Outline canvasdesigner-over
|
||||
$(document).mousemove(function (e) {
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
var target = $(e.target);
|
||||
while (target.length > 0 && (target.attr('canvasdesigner-over') == undefined || target.attr('canvasdesigner-over') == '')) {
|
||||
target = target.parent();
|
||||
}
|
||||
|
||||
if (target.attr('canvasdesigner-over') != undefined && target.attr('canvasdesigner-over') != '') {
|
||||
target.unbind();
|
||||
outlinePosition(target);
|
||||
|
||||
parent.onMouseoverCanvasdesignerItem(target.attr('canvasdesigner-over-name'), target);
|
||||
|
||||
target.click(function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
//console.info(target.attr('canvasdesigner-over'));
|
||||
|
||||
currentTarget = target;
|
||||
outlineSelected();
|
||||
|
||||
parent.onClickCanvasdesignerItem(target.attr('canvasdesigner-over'), target);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
else {
|
||||
outlinePositionHide();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var refreshOutlinePosition = function(schema) {
|
||||
outlinePosition($(schema));
|
||||
}
|
||||
|
||||
var outlinePosition = function (oTarget) {
|
||||
|
||||
var target = oTarget;
|
||||
|
||||
if (target.length > 0 && target.attr('canvasdesigner-over') != undefined && target.attr('canvasdesigner-over') != '') {
|
||||
|
||||
var localname = target[0].localName;
|
||||
var height = $(target).outerHeight();
|
||||
var width = $(target).outerWidth();
|
||||
var position = $(target).offset();
|
||||
var posY = position.top ;
|
||||
//$(window).scrollTop();
|
||||
var posX = position.left;
|
||||
//+ $(window).scrollLeft();
|
||||
|
||||
$(".canvasdesigner-overlay").css('display', 'block');
|
||||
$(".canvasdesigner-overlay").css('left', posX);
|
||||
$(".canvasdesigner-overlay").css('top', posY);
|
||||
$(".canvasdesigner-overlay").css('width', width + "px");
|
||||
$(".canvasdesigner-overlay").css('height', height + "px");
|
||||
|
||||
//console.info("element select " + localname);
|
||||
$(".canvasdesigner-overlay span").html(target.attr('canvasdesigner-over-name'));
|
||||
|
||||
}
|
||||
else {
|
||||
outlinePositionHide();
|
||||
//console.info("element not found select");
|
||||
}
|
||||
}
|
||||
|
||||
var refreshOutlineSelected = function (schema) {
|
||||
outlineSelected($(schema));
|
||||
}
|
||||
|
||||
var outlineSelected = function (oTarget) {
|
||||
|
||||
var target = currentTarget;
|
||||
|
||||
if (oTarget) {
|
||||
currentTarget = oTarget;
|
||||
target = oTarget;
|
||||
}
|
||||
|
||||
if (target && target.length > 0 && target.attr('canvasdesigner-over') != undefined && target.attr('canvasdesigner-over') != '') {
|
||||
|
||||
var localname = target[0].localName;
|
||||
var height = $(target).outerHeight();
|
||||
var width = $(target).outerWidth();
|
||||
var position = $(target).offset();
|
||||
var posY = position.top;
|
||||
//$(window).scrollTop();
|
||||
var posX = position.left;
|
||||
//+ $(window).scrollLeft();
|
||||
|
||||
$(".canvasdesigner-overlay-selected").css('display', 'block');
|
||||
$(".canvasdesigner-overlay-selected").css('left', posX);
|
||||
$(".canvasdesigner-overlay-selected").css('top', posY);
|
||||
$(".canvasdesigner-overlay-selected").css('width', width + "px");
|
||||
$(".canvasdesigner-overlay-selected").css('height', height + "px");
|
||||
|
||||
//console.info("element select " + localname);
|
||||
$(".canvasdesigner-overlay-selected span").html(target.attr('canvasdesigner-over-name'));
|
||||
|
||||
}
|
||||
else {
|
||||
outlinePositionHide();
|
||||
//console.info("element not found select");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var outlinePositionHide = function () {
|
||||
$(".canvasdesigner-overlay").css('display', "none");
|
||||
}
|
||||
|
||||
var outlineSelectedHide = function () {
|
||||
currentTarget = undefined;
|
||||
$(".canvasdesigner-overlay-selected").css('display', "none");
|
||||
}
|
||||
|
||||
var initCanvasdesignerPanel = function () {
|
||||
|
||||
$('link[data-title="canvasdesignerCss"]').attr('disabled', 'disabled');
|
||||
|
||||
// First load the canvasdesigner config from file
|
||||
if (!canvasdesignerConfig) {
|
||||
console.info("canvasdesigner config not found");
|
||||
}
|
||||
|
||||
// Add canvasdesigner from HTML 5 data tags
|
||||
$("[data-canvasdesigner]").each(function (index, value) {
|
||||
var tagName = $(value).data("canvasdesigner") ? $(value).data("canvasdesigner") : $(value)[0].nodeName.toLowerCase();
|
||||
var tagSchema = $(value).data("schema") ? $(value).data("schema") : $(value)[0].nodeName.toLowerCase();
|
||||
var tagSelector = $(value).data("selector") ? $(value).data("selector") : tagSchema;
|
||||
var tagEditors = $(value).data("editors"); //JSON.parse(...);
|
||||
canvasdesignerConfig.configs.splice(canvasdesignerConfig.configs.length, 0, {
|
||||
name: tagName,
|
||||
schema: tagSchema,
|
||||
selector: tagSelector,
|
||||
editors: tagEditors
|
||||
});
|
||||
});
|
||||
|
||||
// For each editor config create a composite alias
|
||||
$.each(canvasdesignerConfig.configs, function (configIndex, config) {
|
||||
if (config.editors) {
|
||||
$.each(config.editors, function (editorIndex, editor) {
|
||||
var clearSchema = config.schema.replace(/[^a-zA-Z0-9]+/g, '').toLowerCase();
|
||||
var clearEditor = JSON.stringify(editor).replace(/[^a-zA-Z0-9]+/g, '').toLowerCase();
|
||||
editor.alias = clearSchema + clearEditor;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Create or update the less file
|
||||
$.ajax({
|
||||
url: "/Umbraco/Api/CanvasDesigner/Init",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
error: function (err) {
|
||||
alert(err.responseText)
|
||||
},
|
||||
data: {
|
||||
config: JSON.stringify(canvasdesignerConfig),
|
||||
pageId: pageId
|
||||
},
|
||||
success: function (data) {
|
||||
|
||||
// Add Less link in head
|
||||
$("head").append("<link>");
|
||||
css = $("head").children(":last");
|
||||
css.attr({
|
||||
rel: "stylesheet/less",
|
||||
type: "text/css",
|
||||
href: data
|
||||
});
|
||||
//console.info("Less styles are loaded");
|
||||
|
||||
// Init Less.js
|
||||
$.getScript("/Umbraco/lib/Less/less-1.7.0.min.js", function (data, textStatus, jqxhr) {
|
||||
|
||||
// Init panel
|
||||
if (parent.setFrameIsLoaded) {
|
||||
parent.setFrameIsLoaded(canvasdesignerConfig, canvasdesignerPalette);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$(function () {
|
||||
|
||||
if (parent.setFrameIsLoaded) {
|
||||
|
||||
// Overlay background-color: rgba(28, 203, 255, 0.05);
|
||||
$("body").append("<div class=\"canvasdesigner-overlay\" style=\"display:none; pointer-events: none; position: absolute; z-index: 9999; border: 1px solid #2ebdff; border-radius: 3px; \"><span style=\"position:absolute;background: #2ebdff; font-family: Helvetica, Arial, sans-serif; color: #fff; padding: 0 5px 0 6px; font-size: 10px; line-height: 17px; display: inline-block; border-radius: 0 0 3px 0;\"></span></div>");
|
||||
$("body").append("<div class=\"canvasdesigner-overlay-selected\" style=\"display:none; pointer-events: none; position: absolute; z-index: 9998; border: 2px solid #2ebdff; border-radius: 3px;\"><span style=\"position:absolute;background: #2ebdff; font-family: Helvetica, Arial, sans-serif; color: #fff; padding: 0 5px; font-size: 10px; line-height: 16px; display: inline-block; border-radius: 0 0 3px 0;\"></span></div>");
|
||||
|
||||
// Set event for any body click
|
||||
initBodyClickEvent()
|
||||
|
||||
// Init canvasdesigner panel
|
||||
initCanvasdesignerPanel();
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
LazyLoad.js([
|
||||
'../lib/jquery/jquery.min.js',
|
||||
'../lib/jquery-ui/jquery-ui.min.js',
|
||||
'../lib/angular/1.1.5/angular.min.js',
|
||||
'../lib/underscore/underscore-min.js',
|
||||
'../lib/umbraco/Extensions.js',
|
||||
'../js/app.js',
|
||||
'../js/umbraco.resources.js',
|
||||
'../js/umbraco.services.js',
|
||||
'../js/umbraco.security.js',
|
||||
'../ServerVariables',
|
||||
'../lib/spectrum/spectrum.js',
|
||||
|
||||
'../js/canvasdesigner.panel.js',
|
||||
], function () {
|
||||
jQuery(document).ready(function () {
|
||||
angular.bootstrap(document, ['Umbraco.canvasdesigner']);
|
||||
});
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
|
||||
function dualSelectBoxShift(id) {
|
||||
var posVal = document.getElementById(id + "_posVals");
|
||||
var selVal = document.getElementById(id + "_selVals");
|
||||
|
||||
// First check the possible items
|
||||
for (var i=0;i<posVal.options.length;i++) {
|
||||
if (posVal.options[i].selected) {
|
||||
var selNew = document.createElement('option');
|
||||
selNew.text = posVal[i].text;
|
||||
selNew.value = posVal[i].value;
|
||||
try {
|
||||
selVal.add(selNew, null);
|
||||
}
|
||||
catch(ex) {
|
||||
selVal.add(selNew);
|
||||
}
|
||||
posVal.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// do the same with the selected items, to return them
|
||||
for (var i=0;i<selVal.options.length;i++) {
|
||||
if (selVal.options[i].selected) {
|
||||
var selNew = document.createElement('option');
|
||||
selNew.text = selVal[i].text;
|
||||
selNew.value = selVal[i].value;
|
||||
try {
|
||||
posVal.add(selNew, null);
|
||||
}
|
||||
catch(ex) {
|
||||
posVal.add(selNew);
|
||||
}
|
||||
selVal.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// update hidden value field with all values
|
||||
var hiddenVal = "";
|
||||
for (var i=0;i<selVal.options.length;i++) {
|
||||
hiddenVal += selVal.options[i].value + ",";
|
||||
}
|
||||
if (hiddenVal != "")
|
||||
hiddenVal = hiddenVal.substring(0, hiddenVal.length-1);
|
||||
document.getElementById(id + "_theValue").value = hiddenVal;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// ---------------------------------------------
|
||||
// guiFunctions
|
||||
// ---------------------------------------------
|
||||
function toggleTree(sender) {
|
||||
var tree = jQuery("#leftDIV");
|
||||
var frame = jQuery("#rightDIV");
|
||||
|
||||
var disp = tree.css("display")
|
||||
var link = jQuery(sender);
|
||||
|
||||
|
||||
if (disp == "none") {
|
||||
tree.show();
|
||||
link.removeClass();
|
||||
resizePage();
|
||||
}
|
||||
else {
|
||||
tree.hide();
|
||||
link.addClass("on");
|
||||
var clientWidth = jQuery(window).width();
|
||||
frame.width(clientWidth - 20);
|
||||
}
|
||||
}
|
||||
|
||||
function resizePage(sender) {
|
||||
var dashboard = jQuery("#rightDIV");
|
||||
var dashboardFrame = jQuery("#right");
|
||||
var tree = jQuery("#leftDIV");
|
||||
var treeToggle = jQuery("#treeToggle");
|
||||
var appIcons = jQuery("#PlaceHolderAppIcons");
|
||||
var uiArea = jQuery("#uiArea");
|
||||
|
||||
if (jQuery(window)) {
|
||||
var clientHeight = jQuery(window).height() - 48;
|
||||
var clientWidth = jQuery(window).width();
|
||||
var leftWidth = parseInt(clientWidth * 0.25);
|
||||
var rightWidth = parseInt(clientWidth - leftWidth - 30);
|
||||
|
||||
// check if appdock is present
|
||||
var treeHeight = parseInt(clientHeight - 5);
|
||||
|
||||
// resize leftdiv
|
||||
tree.width(leftWidth);
|
||||
|
||||
if (appIcons != null) {
|
||||
treeHeight = treeHeight - 135;
|
||||
resizeGuiWindow("PlaceHolderAppIcons", leftWidth, 140);
|
||||
}
|
||||
|
||||
resizeGuiWindow("treeWindow", leftWidth, treeHeight)
|
||||
|
||||
if (tree.css("display") == "none") {
|
||||
dashboard.width(clientWidth - 24);
|
||||
} else {
|
||||
dashboard.width(rightWidth);
|
||||
}
|
||||
if (clientHeight > 0) {
|
||||
dashboard.height(clientHeight);
|
||||
treeToggle.height(clientHeight);
|
||||
}
|
||||
|
||||
treeToggle.show();
|
||||
uiArea.show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function resizeGuiWindow(windowName, newWidth, newHeight, window) {
|
||||
//This no longer does anything and shouldn't be used.
|
||||
}
|
||||
|
||||
function resizeGuiWindowWithTabs(windowName, newWidth, newHeight) {
|
||||
right.document.all[windowName + "ContainerTable"].width = newWidth + 22
|
||||
right.document.all[windowName + "ContainerTableSpacer"].width = newWidth
|
||||
right.document.all[windowName + "Bottom"].width = newWidth + 12
|
||||
right.document.all[windowName + "BottomSpacer"].width = newWidth
|
||||
right.document.all[windowName].style.width = newWidth
|
||||
|
||||
|
||||
// Der skal forskellig størrelse på højden afhængig af om vinduet har en label i bunden
|
||||
if (right.document.all[windowName + 'BottomLabel']) {
|
||||
right.document.all[windowName + "ContainerTable"].height = newHeight - 13;
|
||||
right.document.all[windowName].style.height = newHeight - 13;
|
||||
} else {
|
||||
right.document.all[windowName + "ContainerTable"].height = newHeight + 3;
|
||||
right.document.all[windowName].style.height = newHeight + 3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/** Executed when the application starts, binds to events and set global state */
|
||||
app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', 'editorState', 'fileManager', 'assetsService', 'eventsService', '$cookies', '$templateCache',
|
||||
function (userService, $log, $rootScope, $location, navigationService, appState, editorState, fileManager, assetsService, eventsService, $cookies, $templateCache) {
|
||||
|
||||
//This sets the default jquery ajax headers to include our csrf token, we
|
||||
// need to user the beforeSend method because our token changes per user/login so
|
||||
// it cannot be static
|
||||
$.ajaxSetup({
|
||||
beforeSend: function (xhr) {
|
||||
xhr.setRequestHeader("X-XSRF-TOKEN", $cookies["XSRF-TOKEN"]);
|
||||
}
|
||||
});
|
||||
|
||||
/** Listens for authentication and checks if our required assets are loaded, if/once they are we'll broadcast a ready event */
|
||||
eventsService.on("app.authenticated", function(evt, data) {
|
||||
assetsService._loadInitAssets().then(function() {
|
||||
appState.setGlobalState("isReady", true);
|
||||
|
||||
//send the ready event with the included returnToPath,returnToSearch data
|
||||
eventsService.emit("app.ready", data);
|
||||
returnToPath = null, returnToSearch = null;
|
||||
});
|
||||
});
|
||||
|
||||
/** execute code on each successful route */
|
||||
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
|
||||
|
||||
if(current.params.section){
|
||||
$rootScope.locationTitle = current.params.section + " - " + $location.$$host;
|
||||
}
|
||||
else {
|
||||
$rootScope.locationTitle = "Umbraco - " + $location.$$host;
|
||||
}
|
||||
|
||||
//reset the editorState on each successful route chage
|
||||
editorState.reset();
|
||||
|
||||
//reset the file manager on each route change, the file collection is only relavent
|
||||
// when working in an editor and submitting data to the server.
|
||||
//This ensures that memory remains clear of any files and that the editors don't have to manually clear the files.
|
||||
fileManager.clearFiles();
|
||||
});
|
||||
|
||||
/** When the route change is rejected - based on checkAuth - we'll prevent the rejected route from executing including
|
||||
wiring up it's controller, etc... and then redirect to the rejected URL. */
|
||||
$rootScope.$on('$routeChangeError', function(event, current, previous, rejection) {
|
||||
event.preventDefault();
|
||||
|
||||
var returnPath = null;
|
||||
if (rejection.path == "/login" || rejection.path.startsWith("/login/")) {
|
||||
//Set the current path before redirecting so we know where to redirect back to
|
||||
returnPath = encodeURIComponent($location.url());
|
||||
}
|
||||
|
||||
$location.path(rejection.path)
|
||||
if (returnPath) {
|
||||
$location.search("returnPath", returnPath);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
/* this will initialize the navigation service once the application has started */
|
||||
navigationService.init();
|
||||
|
||||
//check for touch device, add to global appState
|
||||
//var touchDevice = ("ontouchstart" in window || window.touch || window.navigator.msMaxTouchPoints === 5 || window.DocumentTouch && document instanceof DocumentTouch);
|
||||
var touchDevice = /android|webos|iphone|ipad|ipod|blackberry|iemobile|touch/i.test(navigator.userAgent.toLowerCase());
|
||||
appState.setGlobalState("touchDevice", touchDevice);
|
||||
}]);
|
||||
@@ -0,0 +1,17 @@
|
||||
LazyLoad.js( [
|
||||
'lib/jquery/jquery.min.js',
|
||||
/* 1.1.5 */
|
||||
'lib/angular/1.1.5/angular.min.js',
|
||||
'lib/angular/1.1.5/angular-cookies.min.js',
|
||||
'lib/angular/1.1.5/angular-mobile.min.js',
|
||||
'lib/angular/1.1.5/angular-mocks.js',
|
||||
'lib/angular/1.1.5/angular-sanitize.min.js',
|
||||
'lib/underscore/underscore-min.js',
|
||||
'js/umbraco.installer.js',
|
||||
'js/umbraco.directives.js'
|
||||
], function () {
|
||||
jQuery(document).ready(function () {
|
||||
angular.bootstrap(document, ['ngSanitize', 'umbraco.install', 'umbraco.directives.validation']);
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
<%@ Page language="c#" Codebehind="language.aspx.cs" AutoEventWireup="True" Inherits="umbraco.js.language" %>
|
||||
@@ -0,0 +1,173 @@
|
||||
app.config(function ($routeProvider) {
|
||||
|
||||
/** This checks if the user is authenticated for a route and what the isRequired is set to.
|
||||
Depending on whether isRequired = true, it first check if the user is authenticated and will resolve successfully
|
||||
otherwise the route will fail and the $routeChangeError event will execute, in that handler we will redirect to the rejected
|
||||
path that is resolved from this method and prevent default (prevent the route from executing) */
|
||||
var canRoute = function(isRequired) {
|
||||
|
||||
return {
|
||||
/** Checks that the user is authenticated, then ensures that are requires assets are loaded */
|
||||
isAuthenticatedAndReady: function ($q, userService, $route, assetsService, appState) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
//don't need to check if we've redirected to login and we've already checked auth
|
||||
if (!$route.current.params.section
|
||||
&& ($route.current.params.check === false || $route.current.params.check === "false")) {
|
||||
deferred.resolve(true);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
userService.isAuthenticated()
|
||||
.then(function () {
|
||||
|
||||
assetsService._loadInitAssets().then(function() {
|
||||
|
||||
//This could be the first time has loaded after the user has logged in, in this case
|
||||
// we need to broadcast the authenticated event - this will be handled by the startup (init)
|
||||
// handler to set/broadcast the ready state
|
||||
var broadcast = appState.getGlobalState("isReady") !== true;
|
||||
|
||||
userService.getCurrentUser({ broadcastEvent: broadcast }).then(function (user) {
|
||||
//is auth, check if we allow or reject
|
||||
if (isRequired) {
|
||||
// U4-5430, Benjamin Howarth
|
||||
// We need to change the current route params if the user only has access to a single section
|
||||
// To do this we need to grab the current user's allowed sections, then reject the promise with the correct path.
|
||||
if (user.allowedSections.indexOf($route.current.params.section) > -1) {
|
||||
//this will resolve successfully so the route will continue
|
||||
deferred.resolve(true);
|
||||
} else {
|
||||
deferred.reject({ path: "/" + user.allowedSections[0] });
|
||||
}
|
||||
}
|
||||
else {
|
||||
deferred.reject({ path: "/" });
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}, function () {
|
||||
//not auth, check if we allow or reject
|
||||
if (isRequired) {
|
||||
//the check=false is checked above so that we don't have to make another http call to check
|
||||
//if they are logged in since we already know they are not.
|
||||
deferred.reject({ path: "/login/false" });
|
||||
}
|
||||
else {
|
||||
//this will resolve successfully so the route will continue
|
||||
deferred.resolve(true);
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** When this is used to resolve it will attempt to log the current user out */
|
||||
var doLogout = function() {
|
||||
return {
|
||||
isLoggedOut: function ($q, userService) {
|
||||
var deferred = $q.defer();
|
||||
userService.logout().then(function () {
|
||||
//success so continue
|
||||
deferred.resolve(true);
|
||||
}, function() {
|
||||
//logout failed somehow ? we'll reject with the login page i suppose
|
||||
deferred.reject({ path: "/login/false" });
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$routeProvider
|
||||
.when('/login', {
|
||||
templateUrl: 'views/common/login.html',
|
||||
//ensure auth is *not* required so it will redirect to /
|
||||
resolve: canRoute(false)
|
||||
})
|
||||
.when('/login/:check', {
|
||||
templateUrl: 'views/common/login.html',
|
||||
//ensure auth is *not* required so it will redirect to /
|
||||
resolve: canRoute(false)
|
||||
})
|
||||
.when('/logout', {
|
||||
redirectTo: '/login/false',
|
||||
resolve: doLogout()
|
||||
})
|
||||
.when('/:section', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section.toLowerCase() === "default" || rp.section.toLowerCase() === "umbraco" || rp.section === "")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/dashboard.html';
|
||||
},
|
||||
resolve: canRoute(true)
|
||||
})
|
||||
.when('/:section/framed/:url', {
|
||||
//This occurs when we need to launch some content in an iframe
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.url)
|
||||
throw "A framed resource must have a url route parameter";
|
||||
|
||||
return 'views/common/legacy.html';
|
||||
},
|
||||
resolve: canRoute(true)
|
||||
})
|
||||
.when('/:section/:tree/:method', {
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.method)
|
||||
return "views/common/dashboard.html";
|
||||
|
||||
//NOTE: This current isn't utilized by anything but does open up some cool opportunities for
|
||||
// us since we'll be able to have specialized views for individual sections which is something
|
||||
// we've never had before. So could utilize this for a new dashboard model when we get native
|
||||
// angular dashboards working. Perhaps a normal section dashboard would list out the registered
|
||||
// dashboards (as tabs if we wanted) and each tab could actually be a route link to one of these views?
|
||||
|
||||
return ('views/' + rp.tree + '/' + rp.method + '.html');
|
||||
},
|
||||
resolve: canRoute(true)
|
||||
})
|
||||
.when('/:section/:tree/:method/:id', {
|
||||
//This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
|
||||
template: "<div ng-include='templateUrl'></div>",
|
||||
//This controller will execute for this route, then we replace the template dynamnically based on the current tree.
|
||||
controller: function ($scope, $route, $routeParams, treeService) {
|
||||
|
||||
if (!$routeParams.tree || !$routeParams.method) {
|
||||
$scope.templateUrl = "views/common/dashboard.html";
|
||||
}
|
||||
|
||||
// Here we need to figure out if this route is for a package tree and if so then we need
|
||||
// to change it's convention view path to:
|
||||
// /App_Plugins/{mypackage}/backoffice/{treetype}/{method}.html
|
||||
|
||||
// otherwise if it is a core tree we use the core paths:
|
||||
// views/{treetype}/{method}.html
|
||||
|
||||
var packageTreeFolder = treeService.getTreePackageFolder($routeParams.tree);
|
||||
|
||||
if (packageTreeFolder) {
|
||||
$scope.templateUrl = (Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath +
|
||||
"/" + packageTreeFolder +
|
||||
"/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html");
|
||||
}
|
||||
else {
|
||||
$scope.templateUrl = ('views/' + $routeParams.tree + '/' + $routeParams.method + '.html');
|
||||
}
|
||||
|
||||
},
|
||||
resolve: canRoute(true)
|
||||
})
|
||||
.otherwise({ redirectTo: '/login' });
|
||||
}).config(function ($locationProvider) {
|
||||
|
||||
//$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
|
||||
// $locationProvider.html5Mode(true); //turn html5 mode on
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
/*! umbraco
|
||||
* https://github.com/umbraco/umbraco-cms/
|
||||
* Copyright (c) 2016 Umbraco HQ;
|
||||
* Licensed
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
angular.module('umbraco.filters', []);
|
||||
angular.module("umbraco.filters")
|
||||
.filter('compareArrays', function() {
|
||||
return function inArray(array, compareArray, compareProperty) {
|
||||
|
||||
var result = [];
|
||||
|
||||
angular.forEach(array, function(arrayItem){
|
||||
|
||||
var exists = false;
|
||||
|
||||
angular.forEach(compareArray, function(compareItem){
|
||||
if( arrayItem[compareProperty] === compareItem[compareProperty]) {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(!exists) {
|
||||
result.push(arrayItem);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return result;
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
angular.module("umbraco.filters").filter('timespan', function() {
|
||||
return function(input) {
|
||||
var sec_num = parseInt(input, 10);
|
||||
var hours = Math.floor(sec_num / 3600);
|
||||
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
|
||||
var seconds = sec_num - (hours * 3600) - (minutes * 60);
|
||||
|
||||
if (hours < 10) {hours = "0"+hours;}
|
||||
if (minutes < 10) {minutes = "0"+minutes;}
|
||||
if (seconds < 10) {seconds = "0"+seconds;}
|
||||
var time = hours+':'+minutes+':'+seconds;
|
||||
return time;
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,31 @@
|
||||
var umbracoAppDev = angular.module('umbraco.httpbackend', ['umbraco', 'ngMockE2E', 'umbraco.mocks']);
|
||||
|
||||
|
||||
function initBackEnd($httpBackend, contentMocks, mediaMocks, treeMocks, userMocks, contentTypeMocks, sectionMocks, entityMocks, dataTypeMocks, dashboardMocks, macroMocks, utilMocks, localizationMocks, prevaluesMocks) {
|
||||
|
||||
console.log("httpBackend inited");
|
||||
|
||||
//Register mocked http responses
|
||||
contentMocks.register();
|
||||
mediaMocks.register();
|
||||
sectionMocks.register();
|
||||
treeMocks.register();
|
||||
dataTypeMocks.register();
|
||||
dashboardMocks.register();
|
||||
userMocks.register();
|
||||
macroMocks.register();
|
||||
contentTypeMocks.register();
|
||||
utilMocks.register();
|
||||
localizationMocks.register();
|
||||
prevaluesMocks.register();
|
||||
entityMocks.register();
|
||||
|
||||
$httpBackend.whenGET(/^..\/config\//).passThrough();
|
||||
$httpBackend.whenGET(/^views\//).passThrough();
|
||||
$httpBackend.whenGET(/^js\//).passThrough();
|
||||
$httpBackend.whenGET(/^lib\//).passThrough();
|
||||
$httpBackend.whenGET(/^assets\//).passThrough();
|
||||
}
|
||||
|
||||
|
||||
umbracoAppDev.run(initBackEnd);
|
||||
@@ -0,0 +1,468 @@
|
||||
/*! umbraco
|
||||
* https://github.com/umbraco/umbraco-cms/
|
||||
* Copyright (c) 2016 Umbraco HQ;
|
||||
* Licensed
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
angular.module('umbraco.install', []);
|
||||
angular.module("umbraco.install").controller("Umbraco.InstallerController",
|
||||
function ($scope, installerService) {
|
||||
|
||||
//TODO: Decouple the service from the controller - the controller should be responsible
|
||||
// for the model (state) and the service should be responsible for helping the controller,
|
||||
// the controller should be passing the model into it's methods for manipulation and not hold
|
||||
// state. We should not be assigning properties from a service to a controller's scope.
|
||||
// see: https://github.com/umbraco/Umbraco-CMS/commit/b86ef0d7ac83f699aee35d807f7f7ebb6dd0ed2c#commitcomment-5721204
|
||||
|
||||
$scope.stepIndex = 0;
|
||||
//comment this out if you just want to see tips
|
||||
installerService.init();
|
||||
|
||||
//uncomment this to see tips
|
||||
//installerService.switchToFeedback();
|
||||
|
||||
$scope.installer = installerService.status;
|
||||
|
||||
$scope.forward = function () {
|
||||
installerService.forward();
|
||||
};
|
||||
|
||||
$scope.backward = function () {
|
||||
installerService.backward();
|
||||
};
|
||||
|
||||
$scope.install = function () {
|
||||
installerService.install();
|
||||
};
|
||||
|
||||
$scope.gotoStep = function (step) {
|
||||
installerService.gotoNamedStep(step);
|
||||
};
|
||||
|
||||
$scope.restart = function () {
|
||||
installerService.gotoStep(0);
|
||||
};
|
||||
});
|
||||
|
||||
//this ensure that we start with a clean slate on every install and upgrade
|
||||
angular.module("umbraco.install").run(function ($templateCache) {
|
||||
$templateCache.removeAll();
|
||||
});
|
||||
angular.module("umbraco.install").factory('installerService', function($rootScope, $q, $timeout, $http, $location, $log){
|
||||
|
||||
var _status = {
|
||||
index: 0,
|
||||
current: undefined,
|
||||
steps: undefined,
|
||||
loading: true,
|
||||
progress: "100%"
|
||||
};
|
||||
|
||||
var factTimer = undefined;
|
||||
var _installerModel = {
|
||||
installId: undefined,
|
||||
instructions: {
|
||||
}
|
||||
};
|
||||
|
||||
//add to umbraco installer facts here
|
||||
var facts = ['Umbraco helped millions of people watch a man jump from the edge of space',
|
||||
'Over 370 000 websites are currently powered by Umbraco',
|
||||
"At least 2 people have named their cat 'Umbraco'",
|
||||
'On an average day, more than 1000 people download Umbraco',
|
||||
'<a target="_blank" href="http://umbraco.tv">umbraco.tv</a> is the premier source of Umbraco video tutorials to get you started',
|
||||
'You can find the world\'s friendliest CMS community at <a target="_blank" href="http://our.umbraco.org">our.umbraco.org</a>',
|
||||
'You can become a certified Umbraco developer by attending one of the official courses',
|
||||
'Umbraco works really well on tablets',
|
||||
'You have 100% control over your markup and design when crafting a website in Umbraco',
|
||||
'Umbraco is the best of both worlds: 100% free and open source, and backed by a professional and profitable company',
|
||||
"There's a pretty big chance, you've visited a website powered by Umbraco today",
|
||||
"'Umbraco-spotting' is the game of spotting big brands running Umbraco",
|
||||
"At least 4 people have the Umbraco logo tattooed on them",
|
||||
"'Umbraco' is the danish name for an allen key",
|
||||
"Umbraco has been around since 2005, that's a looong time in IT",
|
||||
"More than 400 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='http://codegarden15.com'>CodeGarden</a>",
|
||||
"While you are installing Umbraco someone else on the other side of the planet is probably doing it too",
|
||||
"You can extend Umbraco without modifying the source code using either JavaScript or C#",
|
||||
"Umbraco was installed in more than 165 countries in 2015"
|
||||
];
|
||||
|
||||
/**
|
||||
Returns the description for the step at a given index based on the order of the serverOrder of steps
|
||||
Since they don't execute on the server in the order that they are displayed in the UI.
|
||||
*/
|
||||
function getDescriptionForStepAtIndex(steps, index) {
|
||||
var sorted = _.sortBy(steps, "serverOrder");
|
||||
if (sorted[index]) {
|
||||
return sorted[index].description;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/* Returns the description for the given step name */
|
||||
function getDescriptionForStepName(steps, name) {
|
||||
var found = _.find(steps, function(i) {
|
||||
return i.name == name;
|
||||
});
|
||||
return (found) ? found.description : null;
|
||||
}
|
||||
|
||||
//calculates the offset of the progressbar on the installer
|
||||
function calculateProgress(steps, next) {
|
||||
var sorted = _.sortBy(steps, "serverOrder");
|
||||
|
||||
var pct = "100%";
|
||||
for (var i = sorted.length - 1; i >= 0; i--) {
|
||||
if(sorted[i].name == next){
|
||||
pct = Math.floor((i+1) / steps.length * 100) + "%";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pct;
|
||||
}
|
||||
|
||||
//helpful defaults for the view loading
|
||||
function resolveView(view){
|
||||
|
||||
if(view.indexOf(".html") < 0){
|
||||
view = view + ".html";
|
||||
}
|
||||
if(view.indexOf("/") < 0){
|
||||
view = "views/install/" + view;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/** Have put this here because we are not referencing our other modules */
|
||||
function safeApply (scope, fn) {
|
||||
if (scope.$$phase || scope.$root.$$phase) {
|
||||
if (angular.isFunction(fn)) {
|
||||
fn();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (angular.isFunction(fn)) {
|
||||
scope.$apply(fn);
|
||||
}
|
||||
else {
|
||||
scope.$apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var service = {
|
||||
|
||||
status : _status,
|
||||
//loads the needed steps and sets the intial state
|
||||
init : function(){
|
||||
service.status.loading = true;
|
||||
if(!_status.all){
|
||||
service.getSteps().then(function(response){
|
||||
service.status.steps = response.data.steps;
|
||||
service.status.index = 0;
|
||||
_installerModel.installId = response.data.installId;
|
||||
service.findNextStep();
|
||||
|
||||
$timeout(function(){
|
||||
service.status.loading = false;
|
||||
service.status.configuring = true;
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
//loads available packages from our.umbraco.org
|
||||
getPackages : function(){
|
||||
return $http.get(Umbraco.Sys.ServerVariables.installApiBaseUrl + "GetPackages");
|
||||
},
|
||||
|
||||
getSteps : function(){
|
||||
return $http.get(Umbraco.Sys.ServerVariables.installApiBaseUrl + "GetSetup");
|
||||
},
|
||||
|
||||
gotoStep : function(index){
|
||||
var step = service.status.steps[index];
|
||||
step.view = resolveView(step.view);
|
||||
|
||||
if(!step.model){
|
||||
step.model = {};
|
||||
}
|
||||
|
||||
service.status.index = index;
|
||||
service.status.current = step;
|
||||
service.retrieveCurrentStep();
|
||||
},
|
||||
|
||||
gotoNamedStep : function(stepName){
|
||||
var step = _.find(service.status.steps, function(s, index){
|
||||
if (s.view && s.name === stepName) {
|
||||
service.status.index = index;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
step.view = resolveView(step.view);
|
||||
if(!step.model){
|
||||
step.model = {};
|
||||
}
|
||||
service.retrieveCurrentStep();
|
||||
service.status.current = step;
|
||||
},
|
||||
|
||||
/**
|
||||
Finds the next step containing a view. If one is found it stores it as the current step
|
||||
and retreives the step information and returns it, otherwise returns null .
|
||||
*/
|
||||
findNextStep : function(){
|
||||
var step = _.find(service.status.steps, function(s, index){
|
||||
if(s.view && index >= service.status.index){
|
||||
service.status.index = index;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (step) {
|
||||
if (step.view.indexOf(".html") < 0) {
|
||||
step.view = step.view + ".html";
|
||||
}
|
||||
|
||||
if (step.view.indexOf("/") < 0) {
|
||||
step.view = "views/install/" + step.view;
|
||||
}
|
||||
|
||||
if (!step.model) {
|
||||
step.model = {};
|
||||
}
|
||||
|
||||
service.status.current = step;
|
||||
service.retrieveCurrentStep();
|
||||
|
||||
//returns the next found step
|
||||
return step;
|
||||
}
|
||||
else {
|
||||
//there are no more steps found containing a view so return null
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
storeCurrentStep : function(){
|
||||
_installerModel.instructions[service.status.current.name] = service.status.current.model;
|
||||
},
|
||||
|
||||
retrieveCurrentStep : function(){
|
||||
if(_installerModel.instructions[service.status.current.name]){
|
||||
service.status.current.model = _installerModel.instructions[service.status.current.name];
|
||||
}
|
||||
},
|
||||
|
||||
/** Moves the installer forward to the next view, if there are not more views than the installation will commence */
|
||||
forward : function(){
|
||||
service.storeCurrentStep();
|
||||
service.status.index++;
|
||||
var found = service.findNextStep();
|
||||
if (!found) {
|
||||
//no more steps were found so start the installation process
|
||||
service.install();
|
||||
}
|
||||
},
|
||||
|
||||
backwards : function(){
|
||||
service.storeCurrentStep();
|
||||
service.gotoStep(service.status.index--);
|
||||
},
|
||||
|
||||
install : function(){
|
||||
service.storeCurrentStep();
|
||||
service.switchToFeedback();
|
||||
|
||||
service.status.feedback = getDescriptionForStepAtIndex(service.status.steps, 0);
|
||||
service.status.progress = 0;
|
||||
|
||||
function processInstallStep() {
|
||||
|
||||
$http.post(Umbraco.Sys.ServerVariables.installApiBaseUrl + "PostPerformInstall", _installerModel)
|
||||
.success(function(data, status, headers, config) {
|
||||
if (!data.complete) {
|
||||
|
||||
//progress feedback
|
||||
service.status.progress = calculateProgress(service.status.steps, data.nextStep);
|
||||
|
||||
if (data.view) {
|
||||
//set the current view and model to whatever the process returns, the view is responsible for retriggering install();
|
||||
var v = resolveView(data.view);
|
||||
service.status.current = { view: v, model: data.model };
|
||||
|
||||
//turn off loading bar and feedback
|
||||
service.switchToConfiguration();
|
||||
}
|
||||
else {
|
||||
var desc = getDescriptionForStepName(service.status.steps, data.nextStep);
|
||||
if (desc) {
|
||||
service.status.feedback = desc;
|
||||
}
|
||||
processInstallStep();
|
||||
}
|
||||
}
|
||||
else {
|
||||
service.complete();
|
||||
}
|
||||
}).error(function(data, status, headers, config) {
|
||||
//need to handle 500's separately, this will happen if something goes wrong outside
|
||||
// of the installer (like app startup events or something) and these will get returned as text/html
|
||||
// not as json. If this happens we can't actually load in external views since they will YSOD as well!
|
||||
// so we need to display this in our own internal way
|
||||
|
||||
if (status >= 500 && status < 600) {
|
||||
service.status.current = { view: "ysod", model: null };
|
||||
var ysod = data;
|
||||
//we need to manually write the html to the iframe - the html contains full html markup
|
||||
$timeout(function () {
|
||||
document.getElementById('ysod').contentDocument.write(ysod);
|
||||
}, 500);
|
||||
}
|
||||
else {
|
||||
//this is where we handle installer error
|
||||
var v = data.view ? resolveView(data.view) : resolveView("error");
|
||||
var model = data.model ? data.model : data;
|
||||
service.status.current = { view: v, model: model };
|
||||
}
|
||||
|
||||
service.switchToConfiguration();
|
||||
|
||||
});
|
||||
}
|
||||
processInstallStep();
|
||||
},
|
||||
|
||||
randomFact: function () {
|
||||
safeApply($rootScope, function() {
|
||||
service.status.fact = facts[_.random(facts.length - 1)];
|
||||
});
|
||||
},
|
||||
|
||||
switchToFeedback : function(){
|
||||
service.status.current = undefined;
|
||||
service.status.loading = true;
|
||||
service.status.configuring = false;
|
||||
|
||||
//initial fact
|
||||
service.randomFact();
|
||||
|
||||
//timed facts
|
||||
factTimer = window.setInterval(function(){
|
||||
service.randomFact();
|
||||
},6000);
|
||||
},
|
||||
|
||||
switchToConfiguration : function(){
|
||||
service.status.loading = false;
|
||||
service.status.configuring = true;
|
||||
service.status.feedback = undefined;
|
||||
service.status.fact = undefined;
|
||||
|
||||
if(factTimer){
|
||||
clearInterval(factTimer);
|
||||
}
|
||||
},
|
||||
|
||||
complete : function(){
|
||||
|
||||
service.status.progress = "100%";
|
||||
service.status.done = true;
|
||||
service.status.feedback = "Redirecting you to Umbraco, please wait";
|
||||
service.status.loading = false;
|
||||
|
||||
if(factTimer){
|
||||
clearInterval(factTimer);
|
||||
}
|
||||
|
||||
$timeout(function(){
|
||||
window.location.href = Umbraco.Sys.ServerVariables.umbracoBaseUrl;
|
||||
}, 1500);
|
||||
}
|
||||
};
|
||||
|
||||
return service;
|
||||
});
|
||||
|
||||
angular.module("umbraco.install").controller("Umbraco.Installer.DataBaseController", function($scope, $http, installerService){
|
||||
|
||||
$scope.checking = false;
|
||||
$scope.dbs = [
|
||||
{name: 'Microsoft SQL Server Compact (SQL CE)', id: 0},
|
||||
{name: 'Microsoft SQL Server', id: 1},
|
||||
{ name: 'Microsoft SQL Azure', id: 3 },
|
||||
{ name: 'MySQL', id: 2 },
|
||||
{name: 'Custom connection string', id: -1}];
|
||||
|
||||
if(installerService.status.current.model.dbType === undefined){
|
||||
installerService.status.current.model.dbType = 0;
|
||||
}
|
||||
|
||||
$scope.validateAndForward = function(){
|
||||
if(!$scope.checking && this.myForm.$valid){
|
||||
$scope.checking = true;
|
||||
var model = installerService.status.current.model;
|
||||
|
||||
$http.post(Umbraco.Sys.ServerVariables.installApiBaseUrl + "PostValidateDatabaseConnection",
|
||||
model).then(function(response){
|
||||
|
||||
if(response.data === "true"){
|
||||
installerService.forward();
|
||||
}else{
|
||||
$scope.invalidDbDns = true;
|
||||
}
|
||||
|
||||
$scope.checking = false;
|
||||
}, function(){
|
||||
$scope.invalidDbDns = true;
|
||||
$scope.checking = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
angular.module("umbraco.install").controller("Umbraco.Installer.PackagesController", function ($scope, installerService) {
|
||||
|
||||
installerService.getPackages().then(function (response) {
|
||||
$scope.packages = response.data;
|
||||
});
|
||||
|
||||
$scope.setPackageAndContinue = function (pckId) {
|
||||
installerService.status.current.model = pckId;
|
||||
installerService.forward();
|
||||
};
|
||||
|
||||
});
|
||||
angular.module("umbraco.install").controller("Umbraco.Install.UserController", function($scope, installerService) {
|
||||
|
||||
$scope.passwordPattern = /.*/;
|
||||
$scope.installer.current.model.subscribeToNewsLetter = true;
|
||||
|
||||
if ($scope.installer.current.model.minNonAlphaNumericLength > 0) {
|
||||
var exp = "";
|
||||
for (var i = 0; i < $scope.installer.current.model.minNonAlphaNumericLength; i++) {
|
||||
exp += ".*[\\W].*";
|
||||
}
|
||||
//replace duplicates
|
||||
exp = exp.replace(".*.*", ".*");
|
||||
$scope.passwordPattern = new RegExp(exp);
|
||||
}
|
||||
|
||||
$scope.validateAndInstall = function(){
|
||||
installerService.install();
|
||||
};
|
||||
|
||||
$scope.validateAndForward = function(){
|
||||
if(this.myForm.$valid){
|
||||
installerService.forward();
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,206 @@
|
||||
/*! umbraco
|
||||
* https://github.com/umbraco/umbraco-cms/
|
||||
* Copyright (c) 2016 Umbraco HQ;
|
||||
* Licensed
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
//TODO: This is silly and unecessary to have a separate module for this
|
||||
angular.module('umbraco.security.retryQueue', []);
|
||||
angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']);
|
||||
angular.module('umbraco.security', ['umbraco.security.retryQueue', 'umbraco.security.interceptor']);
|
||||
//TODO: This is silly and unecessary to have a separate module for this
|
||||
angular.module('umbraco.security.retryQueue', [])
|
||||
|
||||
// This is a generic retry queue for security failures. Each item is expected to expose two functions: retry and cancel.
|
||||
.factory('securityRetryQueue', ['$q', '$log', function ($q, $log) {
|
||||
|
||||
var retryQueue = [];
|
||||
var retryUser = null;
|
||||
|
||||
var service = {
|
||||
// The security service puts its own handler in here!
|
||||
onItemAddedCallbacks: [],
|
||||
|
||||
hasMore: function() {
|
||||
return retryQueue.length > 0;
|
||||
},
|
||||
push: function(retryItem) {
|
||||
retryQueue.push(retryItem);
|
||||
// Call all the onItemAdded callbacks
|
||||
angular.forEach(service.onItemAddedCallbacks, function(cb) {
|
||||
try {
|
||||
cb(retryItem);
|
||||
} catch(e) {
|
||||
$log.error('securityRetryQueue.push(retryItem): callback threw an error' + e);
|
||||
}
|
||||
});
|
||||
},
|
||||
pushRetryFn: function(reason, userName, retryFn) {
|
||||
// The reason parameter is optional
|
||||
if ( arguments.length === 2) {
|
||||
retryFn = userName;
|
||||
userName = reason;
|
||||
reason = undefined;
|
||||
}
|
||||
|
||||
if ((retryUser && retryUser !== userName) || userName === null) {
|
||||
throw new Error('invalid user');
|
||||
}
|
||||
|
||||
retryUser = userName;
|
||||
|
||||
// The deferred object that will be resolved or rejected by calling retry or cancel
|
||||
var deferred = $q.defer();
|
||||
var retryItem = {
|
||||
reason: reason,
|
||||
retry: function() {
|
||||
// Wrap the result of the retryFn into a promise if it is not already
|
||||
$q.when(retryFn()).then(function(value) {
|
||||
// If it was successful then resolve our deferred
|
||||
deferred.resolve(value);
|
||||
}, function(value) {
|
||||
// Othewise reject it
|
||||
deferred.reject(value);
|
||||
});
|
||||
},
|
||||
cancel: function() {
|
||||
// Give up on retrying and reject our deferred
|
||||
deferred.reject();
|
||||
}
|
||||
};
|
||||
service.push(retryItem);
|
||||
return deferred.promise;
|
||||
},
|
||||
retryReason: function() {
|
||||
return service.hasMore() && retryQueue[0].reason;
|
||||
},
|
||||
cancelAll: function() {
|
||||
while(service.hasMore()) {
|
||||
retryQueue.shift().cancel();
|
||||
}
|
||||
retryUser = null;
|
||||
},
|
||||
retryAll: function (userName) {
|
||||
|
||||
if (retryUser == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (retryUser !== userName) {
|
||||
service.cancelAll();
|
||||
return;
|
||||
}
|
||||
|
||||
while(service.hasMore()) {
|
||||
retryQueue.shift().retry();
|
||||
}
|
||||
}
|
||||
};
|
||||
return service;
|
||||
}]);
|
||||
angular.module('umbraco.security.interceptor')
|
||||
// This http interceptor listens for authentication successes and failures
|
||||
.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', 'requestInterceptorFilter', function ($injector, queue, notifications, requestInterceptorFilter) {
|
||||
return function(promise) {
|
||||
|
||||
return promise.then(
|
||||
function(originalResponse) {
|
||||
// Intercept successful requests
|
||||
|
||||
//Here we'll check if our custom header is in the response which indicates how many seconds the user's session has before it
|
||||
//expires. Then we'll update the user in the user service accordingly.
|
||||
var headers = originalResponse.headers();
|
||||
if (headers["x-umb-user-seconds"]) {
|
||||
// We must use $injector to get the $http service to prevent circular dependency
|
||||
var userService = $injector.get('userService');
|
||||
userService.setUserTimeout(headers["x-umb-user-seconds"]);
|
||||
}
|
||||
|
||||
return promise;
|
||||
}, function(originalResponse) {
|
||||
// Intercept failed requests
|
||||
|
||||
//Here we'll check if we should ignore the error, this will be based on an original header set
|
||||
var headers = originalResponse.config ? originalResponse.config.headers : {};
|
||||
if (headers["x-umb-ignore-error"] === "ignore") {
|
||||
//exit/ignore
|
||||
return promise;
|
||||
}
|
||||
var filtered = _.find(requestInterceptorFilter(), function(val) {
|
||||
return originalResponse.config.url.indexOf(val) > 0;
|
||||
});
|
||||
if (filtered) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
//A 401 means that the user is not logged in
|
||||
if (originalResponse.status === 401) {
|
||||
|
||||
var userService = $injector.get('userService'); // see above
|
||||
|
||||
//Associate the user name with the retry to ensure we retry for the right user
|
||||
promise = userService.getCurrentUser()
|
||||
.then(function (user) {
|
||||
var userName = user ? user.name : null;
|
||||
//The request bounced because it was not authorized - add a new request to the retry queue
|
||||
return queue.pushRetryFn('unauthorized-server', userName, function retryRequest() {
|
||||
// We must use $injector to get the $http service to prevent circular dependency
|
||||
return $injector.get('$http')(originalResponse.config);
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (originalResponse.status === 404) {
|
||||
|
||||
//a 404 indicates that the request was not found - this could be due to a non existing url, or it could
|
||||
//be due to accessing a url with a parameter that doesn't exist, either way we should notifiy the user about it
|
||||
|
||||
var errMsg = "The URL returned a 404 (not found): <br/><i>" + originalResponse.config.url.split('?')[0] + "</i>";
|
||||
if (originalResponse.data && originalResponse.data.ExceptionMessage) {
|
||||
errMsg += "<br/> with error: <br/><i>" + originalResponse.data.ExceptionMessage + "</i>";
|
||||
}
|
||||
if (originalResponse.config.data) {
|
||||
errMsg += "<br/> with data: <br/><i>" + angular.toJson(originalResponse.config.data) + "</i><br/>Contact your administrator for information.";
|
||||
}
|
||||
|
||||
notifications.error(
|
||||
"Request error",
|
||||
errMsg);
|
||||
|
||||
}
|
||||
else if (originalResponse.status === 403) {
|
||||
//if the status was a 403 it means the user didn't have permission to do what the request was trying to do.
|
||||
//How do we deal with this now, need to tell the user somehow that they don't have permission to do the thing that was
|
||||
//requested. We can either deal with this globally here, or we can deal with it globally for individual requests on the umbRequestHelper,
|
||||
// or completely custom for services calling resources.
|
||||
|
||||
//http://issues.umbraco.org/issue/U4-2749
|
||||
|
||||
//It was decided to just put these messages into the normal status messages.
|
||||
|
||||
var msg = "Unauthorized access to URL: <br/><i>" + originalResponse.config.url.split('?')[0] + "</i>";
|
||||
if (originalResponse.config.data) {
|
||||
msg += "<br/> with data: <br/><i>" + angular.toJson(originalResponse.config.data) + "</i><br/>Contact your administrator for information.";
|
||||
}
|
||||
|
||||
notifications.error(
|
||||
"Authorization error",
|
||||
msg);
|
||||
}
|
||||
|
||||
return promise;
|
||||
});
|
||||
};
|
||||
}])
|
||||
|
||||
.value('requestInterceptorFilter', function() {
|
||||
return ["www.gravatar.com"];
|
||||
})
|
||||
|
||||
// We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block.
|
||||
.config(['$httpProvider', function ($httpProvider) {
|
||||
$httpProvider.responseInterceptors.push('securityInterceptor');
|
||||
}]);
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,42 @@
|
||||
//create the namespace (NOTE: This loads before any dependencies so we don't have a namespace mgr so we just create it manually)
|
||||
var Umbraco = {};
|
||||
Umbraco.Sys = {};
|
||||
//define a global static object
|
||||
Umbraco.Sys.ServerVariables = {
|
||||
umbracoUrls: {
|
||||
"contentApiBaseUrl": "/umbraco/UmbracoApi/Content/",
|
||||
"mediaApiBaseUrl": "/umbraco/UmbracoApi/Media/",
|
||||
"dataTypeApiBaseUrl": "/umbraco/UmbracoApi/DataType/",
|
||||
"sectionApiBaseUrl": "/umbraco/UmbracoApi/Section/",
|
||||
"treeApplicationApiBaseUrl": "/umbraco/UmbracoTrees/ApplicationTreeApi/",
|
||||
"contentTypeApiBaseUrl": "/umbraco/Api/ContentType/",
|
||||
"mediaTypeApiBaseUrl": "/umbraco/Api/MediaType/",
|
||||
"macroApiBaseUrl": "/umbraco/Api/Macro/",
|
||||
"authenticationApiBaseUrl": "/umbraco/UmbracoApi/Authentication/",
|
||||
//For this we'll just provide a file that exists during the mock session since we don't really have legay js tree stuff
|
||||
"legacyTreeJs": "/belle/lib/lazyload/empty.js",
|
||||
"serverVarsJs": "/belle/lib/lazyload/empty.js",
|
||||
"imagesApiBaseUrl": "/umbraco/UmbracoApi/Images/",
|
||||
"entityApiBaseUrl": "/umbraco/UmbracoApi/Entity/",
|
||||
"dashboardApiBaseUrl": "/umbraco/UmbracoApi/Dashboard/",
|
||||
"updateCheckApiBaseUrl": "/umbraco/Api/UpdateCheck/",
|
||||
"relationApiBaseUrl": "/umbraco/UmbracoApi/Relation/",
|
||||
"rteApiBaseUrl": "/umbraco/UmbracoApi/RichTextPreValue/"
|
||||
},
|
||||
umbracoSettings: {
|
||||
"umbracoPath": "/umbraco",
|
||||
"appPluginsPath" : "/App_Plugins",
|
||||
"imageFileTypes": "jpeg,jpg,gif,bmp,png,tiff,tif",
|
||||
"keepUserLoggedIn": true
|
||||
},
|
||||
umbracoPlugins: {
|
||||
trees: [
|
||||
{ alias: "myTree", packageFolder: "MyPackage" }
|
||||
]
|
||||
},
|
||||
isDebuggingEnabled: true,
|
||||
application: {
|
||||
assemblyVersion: "1",
|
||||
version: "7"
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,102 @@
|
||||
var ctrlDown = false;
|
||||
var shiftDown = false;
|
||||
var keycode = 0
|
||||
|
||||
var currentRichTextDocument = null;
|
||||
var currentRichTextObject = null;
|
||||
|
||||
function umbracoCheckKeysUp(e) {
|
||||
ctrlDown = e.ctrlKey;
|
||||
shiftDown = e.shiftKey;
|
||||
}
|
||||
|
||||
function umbracoActivateKeys(ctrl, shift, key) {
|
||||
ctrlDown = ctrl;
|
||||
shiftDown = shift;
|
||||
keycode = key
|
||||
return runShortCuts();
|
||||
}
|
||||
|
||||
function umbracoActivateKeysUp(ctrl, shift, key) {
|
||||
ctrlDown = ctrl;
|
||||
shiftDown = shift;
|
||||
keycode = key;
|
||||
}
|
||||
|
||||
function umbracoCheckKeys(e) {
|
||||
ctrlDown = e.ctrlKey;
|
||||
shiftDown = e.shiftKey;
|
||||
keycode = e.keyCode;
|
||||
|
||||
return runShortCuts();
|
||||
}
|
||||
|
||||
function shortcutCheckKeysPressFirefox(e) {
|
||||
if (ctrlDown && keycode == 83)
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
|
||||
function runShortCuts() {
|
||||
if (currentRichTextObject != undefined && currentRichTextObject != null) {
|
||||
if (ctrlDown) {
|
||||
if (!shiftDown && keycode == 9)
|
||||
functionsFrame.tabSwitch(1);
|
||||
else
|
||||
if (shiftDown && keycode == 9) functionsFrame.tabSwitch(-1);
|
||||
|
||||
if (keycode == 83) {doSubmit(); return false;}
|
||||
if (shiftDown && currentRichTextObject) {
|
||||
if (keycode == 70) {functionsFrame.umbracoInsertForm(myAlias); return false;}
|
||||
if (keycode == 76) {functionsFrame.umbracoLink(myAlias); return false;}
|
||||
if (keycode == 77) {functionsFrame.umbracoInsertMacro(myAlias, umbracoPath); return false;}
|
||||
if (keycode == 80) {functionsFrame.umbracoImage(myAlias); return false;}
|
||||
if (keycode == 84) {functionsFrame.umbracoInsertTable(myAlias); return false;}
|
||||
if (keycode == 86) {functionsFrame.umbracoShowStyles(myAlias); return false;}
|
||||
if (keycode == 85) {functionsFrame.document.getElementById('TabView1_tab01layer_publish').click(); return false;}
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
if (isDialog) {
|
||||
if (keycode == 27) {window.close();} // ESC
|
||||
if (keycode == 13 && functionsFrame.submitOnEnter != undefined) {
|
||||
if (!functionsFrame.disableEnterSubmit) {
|
||||
if (functionsFrame.submitOnEnter) {
|
||||
// firefox hack
|
||||
if (window.addEventListener)
|
||||
e.preventDefault();
|
||||
doSubmit();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ctrlDown) {
|
||||
if (keycode == 83)
|
||||
doSubmit();
|
||||
else if (keycode == 85)
|
||||
document.getElementById('TabView1_tab01layer_publish').click();
|
||||
else if (!shiftDown && keycode == 9) {
|
||||
functionsFrame.tabSwitch(1);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (shiftDown && keycode == 9) {
|
||||
functionsFrame.tabSwitch(-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
if (window.addEventListener) {
|
||||
document.addEventListener('keyup', umbracoCheckKeysUp, false);
|
||||
document.addEventListener('keydown', umbracoCheckKeys, false);
|
||||
document.addEventListener('keypress', shortcutCheckKeysPressFirefox, false);
|
||||
} else {
|
||||
document.attachEvent( "onkeyup", umbracoCheckKeysUp);
|
||||
document.attachEvent("onkeydown", umbracoCheckKeys);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
function umbracoCheckUpgrade(result) {
|
||||
if (result) {
|
||||
if (result.UpgradeType.toLowerCase() != 'none') {
|
||||
if (UmbSpeechBubble == null) {
|
||||
InitUmbracoSpeechBubble();
|
||||
}
|
||||
var icon = 'info';
|
||||
if (result.UpgradeType.toLowerCase() == 'critical') {
|
||||
icon = 'error';
|
||||
}
|
||||
|
||||
UmbSpeechBubble.ShowMessage(icon, 'Upgrade Available!', '<a style="text-decoration:none" target="_blank" href="' + result.UpgradeUrl + '">' + result.UpgradeComment + '</a>', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
var requestRunning = false;
|
||||
var xmlHttp = null;
|
||||
var xmlHttpDebug = false;
|
||||
|
||||
// Inspired by great work of Webfx in xloadtree
|
||||
function umbracoStartXmlRequest(scriptUrl, postData, eventFunction) {
|
||||
|
||||
// random hack for ie7
|
||||
day = new Date();
|
||||
z = day.getTime();
|
||||
y = (z - (parseInt(z/1000,10) * 1000))/10;
|
||||
scriptUrl += "&xmlRnd=" + y;
|
||||
|
||||
if (xmlHttpDebug)
|
||||
alert(scriptUrl)
|
||||
|
||||
this.requestRunning = true;
|
||||
this.xmlHttpObject = XmlHttp.create();
|
||||
if (postData != "") {
|
||||
if (document.all) {
|
||||
this.xmlHttpObject.open("POST", scriptUrl, false);
|
||||
this.xmlHttpObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
}
|
||||
else {
|
||||
eval(eventFunction);
|
||||
}
|
||||
} else
|
||||
this.xmlHttpObject.open("GET", scriptUrl, true);
|
||||
|
||||
|
||||
this.xmlHttpObject.onreadystatechange = function () {
|
||||
if (xmlHttp.readyState == 4) {
|
||||
// Removed the this from this.requestRunning = false; this was causing a bug in the find search box in cms backend.
|
||||
requestRunning = false;
|
||||
// debug
|
||||
if (xmlHttpDebug)
|
||||
alert(xmlHttp.responseText)
|
||||
eval(eventFunction);
|
||||
xmlHttp = null;
|
||||
}
|
||||
};
|
||||
|
||||
// call in new thread to allow ui to update
|
||||
window.setTimeout(function () {
|
||||
this.xmlHttpObject.send(postData);
|
||||
}, 10);
|
||||
|
||||
xmlHttp = this.xmlHttpObject;
|
||||
return this;
|
||||
}
|
||||
|
||||
umbracoStartXmlRequest.prototype.ResultText =
|
||||
umbracoStartXmlRequest.prototype.ResultText = function () {
|
||||
return this.xmlHttpObject.responseText;
|
||||
}
|
||||
|
||||
umbracoStartXmlRequest.prototype.ResultXml =
|
||||
umbracoStartXmlRequest.prototype.ResultXml = function () {
|
||||
return this.xmlHttpObject.responseXML;
|
||||
}
|
||||
|
||||
function umbracoXmlRequestResult() {
|
||||
if (!requestRunning)
|
||||
return xmlHttp.responseXML
|
||||
}
|
||||
|
||||
function umbracoXmlRequestResultTxt() {
|
||||
if (!requestRunning)
|
||||
return xmlHttp.responseText
|
||||
}
|
||||
|
||||
function xmlReturnRandom() {
|
||||
day = new Date()
|
||||
z = day.getTime()
|
||||
y = (z - (parseInt(z/1000,10) * 1000))/10
|
||||
return y
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
//<script>
|
||||
//////////////////
|
||||
// Helper Stuff //
|
||||
//////////////////
|
||||
|
||||
function HTMLEncode(t) {
|
||||
return t.toString().replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">");
|
||||
}
|
||||
|
||||
// used to find the Automation server name
|
||||
function getDomDocumentPrefix() {
|
||||
if (getDomDocumentPrefix.prefix)
|
||||
return getDomDocumentPrefix.prefix;
|
||||
|
||||
var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
|
||||
var o;
|
||||
for (var i = 0; i < prefixes.length; i++) {
|
||||
try {
|
||||
// try to create the objects
|
||||
o = new ActiveXObject(prefixes[i] + ".DomDocument");
|
||||
return getDomDocumentPrefix.prefix = prefixes[i];
|
||||
}
|
||||
catch (ex) {};
|
||||
}
|
||||
|
||||
throw new Error("Could not find an installed XML parser");
|
||||
}
|
||||
|
||||
function getXmlHttpPrefix() {
|
||||
if (getXmlHttpPrefix.prefix)
|
||||
return getXmlHttpPrefix.prefix;
|
||||
|
||||
var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
|
||||
var o;
|
||||
for (var i = 0; i < prefixes.length; i++) {
|
||||
try {
|
||||
// try to create the objects
|
||||
o = new ActiveXObject(prefixes[i] + ".XmlHttp");
|
||||
return getXmlHttpPrefix.prefix = prefixes[i];
|
||||
}
|
||||
catch (ex) {};
|
||||
}
|
||||
|
||||
throw new Error("Could not find an installed XML parser");
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Start the Real stuff //
|
||||
//////////////////////////
|
||||
|
||||
|
||||
// XmlHttp factory
|
||||
function XmlHttp() {}
|
||||
|
||||
XmlHttp.create = function () {
|
||||
try {
|
||||
if (window.XMLHttpRequest) {
|
||||
var req = new XMLHttpRequest();
|
||||
|
||||
// some versions of Moz do not support the readyState property
|
||||
// and the onreadystate event so we patch it!
|
||||
if (req.readyState == null) {
|
||||
req.readyState = 1;
|
||||
req.addEventListener("load", function () {
|
||||
req.readyState = 4;
|
||||
if (typeof req.onreadystatechange == "function")
|
||||
req.onreadystatechange();
|
||||
}, false);
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
if (window.ActiveXObject) {
|
||||
return new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp");
|
||||
}
|
||||
}
|
||||
catch (ex) {}
|
||||
// fell through
|
||||
throw new Error("Your browser does not support XmlHttp objects");
|
||||
};
|
||||
|
||||
// XmlDocument factory
|
||||
function XmlDocument() {}
|
||||
|
||||
XmlDocument.create = function () {
|
||||
try {
|
||||
// DOM2
|
||||
if (document.implementation && document.implementation.createDocument) {
|
||||
var doc = document.implementation.createDocument("", "", null);
|
||||
|
||||
// some versions of Moz do not support the readyState property
|
||||
// and the onreadystate event so we patch it!
|
||||
if (doc.readyState == null) {
|
||||
doc.readyState = 1;
|
||||
doc.addEventListener("load", function () {
|
||||
doc.readyState = 4;
|
||||
if (typeof doc.onreadystatechange == "function")
|
||||
doc.onreadystatechange();
|
||||
}, false);
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
if (window.ActiveXObject)
|
||||
return new ActiveXObject(getDomDocumentPrefix() + ".DomDocument");
|
||||
}
|
||||
catch (ex) {}
|
||||
throw new Error("Your browser does not support XmlDocument objects");
|
||||
};
|
||||
|
||||
// Create the loadXML method and xml getter for Mozilla
|
||||
if (window.DOMParser &&
|
||||
window.XMLSerializer &&
|
||||
window.Node && Node.prototype && Node.prototype.__defineGetter__) {
|
||||
|
||||
// XMLDocument did not extend the Document interface in some versions
|
||||
// of Mozilla. Extend both!
|
||||
XMLDocument.prototype.loadXML =
|
||||
Document.prototype.loadXML = function (s) {
|
||||
|
||||
// parse the string to a new doc
|
||||
var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
|
||||
|
||||
// remove all initial children
|
||||
while (this.hasChildNodes())
|
||||
this.removeChild(this.lastChild);
|
||||
|
||||
// insert and import nodes
|
||||
for (var i = 0; i < doc2.childNodes.length; i++) {
|
||||
this.appendChild(this.importNode(doc2.childNodes[i], true));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* xml getter
|
||||
*
|
||||
* This serializes the DOM tree to an XML String
|
||||
*
|
||||
* Usage: var sXml = oNode.xml
|
||||
*
|
||||
*/
|
||||
// XMLDocument did not extend the Document interface in some versions
|
||||
// of Mozilla. Extend both!
|
||||
XMLDocument.prototype.__defineGetter__("xml", function () {
|
||||
return (new XMLSerializer()).serializeToString(this);
|
||||
});
|
||||
Document.prototype.__defineGetter__("xml", function () {
|
||||
return (new XMLSerializer()).serializeToString(this);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user