Merge remote-tracking branch 'upstream/dev-v7' into dev-v7-U4-9571
# Conflicts: # src/Umbraco.Web.UI.Client/src/less/tree.less
@@ -25,9 +25,10 @@
|
||||
"jquery-migrate": "1.4.0",
|
||||
"angular-dynamic-locale": "0.1.28",
|
||||
"ng-file-upload": "~7.3.8",
|
||||
"tinymce": "~4.1.10",
|
||||
"tinymce": "~4.5.3",
|
||||
"codemirror": "~5.3.0",
|
||||
"angular-local-storage": "~0.2.3",
|
||||
"moment": "~2.10.3"
|
||||
"moment": "~2.10.3",
|
||||
"ace-builds": "^1.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,17 @@ module.exports = function (grunt) {
|
||||
//TODO: Too much watching, this brings windows to it's knees when in dev mode
|
||||
//run by the watch task
|
||||
grunt.registerTask('watch-js', ['jshint:dev', 'concat', 'copy:app', 'copy:mocks', 'copy:canvasdesigner', 'copy:vs', 'karma:unit']);
|
||||
grunt.registerTask('watch-less', ['recess:build', 'recess:installer', 'recess:canvasdesigner', 'postcss', 'copy:canvasdesigner', 'copy:assets', 'copy:vs']);
|
||||
grunt.registerTask('watch-less', ['recess:build', 'recess:installer', 'recess:nonodes', 'recess:canvasdesigner', 'postcss', 'copy:canvasdesigner', 'copy:assets', 'copy:vs']);
|
||||
grunt.registerTask('watch-html', ['copy:views', 'copy:vs']);
|
||||
grunt.registerTask('watch-installer', ['concat:install', 'concat:installJs', 'copy:installer', 'copy:vs']);
|
||||
grunt.registerTask('watch-canvasdesigner', ['copy:canvasdesigner', 'concat:canvasdesignerJs', 'copy:vs']);
|
||||
grunt.registerTask('watch-test', ['jshint:dev', 'karma:unit']);
|
||||
|
||||
//triggered from grunt
|
||||
grunt.registerTask('build', ['concat', 'recess:build', 'recess:installer', 'recess:canvasdesigner', 'postcss', 'bower-install-simple', 'bower', 'copy', 'clean:post']);
|
||||
grunt.registerTask('build', ['concat', 'recess:build', 'recess:installer', 'recess:nonodes', 'recess:canvasdesigner', 'postcss', 'bower-install-simple', 'bower', 'copy', 'clean:post']);
|
||||
|
||||
//triggered from grunt dev vs or grunt vs
|
||||
grunt.registerTask('build-dev', ['clean:pre', 'concat', 'recess:build', 'recess:installer', 'postcss', 'bower-install-simple', 'bower', 'copy']);
|
||||
grunt.registerTask('build-dev', ['clean:pre', 'concat', 'recess:build', 'recess:installer', 'recess:nonodes', 'postcss', 'bower-install-simple', 'bower', 'copy']);
|
||||
|
||||
//utillity tasks
|
||||
grunt.registerTask('docs', ['ngdocs']);
|
||||
@@ -293,6 +293,16 @@ module.exports = function (grunt) {
|
||||
compress: true
|
||||
}
|
||||
},
|
||||
nonodes: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/nonodes.style.min.css':
|
||||
['src/less/pages/nonodes.less']
|
||||
},
|
||||
options: {
|
||||
compile: true,
|
||||
compress: true
|
||||
}
|
||||
},
|
||||
installer: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/installer.css':
|
||||
@@ -394,7 +404,7 @@ module.exports = function (grunt) {
|
||||
tutorials: {
|
||||
src: [],
|
||||
title: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
eslint:{
|
||||
@@ -524,7 +534,26 @@ module.exports = function (grunt) {
|
||||
'addon/selection/*',
|
||||
'addon/dialog/*'
|
||||
]
|
||||
}
|
||||
},
|
||||
'ace-builds': {
|
||||
files: [
|
||||
'src-min-noconflict/ace.js',
|
||||
|
||||
'src-min-noconflict/ext-language_tools.js',
|
||||
'src-min-noconflict/ext-searchbox.js',
|
||||
'src-min-noconflict/ext-settings_menu.js',
|
||||
|
||||
'src-min-noconflict/snippets/text.js',
|
||||
'src-min-noconflict/snippets/javascript.js',
|
||||
|
||||
'src-min-noconflict/theme-chrome.js',
|
||||
|
||||
'src-min-noconflict/mode-razor.js',
|
||||
'src-min-noconflict/mode-javascript.js',
|
||||
|
||||
'src-min-noconflict/worker-javascript.js',
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
.ace-chrome .ace_gutter {
|
||||
background: white !important;
|
||||
color: #ccc !important;
|
||||
overflow : hidden;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_print-margin {
|
||||
|
||||
}
|
||||
|
||||
.ace-chrome {
|
||||
background-color: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_cursor {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_invisible {
|
||||
color: rgb(191, 191, 191);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_constant.ace_buildin {
|
||||
color: rgb(88, 72, 246);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_constant.ace_language {
|
||||
color: rgb(88, 92, 246);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_constant.ace_library {
|
||||
color: rgb(6, 150, 14);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_invalid {
|
||||
background-color: rgb(153, 0, 0);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ace_punctuation.ace_short.ace_razor{
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_fold {
|
||||
}
|
||||
|
||||
.ace-chrome .ace_support.ace_function {
|
||||
color: rgb(60, 76, 114);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_support.ace_constant {
|
||||
color: rgb(6, 150, 14);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_support.ace_type,
|
||||
.ace-chrome .ace_support.ace_class
|
||||
.ace-chrome .ace_support.ace_other {
|
||||
color: rgb(109, 121, 222);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_variable.ace_parameter {
|
||||
font-style:italic;
|
||||
color:#FD971F;
|
||||
}
|
||||
.ace-chrome .ace_keyword.ace_operator {
|
||||
color: rgb(104, 118, 135);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_comment {
|
||||
color: #236e24;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_comment.ace_doc {
|
||||
color: #236e24;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_comment.ace_doc.ace_tag {
|
||||
color: #236e24;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_constant.ace_numeric {
|
||||
color: rgb(0, 0, 205);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_variable {
|
||||
color: rgb(49, 132, 149);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_xml-pe {
|
||||
color: rgb(104, 104, 91);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_entity.ace_name.ace_function {
|
||||
color: #0000A2;
|
||||
}
|
||||
|
||||
|
||||
.ace-chrome .ace_heading {
|
||||
color: rgb(12, 7, 255);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_list {
|
||||
color:rgb(185, 6, 144);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_marker-layer .ace_selection {
|
||||
background: rgb(181, 213, 255);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_marker-layer .ace_step {
|
||||
background: rgb(252, 255, 0);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_marker-layer .ace_stack {
|
||||
background: rgb(164, 229, 101);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_marker-layer .ace_bracket {
|
||||
margin: -1px 0 0 -1px;
|
||||
border: 1px solid rgb(192, 192, 192);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_marker-layer .ace_active-line {
|
||||
background: rgba(0, 0, 0, 0.07) !important;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_gutter-active-line {
|
||||
background: rgba(0, 0, 0, 0.07) !important;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_marker-layer .ace_selected-word {
|
||||
background: rgb(250, 250, 255);
|
||||
border: 1px solid rgb(200, 200, 250);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_storage,
|
||||
.ace-chrome .ace_keyword,
|
||||
.ace-chrome .ace_meta.ace_tag {
|
||||
color: rgb(147, 15, 128);
|
||||
}
|
||||
|
||||
.ace-chrome .ace_string.ace_regex {
|
||||
color: rgb(255, 0, 0)
|
||||
}
|
||||
|
||||
.ace-chrome .ace_string {
|
||||
color: #1A1AA6;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_entity.ace_other.ace_attribute-name {
|
||||
color: #994409;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_indent-guide {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;
|
||||
}
|
||||
|
||||
.ace-chrome .ace_razor {
|
||||
background: yellow;
|
||||
}
|
||||
@@ -172,8 +172,17 @@ tinymce.PluginManager.add('umbracolink', function(editor) {
|
||||
|
||||
//locallink detection, we do this here, to avoid poluting the dialogservice
|
||||
//so the dialog service can just expect to get a node-like structure
|
||||
if(currentTarget.url.indexOf("localLink:") > 0){
|
||||
currentTarget.id = currentTarget.url.substring(currentTarget.url.indexOf(":")+1,currentTarget.url.length-1);
|
||||
if (currentTarget.url.indexOf("localLink:") > 0) {
|
||||
var linkId = currentTarget.url.substring(currentTarget.url.indexOf(":") + 1, currentTarget.url.length - 1);
|
||||
//we need to check if this is an INT or a UDI
|
||||
var parsedIntId = parseInt(linkId, 10);
|
||||
if (isNaN(parsedIntId)) {
|
||||
//it's a UDI
|
||||
currentTarget.udi = linkId;
|
||||
}
|
||||
else {
|
||||
currentTarget.id = linkId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,27 +191,34 @@ tinymce.PluginManager.add('umbracolink', function(editor) {
|
||||
callback: function (data) {
|
||||
if (data) {
|
||||
var href = data.url;
|
||||
|
||||
// We want to use the Udi. If it is set, we use it, else fallback to id, and finally to null
|
||||
var hasUdi = data.udi ? true : false;
|
||||
var id = hasUdi ? data.udi : (data.id ? data.id : null);
|
||||
|
||||
//Create a json obj used to create the attributes for the tag
|
||||
function createElemAttributes() {
|
||||
var a = {
|
||||
href: href,
|
||||
title: data.name,
|
||||
target: data.target ? data.target : null,
|
||||
rel: data.rel ? data.rel : null
|
||||
};
|
||||
if (hasUdi) {
|
||||
a["data-udi"] = data.udi;
|
||||
}
|
||||
else if (data.id) {
|
||||
a["data-id"] = data.id;
|
||||
}
|
||||
}
|
||||
|
||||
function insertLink() {
|
||||
if (anchorElm) {
|
||||
dom.setAttribs(anchorElm, {
|
||||
href: href,
|
||||
title: data.name,
|
||||
target: data.target ? data.target : null,
|
||||
rel: data.rel ? data.rel : null,
|
||||
'data-id': data.id ? data.id : null
|
||||
});
|
||||
dom.setAttribs(anchorElm, createElemAttributes());
|
||||
|
||||
selection.select(anchorElm);
|
||||
editor.execCommand('mceEndTyping');
|
||||
} else {
|
||||
editor.execCommand('mceInsertLink', false, {
|
||||
href: href,
|
||||
title: data.name,
|
||||
target: data.target ? data.target : null,
|
||||
rel: data.rel ? data.rel : null,
|
||||
'data-id': data.id ? data.id : null
|
||||
});
|
||||
editor.execCommand('mceInsertLink', false, createElemAttributes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,9 +228,11 @@ tinymce.PluginManager.add('umbracolink', function(editor) {
|
||||
}
|
||||
|
||||
//if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set
|
||||
if(data.id && (angular.isUndefined(data.isMedia) || !data.isMedia)){
|
||||
href = "/{localLink:" + data.id + "}";
|
||||
insertLink();
|
||||
if (id && (angular.isUndefined(data.isMedia) || !data.isMedia)){
|
||||
|
||||
href = "/{localLink:" + id + "}";
|
||||
|
||||
insertLink();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
body.mce-content-body {
|
||||
background-color: #fff;
|
||||
font-family: Verdana,Arial,Helvetica,sans-serif;
|
||||
font-size: 11px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5em;
|
||||
scrollbar-3dlight-color: #f0f0ee;
|
||||
scrollbar-arrow-color: #676662;
|
||||
scrollbar-base-color: #f0f0ee;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('../fonts/opensans/OpenSans-Regular-webfont.eot');
|
||||
src: local('Open Sans'), local('OpenSans'), url('../fonts/opensans/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), url('../fonts/opensans/OpenSans-Regular-webfont.ttf') format('truetype'), url('../fonts/opensans/OpenSans-Regular-webfont.svg#open_sansregular') format('svg');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url('../fonts/opensans/OpenSans-Semibold-webfont.eot');
|
||||
src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url('../fonts/opensans/OpenSans-Semibold-webfont.eot?#iefix') format('embedded-opentype'), url('../fonts/opensans/OpenSans-Semibold-webfont.ttf') format('truetype'), url('../fonts/opensans/OpenSans-Semibold-webfont.svg#open_sanssemibold') format('svg');
|
||||
}
|
||||
|
||||
abbr,address,article,aside,audio,b,blockquote,body,canvas,caption,cite,code,dd,del,details,dfn,div,dl,dt,em,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,samp,section,small,span,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,ul,var,video{margin:0;padding:0;outline:0;border:0;background:0 0;vertical-align:baseline;font-size:100%}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}nav ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:'';content:none}a{margin:0;padding:0;background:0 0;vertical-align:baseline;font-size:100%}ins{background-color:#ff9;color:#000;text-decoration:none}mark{background-color:#ff9;color:#000;font-weight:700;font-style:italic}del{text-decoration:line-through}abbr[title],dfn[title]{border-bottom:1px dotted;cursor:help}table{border-spacing:0;border-collapse:collapse}hr{display:block;margin:1em 0;padding:0;height:1px;border:0;border-top:1px solid #ccc}input,select{vertical-align:middle}html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{height:100%;width:100%;color:#fff;font-family:'Open Sans',sans-serif;font-weight:400;font-size:.9375em;line-height:1.5}h1{font-size:1.7em;margin:40px auto 10px;font-weight:700}h2{font-size:1.35em;margin:0 auto .4em;font-weight:700}h3{font-size:1em;font-weight:400;font-style:italic}p{font-size:1em;line-height:1.6}p+a{margin-top:1rem;display:inline-block}a,a:active,a:visited{text-decoration:none}.cta{margin:4.5em auto 1.5em;padding-bottom:4.5em}.button,.button:visited{padding:.9375em 1.875em;border-radius:.1em;font-weight:600;font-size:1.2em;background:#2e99f4;color:#fff;display:inline-block;border:none;transition:all 200ms ease-in-out}.button:hover,.button:visited:hover{border-bottom:none;background:#0c80e3}section{background:url(../img/nonodesbg.jpg) center center/cover;height:100%;width:100%;display:table;padding:3em 1.75em}section a,section a:focus,section a:visited{color:#46a5f5;font-size:1.1625em;border-bottom:1px solid transparent;transition:border-bottom 100ms ease-in-out}section a:focus:hover,section a:hover,section a:visited:hover{border-bottom:1px solid}section:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.17);background:linear-gradient(45deg,rgba(85,98,112,.1) 10%,rgba(255,107,107,.1) 95%);z-index:0}section article{display:table-cell;vertical-align:middle;margin:0 auto;text-align:center;position:relative;z-index:100}section article>div{max-width:60em;margin:0 auto}section .logo{background:url(../img/logo.png) no-repeat;width:91px;height:91px;margin:0 auto}section .row{overflow:hidden}section .row .col{text-align:left;width:100%}section .row .col:nth-child(2){margin-top:3em}@media screen and (min-width:48em){body,html{font-size:1em}h1{font-size:2.5em;margin:70px auto 0;letter-spacing:.5px}h2{font-size:1.4375em;margin:0 auto 1em}h3{font-size:1.2em}a{font-size:1.1rem;font-weight:600}p+a{margin-top:3rem}.cta{margin:7.5em auto 2.5em;border-bottom:1px solid rgba(255,255,255,.5);padding-bottom:7.5em}section{padding:0 15px}section .row .col{float:left;width:50%;padding-right:5%;display:inline-block}section .row .col:nth-child(2){padding-right:0;padding-left:5%;margin-top:0}.button{font-size:1.1625em}}
|
||||
|
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 298 KiB After Width: | Height: | Size: 273 KiB |
@@ -20,7 +20,10 @@
|
||||
<div class="fix-left-menu selected">
|
||||
|
||||
<div class="avatar">
|
||||
<img ng-src="../assets/img/application/logo.png">
|
||||
<img
|
||||
ng-src="../assets/img/application/logo.png"
|
||||
ng-srcset="../assets/img/application/logo@2x.png 2x,
|
||||
../assets/img/application/logo@3x.png 3x" />
|
||||
</div>
|
||||
|
||||
<ul class="sections" ng-class="{selected: showDevicesPreview}">
|
||||
|
||||
@@ -40,27 +40,50 @@ Use this directive to generate a list of breadcrumbs.
|
||||
|
||||
@param {array} ancestors Array of ancestors
|
||||
@param {string} entityType The content entity type (member, media, content).
|
||||
@param {callback} Callback when an ancestor is clicked. It will override the default link behaviour.
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function BreadcrumbsDirective() {
|
||||
function BreadcrumbsDirective() {
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/editor/umb-breadcrumbs.html',
|
||||
scope: {
|
||||
ancestors: "=",
|
||||
entityType: "@"
|
||||
}
|
||||
};
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
return directive;
|
||||
scope.allowOnOpen = false;
|
||||
|
||||
}
|
||||
scope.open = function(ancestor) {
|
||||
if(scope.onOpen && scope.allowOnOpen) {
|
||||
scope.onOpen({'ancestor': ancestor});
|
||||
}
|
||||
};
|
||||
|
||||
angular.module('umbraco.directives').directive('umbBreadcrumbs', BreadcrumbsDirective);
|
||||
function onInit() {
|
||||
if ("onOpen" in attr) {
|
||||
scope.allowOnOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
onInit();
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/editor/umb-breadcrumbs.html',
|
||||
scope: {
|
||||
ancestors: "=",
|
||||
entityType: "@",
|
||||
onOpen: "&"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbBreadcrumbs', BreadcrumbsDirective);
|
||||
|
||||
})();
|
||||
|
||||
@@ -254,6 +254,7 @@ Use this directive to construct a header inside the main editor window.
|
||||
hideAlias: "@",
|
||||
description: "=",
|
||||
hideDescription: "@",
|
||||
descriptionLocked: "@",
|
||||
navigation: "="
|
||||
},
|
||||
link: link
|
||||
|
||||
@@ -163,13 +163,13 @@ angular.module('umbraco.directives')
|
||||
}
|
||||
|
||||
// ignore clicks on dialog from old dialog service
|
||||
var oldDialog = $(el).parents("#old-dialog-service");
|
||||
var oldDialog = $(event.target).parents("#old-dialog-service");
|
||||
if (oldDialog.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore clicks in tinyMCE dropdown(floatpanel)
|
||||
var floatpanel = $(el).parents(".mce-floatpanel");
|
||||
var floatpanel = $(event.target).closest(".mce-floatpanel");
|
||||
if (floatpanel.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,12 +105,14 @@ angular.module("umbraco.directives")
|
||||
});
|
||||
|
||||
//// INIT /////
|
||||
$image.load(function(){
|
||||
$timeout(function(){
|
||||
setDimensions();
|
||||
scope.loaded = true;
|
||||
scope.onImageLoaded();
|
||||
});
|
||||
$image.load(function() {
|
||||
$timeout(function() {
|
||||
setDimensions();
|
||||
scope.loaded = true;
|
||||
if (angular.isFunction(scope.onImageLoaded)) {
|
||||
scope.onImageLoaded();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(window).on('resize.umbImageGravity', function(){
|
||||
|
||||
@@ -5,7 +5,27 @@ angular.module("umbraco.directives")
|
||||
* @name umbraco.directives.directive:localize
|
||||
* @restrict EA
|
||||
* @function
|
||||
* @description Localize directive
|
||||
* @description
|
||||
* <div>
|
||||
* <strong>Component</strong><br />
|
||||
* Localize a specific token to put into the HTML as an item
|
||||
* </div>
|
||||
* <div>
|
||||
* <strong>Attribute</strong><br />
|
||||
* Add a HTML attribute to an element containing the HTML attribute name you wish to localise
|
||||
* Using the format of '@section_key' or 'section_key'
|
||||
* </div>
|
||||
* ##Usage
|
||||
* <pre>
|
||||
* <!-- Component -->
|
||||
* <localize key="general_close">Close</localize>
|
||||
* <localize key="section_key">Fallback value</localize>
|
||||
*
|
||||
* <!-- Attribute -->
|
||||
* <input type="text" localize="placeholder" placeholder="@placeholders_entername" />
|
||||
* <input type="text" localize="placeholder,title" title="@section_key" placeholder="@placeholders_entername" />
|
||||
* <div localize="title" title="@section_key"></div>
|
||||
* </pre>
|
||||
**/
|
||||
.directive('localize', function ($log, localizationService) {
|
||||
return {
|
||||
@@ -28,6 +48,7 @@ angular.module("umbraco.directives")
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function (scope, element, attrs) {
|
||||
//Support one or more attribute properties to update
|
||||
var keys = attrs.localize.split(',');
|
||||
|
||||
angular.forEach(keys, function(value, key){
|
||||
@@ -35,13 +56,15 @@ angular.module("umbraco.directives")
|
||||
|
||||
if(attr){
|
||||
if(attr[0] === '@'){
|
||||
|
||||
var t = localizationService.tokenize(attr.substring(1), scope);
|
||||
localizationService.localize(t.key, t.tokens).then(function(val){
|
||||
element.attr(value, val);
|
||||
});
|
||||
|
||||
//If the translation key starts with @ then remove it
|
||||
attr = attr.substring(1);
|
||||
}
|
||||
|
||||
var t = localizationService.tokenize(attr, scope);
|
||||
|
||||
localizationService.localize(t.key, t.tokens).then(function(val){
|
||||
element.attr(value, val);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -478,8 +478,10 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
|
||||
numberOfOverlays = overlayHelper.getNumberOfOverlays();
|
||||
|
||||
if(numberOfOverlays === overlayNumber) {
|
||||
scope.closeOverLay();
|
||||
if (numberOfOverlays === overlayNumber) {
|
||||
scope.$apply(function () {
|
||||
scope.closeOverLay();
|
||||
});
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
@@ -43,7 +43,8 @@
|
||||
templateUrl: "views/components/tabs/umb-tabs-nav.html",
|
||||
scope: {
|
||||
model: "=",
|
||||
tabdrop: "="
|
||||
tabdrop: "=",
|
||||
idSuffix: "@"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -17,11 +17,13 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
hideheader: '@',
|
||||
cachekey: '@',
|
||||
isdialog: '@',
|
||||
onlyinitialized: '@',
|
||||
//Custom query string arguments to pass in to the tree as a string, example: "startnodeid=123&something=value"
|
||||
customtreeparams: '@',
|
||||
eventhandler: '=',
|
||||
enablecheckboxes: '@',
|
||||
enablelistviewsearch: '@'
|
||||
enablelistviewsearch: '@',
|
||||
enablelistviewexpand: '@'
|
||||
},
|
||||
|
||||
compile: function(element, attrs) {
|
||||
@@ -35,7 +37,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
'<a class="umb-options" ng-hide="tree.root.isContainer || !tree.root.menuUrl" ng-click="options(tree.root, $event)" ng-swipe-right="options(tree.root, $event)"><i></i><i></i><i></i></a>' +
|
||||
'</div>';
|
||||
template += '<ul>' +
|
||||
'<umb-tree-item ng-repeat="child in tree.root.children" eventhandler="eventhandler" node="child" current-node="currentNode" tree="this" section="{{section}}" ng-animate="animation()"></umb-tree-item>' +
|
||||
'<umb-tree-item ng-repeat="child in tree.root.children" enablelistviewexpand="{{enablelistviewexpand}}" eventhandler="eventhandler" node="child" current-node="currentNode" tree="this" section="{{section}}" ng-animate="animation()"></umb-tree-item>' +
|
||||
'</ul>' +
|
||||
'</li>' +
|
||||
'</ul>';
|
||||
@@ -251,7 +253,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
deleteAnimations = false;
|
||||
|
||||
//default args
|
||||
var args = { section: scope.section, tree: scope.treealias, cacheKey: scope.cachekey, isDialog: scope.isdialog ? scope.isdialog : false };
|
||||
var args = { section: scope.section, tree: scope.treealias, cacheKey: scope.cachekey, isDialog: scope.isdialog ? scope.isdialog : false, onlyinitialized: scope.onlyinitialized };
|
||||
|
||||
//add the extra query string params if specified
|
||||
if (scope.customtreeparams) {
|
||||
@@ -304,7 +306,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
scope.selectEnabledNodeClass = function (node) {
|
||||
return node ?
|
||||
node.selected ?
|
||||
'icon umb-tree-icon sprTree icon-check blue temporary' :
|
||||
'icon umb-tree-icon sprTree icon-check green temporary' :
|
||||
'' :
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@ angular.module("umbraco.directives")
|
||||
section: '@',
|
||||
eventhandler: '=',
|
||||
currentNode: '=',
|
||||
enablelistviewexpand: '@',
|
||||
node: '=',
|
||||
tree: '='
|
||||
},
|
||||
@@ -38,7 +39,7 @@ angular.module("umbraco.directives")
|
||||
'<div ng-class="getNodeCssClass(node)" ng-swipe-right="options(node, $event)" >' +
|
||||
//NOTE: This ins element is used to display the search icon if the node is a container/listview and the tree is currently in dialog
|
||||
//'<ins ng-if="tree.enablelistviewsearch && node.metaData.isContainer" class="umb-tree-node-search icon-search" ng-click="searchNode(node, $event)" alt="searchAltText"></ins>' +
|
||||
'<ins ng-class="{\'icon-navigation-right\': !node.expanded, \'icon-navigation-down\': node.expanded}" ng-click="load(node)"> </ins>' +
|
||||
'<ins ng-class="{\'icon-navigation-right\': !node.expanded || node.metaData.isContainer, \'icon-navigation-down\': node.expanded && !node.metaData.isContainer}" ng-click="load(node)"> </ins>' +
|
||||
'<i class="icon umb-tree-icon sprTree" ng-click="select(node, $event)"></i>' +
|
||||
'<a href="#/{{node.routePath}}" ng-click="select(node, $event)"></a>' +
|
||||
//NOTE: These are the 'option' elipses
|
||||
@@ -74,11 +75,12 @@ angular.module("umbraco.directives")
|
||||
|
||||
//toggle visibility of last 'ins' depending on children
|
||||
//visibility still ensure the space is "reserved", so both nodes with and without children are aligned.
|
||||
if (!node.hasChildren) {
|
||||
element.find("ins").last().css("visibility", "hidden");
|
||||
|
||||
if (node.hasChildren || node.metaData.isContainer && scope.enablelistviewexpand === "true") {
|
||||
element.find("ins").last().css("visibility", "visible");
|
||||
}
|
||||
else {
|
||||
element.find("ins").last().css("visibility", "visible");
|
||||
element.find("ins").last().css("visibility", "hidden");
|
||||
}
|
||||
|
||||
var icon = element.find("i:first");
|
||||
@@ -192,7 +194,7 @@ angular.module("umbraco.directives")
|
||||
emits treeNodeCollapsing event if already expanded and treeNodeExpanding if collapsed
|
||||
*/
|
||||
scope.load = function (node) {
|
||||
if (node.expanded) {
|
||||
if (node.expanded && !node.metaData.isContainer) {
|
||||
deleteAnimations = false;
|
||||
emitEvent("treeNodeCollapsing", { tree: scope.tree, node: node, element: element });
|
||||
node.expanded = false;
|
||||
@@ -227,7 +229,7 @@ angular.module("umbraco.directives")
|
||||
|
||||
setupNodeDom(scope.node, scope.tree);
|
||||
|
||||
var template = '<ul ng-class="{collapsed: !node.expanded}"><umb-tree-item ng-repeat="child in node.children" eventhandler="eventhandler" tree="tree" current-node="currentNode" node="child" section="{{section}}" ng-animate="animation()"></umb-tree-item></ul>';
|
||||
var template = '<ul ng-class="{collapsed: !node.expanded}"><umb-tree-item ng-repeat="child in node.children" enablelistviewexpand="{{enablelistviewexpand}}" eventhandler="eventhandler" tree="tree" current-node="currentNode" node="child" section="{{section}}" ng-animate="animation()"></umb-tree-item></ul>';
|
||||
var newElement = angular.element(template);
|
||||
$compile(newElement)(scope);
|
||||
element.append(newElement);
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function AceEditorDirective(umbAceEditorConfig, assetsService, angularHelper) {
|
||||
|
||||
/**
|
||||
* Sets editor options such as the wrapping mode or the syntax checker.
|
||||
*
|
||||
* The supported options are:
|
||||
*
|
||||
* <ul>
|
||||
* <li>showGutter</li>
|
||||
* <li>useWrapMode</li>
|
||||
* <li>onLoad</li>
|
||||
* <li>theme</li>
|
||||
* <li>mode</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param acee
|
||||
* @param session ACE editor session
|
||||
* @param {object} opts Options to be set
|
||||
*/
|
||||
var setOptions = function(acee, session, opts) {
|
||||
|
||||
// sets the ace worker path, if running from concatenated
|
||||
// or minified source
|
||||
if (angular.isDefined(opts.workerPath)) {
|
||||
var config = window.ace.require('ace/config');
|
||||
config.set('workerPath', opts.workerPath);
|
||||
}
|
||||
|
||||
// ace requires loading
|
||||
if (angular.isDefined(opts.require)) {
|
||||
opts.require.forEach(function(n) {
|
||||
window.ace.require(n);
|
||||
});
|
||||
}
|
||||
|
||||
// Boolean options
|
||||
if (angular.isDefined(opts.showGutter)) {
|
||||
acee.renderer.setShowGutter(opts.showGutter);
|
||||
}
|
||||
if (angular.isDefined(opts.useWrapMode)) {
|
||||
session.setUseWrapMode(opts.useWrapMode);
|
||||
}
|
||||
if (angular.isDefined(opts.showInvisibles)) {
|
||||
acee.renderer.setShowInvisibles(opts.showInvisibles);
|
||||
}
|
||||
if (angular.isDefined(opts.showIndentGuides)) {
|
||||
acee.renderer.setDisplayIndentGuides(opts.showIndentGuides);
|
||||
}
|
||||
if (angular.isDefined(opts.useSoftTabs)) {
|
||||
session.setUseSoftTabs(opts.useSoftTabs);
|
||||
}
|
||||
if (angular.isDefined(opts.showPrintMargin)) {
|
||||
acee.setShowPrintMargin(opts.showPrintMargin);
|
||||
}
|
||||
|
||||
// commands
|
||||
if (angular.isDefined(opts.disableSearch) && opts.disableSearch) {
|
||||
acee.commands.addCommands([{
|
||||
name: 'unfind',
|
||||
bindKey: {
|
||||
win: 'Ctrl-F',
|
||||
mac: 'Command-F'
|
||||
},
|
||||
exec: function() {
|
||||
return false;
|
||||
},
|
||||
readOnly: true
|
||||
}]);
|
||||
}
|
||||
|
||||
// Basic options
|
||||
if (angular.isString(opts.theme)) {
|
||||
acee.setTheme('ace/theme/' + opts.theme);
|
||||
}
|
||||
if (angular.isString(opts.mode)) {
|
||||
session.setMode('ace/mode/' + opts.mode);
|
||||
}
|
||||
// Advanced options
|
||||
if (angular.isDefined(opts.firstLineNumber)) {
|
||||
if (angular.isNumber(opts.firstLineNumber)) {
|
||||
session.setOption('firstLineNumber', opts.firstLineNumber);
|
||||
} else if (angular.isFunction(opts.firstLineNumber)) {
|
||||
session.setOption('firstLineNumber', opts.firstLineNumber());
|
||||
}
|
||||
}
|
||||
|
||||
// advanced options
|
||||
var key, obj;
|
||||
if (angular.isDefined(opts.advanced)) {
|
||||
for (key in opts.advanced) {
|
||||
// create a javascript object with the key and value
|
||||
obj = {
|
||||
name: key,
|
||||
value: opts.advanced[key]
|
||||
};
|
||||
// try to assign the option to the ace editor
|
||||
acee.setOption(obj.name, obj.value);
|
||||
}
|
||||
}
|
||||
|
||||
// advanced options for the renderer
|
||||
if (angular.isDefined(opts.rendererOptions)) {
|
||||
for (key in opts.rendererOptions) {
|
||||
// create a javascript object with the key and value
|
||||
obj = {
|
||||
name: key,
|
||||
value: opts.rendererOptions[key]
|
||||
};
|
||||
// try to assign the option to the ace editor
|
||||
acee.renderer.setOption(obj.name, obj.value);
|
||||
}
|
||||
}
|
||||
|
||||
// onLoad callbacks
|
||||
angular.forEach(opts.callbacks, function(cb) {
|
||||
if (angular.isFunction(cb)) {
|
||||
cb(acee);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function link(scope, el, attr, ngModel) {
|
||||
|
||||
// Load in ace library
|
||||
assetsService.load(['lib/ace-builds/src-min-noconflict/ace.js', 'lib/ace-builds/src-min-noconflict/ext-language_tools.js']).then(function () {
|
||||
if (angular.isUndefined(window.ace)) {
|
||||
throw new Error('ui-ace need ace to work... (o rly?)');
|
||||
} else {
|
||||
// init editor
|
||||
init();
|
||||
}
|
||||
});
|
||||
|
||||
function init() {
|
||||
|
||||
/**
|
||||
* Corresponds the umbAceEditorConfig ACE configuration.
|
||||
* @type object
|
||||
*/
|
||||
var options = umbAceEditorConfig.ace || {};
|
||||
|
||||
/**
|
||||
* umbAceEditorConfig merged with user options via json in attribute or data binding
|
||||
* @type object
|
||||
*/
|
||||
var opts = angular.extend({}, options, scope.umbAceEditor);
|
||||
|
||||
|
||||
//load ace libraries here...
|
||||
|
||||
/**
|
||||
* ACE editor
|
||||
* @type object
|
||||
*/
|
||||
var acee = window.ace.edit(el[0]);
|
||||
acee.$blockScrolling = Infinity;
|
||||
|
||||
/**
|
||||
* ACE editor session.
|
||||
* @type object
|
||||
* @see [EditSession]{@link http://ace.c9.io/#nav=api&api=edit_session}
|
||||
*/
|
||||
var session = acee.getSession();
|
||||
|
||||
/**
|
||||
* Reference to a change listener created by the listener factory.
|
||||
* @function
|
||||
* @see listenerFactory.onChange
|
||||
*/
|
||||
var onChangeListener;
|
||||
|
||||
/**
|
||||
* Reference to a blur listener created by the listener factory.
|
||||
* @function
|
||||
* @see listenerFactory.onBlur
|
||||
*/
|
||||
var onBlurListener;
|
||||
|
||||
/**
|
||||
* Calls a callback by checking its existing. The argument list
|
||||
* is variable and thus this function is relying on the arguments
|
||||
* object.
|
||||
* @throws {Error} If the callback isn't a function
|
||||
*/
|
||||
var executeUserCallback = function() {
|
||||
|
||||
/**
|
||||
* The callback function grabbed from the array-like arguments
|
||||
* object. The first argument should always be the callback.
|
||||
*
|
||||
* @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments}
|
||||
* @type {*}
|
||||
*/
|
||||
var callback = arguments[0];
|
||||
|
||||
/**
|
||||
* Arguments to be passed to the callback. These are taken
|
||||
* from the array-like arguments object. The first argument
|
||||
* is stripped because that should be the callback function.
|
||||
*
|
||||
* @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments}
|
||||
* @type {Array}
|
||||
*/
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
if (angular.isDefined(callback)) {
|
||||
scope.$evalAsync(function() {
|
||||
if (angular.isFunction(callback)) {
|
||||
callback(args);
|
||||
} else {
|
||||
throw new Error('ui-ace use a function as callback.');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Listener factory. Until now only change listeners can be created.
|
||||
* @type object
|
||||
*/
|
||||
var listenerFactory = {
|
||||
/**
|
||||
* Creates a change listener which propagates the change event
|
||||
* and the editor session to the callback from the user option
|
||||
* onChange. It might be exchanged during runtime, if this
|
||||
* happens the old listener will be unbound.
|
||||
*
|
||||
* @param callback callback function defined in the user options
|
||||
* @see onChangeListener
|
||||
*/
|
||||
onChange: function(callback) {
|
||||
return function(e) {
|
||||
var newValue = session.getValue();
|
||||
angularHelper.safeApply(scope, function () {
|
||||
scope.model = newValue;
|
||||
});
|
||||
executeUserCallback(callback, e, acee);
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Creates a blur listener which propagates the editor session
|
||||
* to the callback from the user option onBlur. It might be
|
||||
* exchanged during runtime, if this happens the old listener
|
||||
* will be unbound.
|
||||
*
|
||||
* @param callback callback function defined in the user options
|
||||
* @see onBlurListener
|
||||
*/
|
||||
onBlur: function(callback) {
|
||||
return function() {
|
||||
executeUserCallback(callback, acee);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
attr.$observe('readonly', function(value) {
|
||||
acee.setReadOnly(!!value || value === '');
|
||||
});
|
||||
|
||||
// Value Blind
|
||||
if(scope.model) {
|
||||
session.setValue(scope.model);
|
||||
}
|
||||
|
||||
// Listen for option updates
|
||||
var updateOptions = function(current, previous) {
|
||||
if (current === previous) {
|
||||
return;
|
||||
}
|
||||
|
||||
opts = angular.extend({}, options, scope.umbAceEditor);
|
||||
|
||||
opts.callbacks = [opts.onLoad];
|
||||
if (opts.onLoad !== options.onLoad) {
|
||||
// also call the global onLoad handler
|
||||
opts.callbacks.unshift(options.onLoad);
|
||||
}
|
||||
|
||||
// EVENTS
|
||||
|
||||
// unbind old change listener
|
||||
session.removeListener('change', onChangeListener);
|
||||
|
||||
// bind new change listener
|
||||
onChangeListener = listenerFactory.onChange(opts.onChange);
|
||||
session.on('change', onChangeListener);
|
||||
|
||||
// unbind old blur listener
|
||||
//session.removeListener('blur', onBlurListener);
|
||||
acee.removeListener('blur', onBlurListener);
|
||||
|
||||
// bind new blur listener
|
||||
onBlurListener = listenerFactory.onBlur(opts.onBlur);
|
||||
acee.on('blur', onBlurListener);
|
||||
|
||||
setOptions(acee, session, opts);
|
||||
};
|
||||
|
||||
scope.$watch(scope.umbAceEditor, updateOptions, /* deep watch */ true);
|
||||
|
||||
// set the options here, even if we try to watch later, if this
|
||||
// line is missing things go wrong (and the tests will also fail)
|
||||
updateOptions(options);
|
||||
|
||||
el.on('$destroy', function() {
|
||||
acee.session.$stopWorker();
|
||||
acee.destroy();
|
||||
});
|
||||
|
||||
scope.$watch(function() {
|
||||
return [el[0].offsetWidth, el[0].offsetHeight];
|
||||
}, function() {
|
||||
acee.resize();
|
||||
acee.renderer.updateFull();
|
||||
}, true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'EA',
|
||||
scope: {
|
||||
"umbAceEditor": "=",
|
||||
"model": "="
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives')
|
||||
.constant('umbAceEditorConfig', {})
|
||||
.directive('umbAceEditor', AceEditorDirective);
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbDateTimePicker
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
<b>Added in Umbraco version 7.6</b>
|
||||
This directive is a wrapper of the bootstrap datetime picker version 3.1.3. Use it to render a date time picker.
|
||||
For extra details about options and events take a look here: http://eonasdan.github.io/bootstrap-datetimepicker/
|
||||
|
||||
Use this directive to render a date time picker
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-date-time-picker
|
||||
options="vm.config"
|
||||
on-change="vm.datePickerChange(event)"
|
||||
on-error="vm.datePickerError(event)">
|
||||
</umb-date-time-picker>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.date = "";
|
||||
|
||||
vm.config = {
|
||||
pickDate: true,
|
||||
pickTime: true,
|
||||
useSeconds: true,
|
||||
format: "YYYY-MM-DD HH:mm:ss",
|
||||
icons: {
|
||||
time: "icon-time",
|
||||
date: "icon-calendar",
|
||||
up: "icon-chevron-up",
|
||||
down: "icon-chevron-down"
|
||||
}
|
||||
};
|
||||
|
||||
vm.datePickerChange = datePickerChange;
|
||||
vm.datePickerError = datePickerError;
|
||||
|
||||
function datePickerChange(event) {
|
||||
// handle change
|
||||
if(event.date && event.date.isValid()) {
|
||||
var date = event.date.format(vm.datePickerConfig.format);
|
||||
}
|
||||
}
|
||||
|
||||
function datePickerError(event) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {object} options (<code>binding</code>): Config object for the date picker.
|
||||
@param {callback} onHide (<code>callback</code>): Hide callback.
|
||||
@param {callback} onShow (<code>callback</code>): Show callback.
|
||||
@param {callback} onChange (<code>callback</code>): Change callback.
|
||||
@param {callback} onError (<code>callback</code>): Error callback.
|
||||
@param {callback} onUpdate (<code>callback</code>): Update callback.
|
||||
**/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function DateTimePickerDirective(assetsService) {
|
||||
|
||||
function link(scope, element, attrs, ctrl) {
|
||||
|
||||
function onInit() {
|
||||
// load css file for the date picker
|
||||
assetsService.loadCss('lib/datetimepicker/bootstrap-datetimepicker.min.css');
|
||||
|
||||
// load the js file for the date picker
|
||||
assetsService.loadJs('lib/datetimepicker/bootstrap-datetimepicker.js').then(function () {
|
||||
// init date picker
|
||||
initDatePicker();
|
||||
});
|
||||
}
|
||||
|
||||
function onHide(event) {
|
||||
if (scope.onHide) {
|
||||
scope.$apply(function(){
|
||||
// callback
|
||||
scope.onHide({event: event});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onShow() {
|
||||
if (scope.onShow) {
|
||||
scope.$apply(function(){
|
||||
// callback
|
||||
scope.onShow();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onChange(event) {
|
||||
if (scope.onChange && event.date && event.date.isValid()) {
|
||||
scope.$apply(function(){
|
||||
// callback
|
||||
scope.onChange({event: event});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onError(event) {
|
||||
if (scope.onError) {
|
||||
scope.$apply(function(){
|
||||
// callback
|
||||
scope.onError({event:event});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onUpdate(event) {
|
||||
if (scope.onUpdate) {
|
||||
scope.$apply(function(){
|
||||
// callback
|
||||
scope.onUpdate({event: event});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function initDatePicker() {
|
||||
// Open the datepicker and add a changeDate eventlistener
|
||||
element
|
||||
.datetimepicker(scope.options)
|
||||
.on("dp.hide", onHide)
|
||||
.on("dp.show", onShow)
|
||||
.on("dp.change", onChange)
|
||||
.on("dp.error", onError)
|
||||
.on("dp.update", onUpdate);
|
||||
}
|
||||
|
||||
onInit();
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-date-time-picker.html',
|
||||
scope: {
|
||||
options: "=",
|
||||
onHide: "&",
|
||||
onShow: "&",
|
||||
onChange: "&",
|
||||
onError: "&",
|
||||
onUpdate: "&"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbDateTimePicker', DateTimePickerDirective);
|
||||
|
||||
})();
|
||||
@@ -87,7 +87,8 @@ Use this directive to generate a list of folders presented as a flexbox grid.
|
||||
|
||||
scope.clickFolder = function(folder, $event, $index) {
|
||||
if(scope.onClick) {
|
||||
scope.onClick(folder, $event, $index);
|
||||
scope.onClick(folder, $event, $index);
|
||||
$event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -107,34 +107,76 @@ When this combination is hit an overview is opened with shortcuts based on the m
|
||||
@param {object} model keyboard shortcut model. See description and example above.
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function KeyboardShortcutsOverviewDirective() {
|
||||
function KeyboardShortcutsOverviewDirective(platformService) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.shortcutOverlay = false;
|
||||
var eventBindings = [];
|
||||
var isMac = platformService.isMac();
|
||||
|
||||
scope.toggleShortcutsOverlay = function() {
|
||||
scope.shortcutOverlay = !scope.shortcutOverlay;
|
||||
};
|
||||
scope.toggleShortcutsOverlay = function () {
|
||||
scope.showOverlay = !scope.showOverlay;
|
||||
scope.onToggle();
|
||||
};
|
||||
|
||||
function onInit() {
|
||||
|
||||
angular.forEach(scope.model, function (shortcutGroup) {
|
||||
angular.forEach(shortcutGroup.shortcuts, function (shortcut) {
|
||||
|
||||
shortcut.platformKeys = [];
|
||||
|
||||
// get shortcut keys for mac
|
||||
if (isMac && shortcut.keys && shortcut.keys.mac) {
|
||||
shortcut.platformKeys = shortcut.keys.mac;
|
||||
// get shortcut keys for windows
|
||||
} else if (!isMac && shortcut.keys && shortcut.keys.win) {
|
||||
shortcut.platformKeys = shortcut.keys.win;
|
||||
// get default shortcut keys
|
||||
} else if (shortcut.keys && shortcut && shortcut.keys.length > 0) {
|
||||
shortcut.platformKeys = shortcut.keys;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onInit();
|
||||
|
||||
eventBindings.push(scope.$watch('model', function(newValue, oldValue){
|
||||
if (newValue !== oldValue) {
|
||||
onInit();
|
||||
}
|
||||
}));
|
||||
|
||||
// clean up
|
||||
scope.$on('$destroy', function () {
|
||||
// unbind watchers
|
||||
for (var e in eventBindings) {
|
||||
eventBindings[e]();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-keyboard-shortcuts-overview.html',
|
||||
link: link,
|
||||
scope: {
|
||||
model: "=",
|
||||
onToggle: "&",
|
||||
showOverlay: "=?"
|
||||
}
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-keyboard-shortcuts-overview.html',
|
||||
link: link,
|
||||
scope: {
|
||||
model: "="
|
||||
}
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbKeyboardShortcutsOverview', KeyboardShortcutsOverviewDirective);
|
||||
angular.module('umbraco.directives').directive('umbKeyboardShortcutsOverview', KeyboardShortcutsOverviewDirective);
|
||||
|
||||
})();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Used on a button to launch a mini content editor editor dialog
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbLaunchMiniEditor', function (dialogService, editorState, fileManager, contentEditingHelper) {
|
||||
.directive('umbLaunchMiniEditor', function (miniEditorHelper) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
replace: false,
|
||||
@@ -16,69 +16,8 @@ angular.module("umbraco.directives")
|
||||
},
|
||||
link: function(scope, element, attrs) {
|
||||
|
||||
var launched = false;
|
||||
|
||||
element.click(function() {
|
||||
|
||||
if (launched === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
launched = true;
|
||||
|
||||
//We need to store the current files selected in the file manager locally because the fileManager
|
||||
// is a singleton and is shared globally. The mini dialog will also be referencing the fileManager
|
||||
// and we don't want it to be sharing the same files as the main editor. So we'll store the current files locally here,
|
||||
// clear them out and then launch the dialog. When the dialog closes, we'll reset the fileManager to it's previous state.
|
||||
var currFiles = _.groupBy(fileManager.getFiles(), "alias");
|
||||
fileManager.clearFiles();
|
||||
|
||||
//We need to store the original editorState entity because it will need to change when the mini editor is loaded so that
|
||||
// any property editors that are working with editorState get given the correct entity, otherwise strange things will
|
||||
// start happening.
|
||||
var currEditorState = editorState.getCurrent();
|
||||
|
||||
dialogService.open({
|
||||
template: "views/common/dialogs/content/edit.html",
|
||||
id: scope.node.id,
|
||||
closeOnSave: true,
|
||||
tabFilter: ["Generic properties"],
|
||||
callback: function (data) {
|
||||
|
||||
//set the node name back
|
||||
scope.node.name = data.name;
|
||||
|
||||
//reset the fileManager to what it was
|
||||
fileManager.clearFiles();
|
||||
_.each(currFiles, function (val, key) {
|
||||
fileManager.setFiles(key, _.map(currFiles['upload'], function (i) { return i.file; }));
|
||||
});
|
||||
|
||||
//reset the editor state
|
||||
editorState.set(currEditorState);
|
||||
|
||||
//Now we need to check if the content item that was edited was actually the same content item
|
||||
// as the main content editor and if so, update all property data
|
||||
if (data.id === currEditorState.id) {
|
||||
var changed = contentEditingHelper.reBindChangedProperties(currEditorState, data);
|
||||
}
|
||||
|
||||
launched = false;
|
||||
},
|
||||
closeCallback: function () {
|
||||
//reset the fileManager to what it was
|
||||
fileManager.clearFiles();
|
||||
_.each(currFiles, function (val, key) {
|
||||
fileManager.setFiles(key, _.map(currFiles['upload'], function (i) { return i.file; }));
|
||||
});
|
||||
|
||||
//reset the editor state
|
||||
editorState.set(currEditorState);
|
||||
|
||||
launched = false;
|
||||
}
|
||||
});
|
||||
|
||||
miniEditorHelper.launchMiniEditor(scope.node);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -247,6 +247,7 @@ Use this directive to generate a thumbnail grid of media items.
|
||||
scope.clickItem = function(item, $event, $index) {
|
||||
if (scope.onClick) {
|
||||
scope.onClick(item, $event, $index);
|
||||
$event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function MiniListViewDirective(entityResource, iconHelper) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.search = "";
|
||||
scope.miniListViews = [];
|
||||
scope.breadcrumb = [];
|
||||
|
||||
var miniListViewsHistory = [];
|
||||
var goingForward = true;
|
||||
var skipAnimation = true;
|
||||
|
||||
function onInit() {
|
||||
open(scope.node);
|
||||
}
|
||||
|
||||
function open(node) {
|
||||
|
||||
// convert legacy icon for node
|
||||
if(node && node.icon) {
|
||||
node.icon = iconHelper.convertFromLegacyIcon(node.icon);
|
||||
}
|
||||
|
||||
goingForward = true;
|
||||
|
||||
var miniListView = {
|
||||
node: node,
|
||||
loading: true,
|
||||
pagination: {
|
||||
pageSize: 10,
|
||||
pageNumber: 1,
|
||||
filter: '',
|
||||
orderDirection: "Ascending",
|
||||
orderBy: "SortOrder",
|
||||
orderBySystemField: true
|
||||
}
|
||||
};
|
||||
|
||||
// clear and push mini list view in dom so we only render 1 view
|
||||
scope.miniListViews = [];
|
||||
scope.miniListViews.push(miniListView);
|
||||
|
||||
// store in history so we quickly can navigate back
|
||||
miniListViewsHistory.push(miniListView);
|
||||
|
||||
// get children
|
||||
getChildrenForMiniListView(miniListView);
|
||||
|
||||
makeBreadcrumb();
|
||||
|
||||
}
|
||||
|
||||
function getChildrenForMiniListView(miniListView) {
|
||||
|
||||
// start loading animation list view
|
||||
miniListView.loading = true;
|
||||
|
||||
entityResource.getPagedChildren(miniListView.node.id, scope.entityType, miniListView.pagination)
|
||||
.then(function (data) {
|
||||
// update children
|
||||
miniListView.children = data.items;
|
||||
_.each(miniListView.children, function(c) {
|
||||
// convert legacy icon for node
|
||||
if(c.icon) {
|
||||
c.icon = iconHelper.convertFromLegacyIcon(c.icon);
|
||||
}
|
||||
// set published state for content
|
||||
if (c.metaData) {
|
||||
c.hasChildren = c.metaData.HasChildren;
|
||||
if(scope.entityType === "Document") {
|
||||
c.published = c.metaData.IsPublished;
|
||||
}
|
||||
}
|
||||
});
|
||||
// update pagination
|
||||
miniListView.pagination.totalItems = data.totalItems;
|
||||
miniListView.pagination.totalPages = data.totalPages;
|
||||
// stop load indicator
|
||||
miniListView.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
scope.openNode = function(event, node) {
|
||||
open(node);
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
scope.selectNode = function(node) {
|
||||
if(scope.onSelect) {
|
||||
scope.onSelect({'node': node});
|
||||
}
|
||||
};
|
||||
|
||||
/* Pagination */
|
||||
scope.goToPage = function(pageNumber, miniListView) {
|
||||
// set new page number
|
||||
miniListView.pagination.pageNumber = pageNumber;
|
||||
// get children
|
||||
getChildrenForMiniListView(miniListView);
|
||||
};
|
||||
|
||||
/* Breadcrumb */
|
||||
scope.clickBreadcrumb = function(ancestor) {
|
||||
|
||||
var found = false;
|
||||
goingForward = false;
|
||||
|
||||
angular.forEach(miniListViewsHistory, function(historyItem, index){
|
||||
// We need to make sure we can compare the two id's.
|
||||
// Some id's are integers and others are strings.
|
||||
// Members have string ids like "all-members".
|
||||
if(historyItem.node.id.toString() === ancestor.id.toString()) {
|
||||
// load the list view from history
|
||||
scope.miniListViews = [];
|
||||
scope.miniListViews.push(historyItem);
|
||||
// clean up history - remove all children after
|
||||
miniListViewsHistory.splice(index + 1, miniListViewsHistory.length);
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(!found) {
|
||||
// if we can't find the view in the history - close the list view
|
||||
scope.exitMiniListView();
|
||||
}
|
||||
|
||||
// update the breadcrumb
|
||||
makeBreadcrumb();
|
||||
|
||||
};
|
||||
|
||||
scope.showBackButton = function() {
|
||||
// don't show the back button if the start node is a list view
|
||||
if(scope.node.metaData && scope.node.metaData.IsContainer || scope.node.isContainer) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
scope.exitMiniListView = function() {
|
||||
miniListViewsHistory = [];
|
||||
scope.miniListViews = [];
|
||||
if(scope.onClose) {
|
||||
scope.onClose();
|
||||
}
|
||||
};
|
||||
|
||||
function makeBreadcrumb() {
|
||||
scope.breadcrumb = [];
|
||||
angular.forEach(miniListViewsHistory, function(historyItem){
|
||||
scope.breadcrumb.push(historyItem.node);
|
||||
});
|
||||
}
|
||||
|
||||
/* Search */
|
||||
scope.searchMiniListView = function(search, miniListView) {
|
||||
// set search value
|
||||
miniListView.pagination.filter = search;
|
||||
// reset pagination
|
||||
miniListView.pagination.pageNumber = 1;
|
||||
// start loading animation list view
|
||||
miniListView.loading = true;
|
||||
searchMiniListView(miniListView);
|
||||
};
|
||||
|
||||
var searchMiniListView = _.debounce(function (miniListView) {
|
||||
scope.$apply(function () {
|
||||
getChildrenForMiniListView(miniListView);
|
||||
});
|
||||
}, 500);
|
||||
|
||||
/* Animation */
|
||||
scope.getMiniListViewAnimation = function() {
|
||||
|
||||
// disable the first "slide-in-animation"" if the start node is a list view
|
||||
if(scope.node.metaData && scope.node.metaData.IsContainer && skipAnimation || scope.node.isContainer && skipAnimation) {
|
||||
skipAnimation = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if(goingForward) {
|
||||
return 'umb-mini-list-view--forward';
|
||||
} else {
|
||||
return 'umb-mini-list-view--backwards';
|
||||
}
|
||||
};
|
||||
|
||||
onInit();
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-mini-list-view.html',
|
||||
scope: {
|
||||
node: "=",
|
||||
entityType: "@",
|
||||
startNodeId: "=",
|
||||
onSelect: "&",
|
||||
onClose: "&"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbMiniListView', MiniListViewDirective);
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbNodePreview
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
<strong>Added in Umbraco v. 7.6:</strong> Use this directive to render a node preview.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.NodePreviewController as vm">
|
||||
|
||||
<div ui-sortable ng-model="vm.nodes">
|
||||
<umb-node-preview
|
||||
ng-repeat="node in vm.nodes"
|
||||
icon="node.icon"
|
||||
name="node.name"
|
||||
published="node.published"
|
||||
description="node.description"
|
||||
sortable="vm.sortable"
|
||||
allow-remove="vm.allowRemove"
|
||||
allow-open="vm.allowOpen"
|
||||
on-remove="vm.remove($index, vm.nodes)"
|
||||
on-open="vm.open(node)">
|
||||
</umb-node-preview>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.allowRemove = true;
|
||||
vm.allowOpen = true;
|
||||
vm.sortable = true;
|
||||
|
||||
vm.nodes = [
|
||||
{
|
||||
"icon": "icon-document",
|
||||
"name": "My node 1",
|
||||
"published": true,
|
||||
"description": "A short description of my node"
|
||||
},
|
||||
{
|
||||
"icon": "icon-document",
|
||||
"name": "My node 2",
|
||||
"published": true,
|
||||
"description": "A short description of my node"
|
||||
}
|
||||
];
|
||||
|
||||
vm.remove = remove;
|
||||
vm.open = open;
|
||||
|
||||
function remove(index, nodes) {
|
||||
alert("remove node");
|
||||
}
|
||||
|
||||
function open(node) {
|
||||
alert("open node");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.NodePreviewController", Controller);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {string} icon (<code>binding</code>): The node icon.
|
||||
@param {string} name (<code>binding</code>): The node name.
|
||||
@param {boolean} published (<code>binding</code>): The node pusblished state.
|
||||
@param {string} description (<code>binding</code>): A short description.
|
||||
@param {boolean} sortable (<code>binding</code>): Will add a move cursor on the node preview. Can used in combination with ui-sortable.
|
||||
@param {boolean} allowRemove (<code>binding</code>): Show/Hide the remove button.
|
||||
@param {boolean} allowOpen (<code>binding</code>): Show/Hide the open button.
|
||||
@param {function} onRemove (<code>expression</code>): Callback function when the remove button is clicked.
|
||||
@param {function} onOpen (<code>expression</code>): Callback function when the open button is clicked.
|
||||
**/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function NodePreviewDirective() {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-node-preview.html',
|
||||
scope: {
|
||||
icon: "=?",
|
||||
name: "=",
|
||||
description: "=?",
|
||||
published: "=?",
|
||||
sortable: "=?",
|
||||
allowOpen: "=?",
|
||||
allowRemove: "=?",
|
||||
onOpen: "&?",
|
||||
onRemove: "&?"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbNodePreview', NodePreviewDirective);
|
||||
|
||||
})();
|
||||
@@ -134,25 +134,40 @@ Use this directive to generate a pagination.
|
||||
|
||||
}
|
||||
|
||||
scope.next = function() {
|
||||
if (scope.onNext && scope.pageNumber < scope.totalPages) {
|
||||
scope.pageNumber++;
|
||||
scope.onNext(scope.pageNumber);
|
||||
}
|
||||
scope.next = function () {
|
||||
if (scope.pageNumber < scope.totalPages) {
|
||||
scope.pageNumber++;
|
||||
if (scope.onNext) {
|
||||
scope.onNext(scope.pageNumber);
|
||||
}
|
||||
if (scope.onChange) {
|
||||
scope.onChange({ "pageNumber": scope.pageNumber });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scope.prev = function(pageNumber) {
|
||||
if (scope.onPrev && scope.pageNumber > 1) {
|
||||
scope.pageNumber--;
|
||||
scope.onPrev(scope.pageNumber);
|
||||
}
|
||||
scope.prev = function (pageNumber) {
|
||||
if (scope.pageNumber > 1) {
|
||||
scope.pageNumber--;
|
||||
if (scope.onPrev) {
|
||||
scope.onPrev(scope.pageNumber);
|
||||
}
|
||||
if (scope.onChange) {
|
||||
scope.onChange({ "pageNumber": scope.pageNumber });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scope.goToPage = function(pageNumber) {
|
||||
if(scope.onGoToPage) {
|
||||
scope.pageNumber = pageNumber + 1;
|
||||
scope.onGoToPage(scope.pageNumber);
|
||||
}
|
||||
scope.goToPage = function (pageNumber) {
|
||||
scope.pageNumber = pageNumber + 1;
|
||||
if (scope.onGoToPage) {
|
||||
scope.onGoToPage(scope.pageNumber);
|
||||
}
|
||||
if (scope.onChange) {
|
||||
if (scope.onChange) {
|
||||
scope.onChange({ "pageNumber": scope.pageNumber });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var unbindPageNumberWatcher = scope.$watch('pageNumber', function(newValue, oldValue){
|
||||
@@ -176,7 +191,8 @@ Use this directive to generate a pagination.
|
||||
totalPages: "=",
|
||||
onNext: "=",
|
||||
onPrev: "=",
|
||||
onGoToPage: "="
|
||||
onGoToPage: "=",
|
||||
onChange: "&"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -36,119 +36,119 @@ Use this directive make an element sticky and follow the page when scrolling.
|
||||
@param {string} scrollableContainer Set the class (".element") or the id ("#element") of the scrollable container element.
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function StickyBarDirective($rootScope) {
|
||||
function StickyBarDirective($rootScope) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
var bar = $(el);
|
||||
var scrollableContainer = null;
|
||||
var clonedBar = null;
|
||||
var cloneIsMade = false;
|
||||
var barTop = bar.context.offsetTop;
|
||||
var bar = $(el);
|
||||
var scrollableContainer = null;
|
||||
var clonedBar = null;
|
||||
var cloneIsMade = false;
|
||||
|
||||
function activate() {
|
||||
function activate() {
|
||||
|
||||
if (attr.scrollableContainer) {
|
||||
scrollableContainer = $(attr.scrollableContainer);
|
||||
} else {
|
||||
scrollableContainer = $(window);
|
||||
}
|
||||
if (attr.scrollableContainer) {
|
||||
scrollableContainer = $(attr.scrollableContainer);
|
||||
} else {
|
||||
scrollableContainer = $(window);
|
||||
}
|
||||
|
||||
scrollableContainer.on('scroll.umbStickyBar', determineVisibility).trigger("scroll");
|
||||
$(window).on('resize.umbStickyBar', determineVisibility);
|
||||
scrollableContainer.on('scroll.umbStickyBar', determineVisibility).trigger("scroll");
|
||||
$(window).on('resize.umbStickyBar', determineVisibility);
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
scrollableContainer.off('.umbStickyBar');
|
||||
$(window).off('.umbStickyBar');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function determineVisibility() {
|
||||
|
||||
var scrollTop = scrollableContainer.scrollTop();
|
||||
|
||||
if (scrollTop > barTop) {
|
||||
|
||||
if (!cloneIsMade) {
|
||||
|
||||
createClone();
|
||||
|
||||
clonedBar.css({
|
||||
'visibility': 'visible'
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
calculateSize();
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (cloneIsMade) {
|
||||
|
||||
//remove cloned element (switched places with original on creation)
|
||||
bar.remove();
|
||||
bar = clonedBar;
|
||||
clonedBar = null;
|
||||
|
||||
bar.removeClass('-umb-sticky-bar');
|
||||
bar.css({
|
||||
position: 'relative',
|
||||
'width': 'auto',
|
||||
'height': 'auto',
|
||||
'z-index': 'auto',
|
||||
'visibility': 'visible'
|
||||
});
|
||||
|
||||
cloneIsMade = false;
|
||||
|
||||
}
|
||||
scope.$on('$destroy', function () {
|
||||
scrollableContainer.off('.umbStickyBar');
|
||||
$(window).off('.umbStickyBar');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
function determineVisibility() {
|
||||
|
||||
function calculateSize() {
|
||||
clonedBar.css({
|
||||
width: bar.outerWidth(),
|
||||
height: bar.height()
|
||||
});
|
||||
}
|
||||
var barTop = bar[0].offsetTop;
|
||||
var scrollTop = scrollableContainer.scrollTop();
|
||||
|
||||
function createClone() {
|
||||
//switch place with cloned element, to keep binding intact
|
||||
clonedBar = bar;
|
||||
bar = clonedBar.clone();
|
||||
clonedBar.after(bar);
|
||||
clonedBar.addClass('-umb-sticky-bar');
|
||||
clonedBar.css({
|
||||
'position': 'fixed',
|
||||
'z-index': 500,
|
||||
'visibility': 'hidden'
|
||||
});
|
||||
if (scrollTop > barTop) {
|
||||
|
||||
cloneIsMade = true;
|
||||
calculateSize();
|
||||
if (!cloneIsMade) {
|
||||
|
||||
}
|
||||
createClone();
|
||||
|
||||
activate();
|
||||
clonedBar.css({
|
||||
'visibility': 'visible'
|
||||
});
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
var directive = {
|
||||
restrict: 'A',
|
||||
link: link
|
||||
};
|
||||
calculateSize();
|
||||
|
||||
return directive;
|
||||
}
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbStickyBar', StickyBarDirective);
|
||||
} else {
|
||||
|
||||
if (cloneIsMade) {
|
||||
|
||||
//remove cloned element (switched places with original on creation)
|
||||
bar.remove();
|
||||
bar = clonedBar;
|
||||
clonedBar = null;
|
||||
|
||||
bar.removeClass('-umb-sticky-bar');
|
||||
bar.css({
|
||||
position: 'relative',
|
||||
'width': 'auto',
|
||||
'height': 'auto',
|
||||
'z-index': 'auto',
|
||||
'visibility': 'visible'
|
||||
});
|
||||
|
||||
cloneIsMade = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function calculateSize() {
|
||||
clonedBar.css({
|
||||
width: bar.outerWidth(),
|
||||
height: bar.height()
|
||||
});
|
||||
}
|
||||
|
||||
function createClone() {
|
||||
//switch place with cloned element, to keep binding intact
|
||||
clonedBar = bar;
|
||||
bar = clonedBar.clone();
|
||||
clonedBar.after(bar);
|
||||
clonedBar.addClass('-umb-sticky-bar');
|
||||
clonedBar.css({
|
||||
'position': 'fixed',
|
||||
'z-index': 500,
|
||||
'visibility': 'hidden'
|
||||
});
|
||||
|
||||
cloneIsMade = true;
|
||||
calculateSize();
|
||||
|
||||
}
|
||||
|
||||
activate();
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'A',
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbStickyBar', StickyBarDirective);
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function TableDirective() {
|
||||
function TableDirective(iconHelper) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
}
|
||||
};
|
||||
|
||||
scope.getIcon = function (entry) {
|
||||
return iconHelper.convertFromLegacyIcon(entry.icon);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
|
||||
@@ -9,7 +9,7 @@ function valServerField(serverValidationManager) {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
restrict: "A",
|
||||
link: function (scope, element, attr, ctrl) {
|
||||
link: function (scope, element, attr, ngModel) {
|
||||
|
||||
var fieldName = null;
|
||||
var eventBindings = [];
|
||||
@@ -23,23 +23,25 @@ function valServerField(serverValidationManager) {
|
||||
// resubmitted. So once a field is changed that has a server error assigned to it
|
||||
// we need to re-validate it for the server side validator so the user can resubmit
|
||||
// the form. Of course normal client-side validators will continue to execute.
|
||||
eventBindings.push(scope.$watch('ngModel', function(newValue){
|
||||
if (ctrl.$invalid) {
|
||||
ctrl.$setValidity('valServerField', true);
|
||||
eventBindings.push(scope.$watch(function() {
|
||||
return ngModel.$modelValue;
|
||||
}, function(newValue){
|
||||
if (ngModel.$invalid) {
|
||||
ngModel.$setValidity('valServerField', true);
|
||||
}
|
||||
}));
|
||||
|
||||
//subscribe to the server validation changes
|
||||
serverValidationManager.subscribe(null, fieldName, function (isValid, fieldErrors, allErrors) {
|
||||
if (!isValid) {
|
||||
ctrl.$setValidity('valServerField', false);
|
||||
ngModel.$setValidity('valServerField', false);
|
||||
//assign an error msg property to the current validator
|
||||
ctrl.errorMsg = fieldErrors[0].errorMsg;
|
||||
ngModel.errorMsg = fieldErrors[0].errorMsg;
|
||||
}
|
||||
else {
|
||||
ctrl.$setValidity('valServerField', true);
|
||||
ngModel.$setValidity('valServerField', true);
|
||||
//reset the error message
|
||||
ctrl.errorMsg = "";
|
||||
ngModel.errorMsg = "";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -343,8 +343,13 @@ angular.module('umbraco.mocks').
|
||||
{
|
||||
results.push(decodeURIComponent(match[1].replace(/\+/g, " ")));
|
||||
}
|
||||
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
getObjectPropertyFromJsonString: function(data, name) {
|
||||
var obj = JSON.parse(data);
|
||||
return obj[name];
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
@@ -21,8 +21,9 @@ angular.module('umbraco.mocks').
|
||||
if (!mocksUtils.checkAuth()) {
|
||||
return [401, null, null];
|
||||
}
|
||||
|
||||
|
||||
var ids = mocksUtils.getParametersByName(data, "ids") || [1234, 23324, 2323, 23424];
|
||||
|
||||
var nodes = [];
|
||||
|
||||
$(ids).each(function (i, id) {
|
||||
@@ -33,6 +34,33 @@ angular.module('umbraco.mocks').
|
||||
return [200, nodes, null];
|
||||
}
|
||||
|
||||
function returnEntitybyIdsPost(method, url, data, headers) {
|
||||
|
||||
if (!mocksUtils.checkAuth()) {
|
||||
return [401, null, null];
|
||||
}
|
||||
|
||||
var ids = mocksUtils.getObjectPropertyFromJsonString(data, "ids") || [1234, 23324, 2323, 23424];
|
||||
|
||||
var nodes = [];
|
||||
|
||||
$(ids).each(function (i, id) {
|
||||
var _id = parseInt(id, 10);
|
||||
nodes.push(mocksUtils.getMockEntity(_id));
|
||||
});
|
||||
|
||||
return [200, nodes, null];
|
||||
}
|
||||
|
||||
function returnEntityUrl() {
|
||||
|
||||
if (!mocksUtils.checkAuth()) {
|
||||
return [401, null, null];
|
||||
}
|
||||
|
||||
return [200, "url", null];
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
register: function () {
|
||||
@@ -41,6 +69,10 @@ angular.module('umbraco.mocks').
|
||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetByIds'))
|
||||
.respond(returnEntitybyIds);
|
||||
|
||||
$httpBackend
|
||||
.whenPOST(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetByIds'))
|
||||
.respond(returnEntitybyIdsPost);
|
||||
|
||||
$httpBackend
|
||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetAncestors'))
|
||||
.respond(returnEntitybyIds);
|
||||
@@ -48,6 +80,10 @@ angular.module('umbraco.mocks').
|
||||
$httpBackend
|
||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetById?'))
|
||||
.respond(returnEntitybyId);
|
||||
|
||||
$httpBackend
|
||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetUrl?'))
|
||||
.respond(returnEntityUrl);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -13,6 +13,41 @@ function authResource($q, $http, umbRequestHelper, angularHelper) {
|
||||
|
||||
return {
|
||||
|
||||
get2FAProviders: function () {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"authenticationApiBaseUrl",
|
||||
"Get2FAProviders")),
|
||||
'Could not retrive two factor provider info');
|
||||
},
|
||||
|
||||
send2FACode: function (provider) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"authenticationApiBaseUrl",
|
||||
"PostSend2FACode"),
|
||||
angular.toJson(provider)),
|
||||
'Could not send code');
|
||||
},
|
||||
|
||||
verify2FACode: function (provider, code) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"authenticationApiBaseUrl",
|
||||
"PostVerify2FACode"),
|
||||
{
|
||||
code: code,
|
||||
provider: provider
|
||||
}),
|
||||
'Could not verify code');
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.authResource#performLogin
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.codefileResource
|
||||
* @description Loads in data for files that contain code such as js scripts, partial views and partial view macros
|
||||
**/
|
||||
function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#getByPath
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Gets a codefile item with a given path
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.getByPath('scripts', 'oooh-la-la.js')
|
||||
* .then(function(codefile) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* <pre>
|
||||
* codefileResource.getByPath('partialView', 'Grid%2fEditors%2fBase.cshtml')
|
||||
* .then(function(codefile) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {type} the type of script (partialView, partialViewMacro, script)
|
||||
* @param {virtualpath} the virtual path of the script
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getByPath: function (type, virtualpath) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"GetByPath",
|
||||
[{ type: type }, {virtualPath: virtualpath }])),
|
||||
"Failed to retrieve data for " + type + " from virtual path " + virtualpath);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#getByAlias
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Gets a template item with a given alias
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.getByAlias("upload")
|
||||
* .then(function(template) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {String} alias Alias of template to retrieve
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getByAlias: function (alias) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateApiBaseUrl",
|
||||
"GetByAlias",
|
||||
[{ alias: alias }])),
|
||||
"Failed to retrieve data for template with alias: " + alias);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#deleteByPath
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Deletes a codefile with a given type & path
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.deleteByPath('scripts', 'oooh-la-la.js')
|
||||
* .then(function() {
|
||||
* alert('its gone!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* <pre>
|
||||
* codefileResource.deleteByPath('partialViews', 'Grid%2fEditors%2fBase.cshtml')
|
||||
* .then(function() {
|
||||
* alert('its gone!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {type} the type of script (partialViews, partialViewMacros, scripts)
|
||||
* @param {virtualpath} the virtual path of the script
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
deleteByPath: function (type, virtualpath) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"Delete",
|
||||
[{ type: type }, { virtualPath: virtualpath}])),
|
||||
"Failed to delete item: " + virtualpath);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#save
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Saves or update a codeFile
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.save(codeFile)
|
||||
* .then(function(codeFile) {
|
||||
* alert('its saved!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Object} template object to save
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
save: function (codeFile) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"PostSave"),
|
||||
codeFile),
|
||||
"Failed to save data for code file " + codeFile.virtualPath);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#getSnippets
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Gets code snippets for a given file type
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.getSnippets("partialViews")
|
||||
* .then(function(snippets) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {string} file type: (partialViews, partialViewMacros)
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getSnippets: function (fileType) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"GetSnippets?type=" + fileType )),
|
||||
"Failed to get snippet for" + fileType);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#getScaffold
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Returns a scaffold of an empty codefile item.
|
||||
*
|
||||
* The scaffold is used to build editors for code file editors that has not yet been populated with data.
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.getScaffold("partialViews", "Breadcrumb")
|
||||
* .then(function(data) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {string} File type: (scripts, partialViews, partialViewMacros).
|
||||
* @param {string} Snippet name (Ex. Breadcrumb).
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
|
||||
getScaffold: function (type, id, snippetName) {
|
||||
|
||||
var queryString = "?type=" + type + "&id=" + id;
|
||||
if (snippetName) {
|
||||
queryString += "&snippetName=" + snippetName;
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"GetScaffold" + queryString)),
|
||||
"Failed to get scaffold for" + type);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.codefileResource#createContainer
|
||||
* @methodOf umbraco.resources.codefileResource
|
||||
*
|
||||
* @description
|
||||
* Creates a container/folder
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* codefileResource.createContainer("partialViews", "folder%2ffolder", "folder")
|
||||
* .then(function(data) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {string} File type: (scripts, partialViews, partialViewMacros).
|
||||
* @param {string} Parent Id: url encoded path
|
||||
* @param {string} Container name
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
|
||||
createContainer: function(type, parentId, name) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"PostCreateContainer",
|
||||
{ type: type, parentId: parentId, name: encodeURIComponent(name) })),
|
||||
'Failed to create a folder under parent id ' + parentId);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco.resources").factory("codefileResource", codefileResource);
|
||||
@@ -477,20 +477,20 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetChildren",
|
||||
[
|
||||
{ id: parentId },
|
||||
{ pageNumber: options.pageNumber },
|
||||
{ pageSize: options.pageSize },
|
||||
{ orderBy: options.orderBy },
|
||||
{ orderDirection: options.orderDirection },
|
||||
{ orderBySystemField: toBool(options.orderBySystemField) },
|
||||
{ filter: options.filter }
|
||||
])),
|
||||
'Failed to retrieve children for content item ' + parentId);
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetChildren",
|
||||
{
|
||||
id: parentId,
|
||||
pageNumber: options.pageNumber,
|
||||
pageSize: options.pageSize,
|
||||
orderBy: options.orderBy,
|
||||
orderDirection: options.orderDirection,
|
||||
orderBySystemField: toBool(options.orderBySystemField),
|
||||
filter: options.filter
|
||||
})),
|
||||
'Failed to retrieve children for content item ' + parentId);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,6 +92,16 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
'Failed to retrieve property type aliases');
|
||||
},
|
||||
|
||||
getAllStandardFields: function () {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentTypeApiBaseUrl",
|
||||
"GetAllStandardFields")),
|
||||
'Failed to retrieve standard fields');
|
||||
},
|
||||
|
||||
getPropertyTypeScaffold : function (id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
|
||||
@@ -38,6 +38,10 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
|
||||
getSafeAlias: function (value, camelCase) {
|
||||
|
||||
if (!value) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -56,7 +60,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* entityResource.getPath(id)
|
||||
* entityResource.getPath(id, type)
|
||||
* .then(function(pathArray) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
@@ -68,6 +72,11 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
*
|
||||
*/
|
||||
getPath: function (id, type) {
|
||||
|
||||
if (id === -1 || id === "-1") {
|
||||
return "-1";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -77,6 +86,42 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
'Failed to retrieve path for id:' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.entityResource#getUrl
|
||||
* @methodOf umbraco.resources.entityResource
|
||||
*
|
||||
* @description
|
||||
* Returns a url, given a node ID and type
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* entityResource.getUrl(id, type)
|
||||
* .then(function(url) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id Id of node to return the public url to
|
||||
* @param {string} type Object type name
|
||||
* @returns {Promise} resourcePromise object containing the url.
|
||||
*
|
||||
*/
|
||||
getUrl: function (id, type) {
|
||||
|
||||
if (id === -1 || id === "-1") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetUrl",
|
||||
[{ id: id }, {type: type }])),
|
||||
'Failed to retrieve url for id:' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.entityResource#getById
|
||||
@@ -100,14 +145,19 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
* @returns {Promise} resourcePromise object containing the entity.
|
||||
*
|
||||
*/
|
||||
getById: function (id, type) {
|
||||
getById: function (id, type) {
|
||||
|
||||
if (id === -1 || id === "-1") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetById",
|
||||
[{ id: id}, {type: type }])),
|
||||
'Failed to retrieve entity data for id ' + id);
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetById",
|
||||
[{ id: id }, { type: type }])),
|
||||
'Failed to retrieve entity data for id ' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -135,24 +185,17 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
*/
|
||||
getByIds: function (ids, type) {
|
||||
|
||||
var query = "";
|
||||
_.each(ids, function(item) {
|
||||
query += "ids=" + item + "&";
|
||||
});
|
||||
|
||||
// if ids array is empty we need a empty variable in the querystring otherwise the service returns a error
|
||||
if (ids.length === 0) {
|
||||
query += "ids=&";
|
||||
}
|
||||
|
||||
query += "type=" + type;
|
||||
var query = "type=" + type;
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetByIds",
|
||||
query)),
|
||||
query),
|
||||
{
|
||||
ids: ids
|
||||
}),
|
||||
'Failed to retrieve entity data for ids ' + ids);
|
||||
},
|
||||
|
||||
@@ -261,18 +304,19 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.entityResource#getAncestors
|
||||
* @name umbraco.resources.entityResource#getChildren
|
||||
* @methodOf umbraco.resources.entityResource
|
||||
*
|
||||
* @description
|
||||
* Gets children entities for a given item
|
||||
*
|
||||
*
|
||||
* @param {Int} parentid id of content item to return children of
|
||||
* @param {string} type Object type name
|
||||
* @returns {Promise} resourcePromise object containing the entity.
|
||||
*
|
||||
*/
|
||||
getChildren: function (id, type) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -281,6 +325,146 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
[{ id: id }, { type: type }])),
|
||||
'Failed to retrieve child data for id ' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.entityResource#getPagedChildren
|
||||
* @methodOf umbraco.resources.entityResource
|
||||
*
|
||||
* @description
|
||||
* Gets paged children of a content item with a given id
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* entityResource.getPagedChildren(1234, "Content", {pageSize: 10, pageNumber: 2})
|
||||
* .then(function(contentArray) {
|
||||
* var children = contentArray;
|
||||
* alert('they are here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} parentid id of content item to return children of
|
||||
* @param {string} type Object type name
|
||||
* @param {Object} options optional options object
|
||||
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 1
|
||||
* @param {Int} options.pageNumber if paging data, current page index, default = 100
|
||||
* @param {String} options.filter if provided, query will only return those with names matching the filter
|
||||
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending`
|
||||
* @param {String} options.orderBy property to order items by, default: `SortOrder`
|
||||
* @returns {Promise} resourcePromise object containing an array of content items.
|
||||
*
|
||||
*/
|
||||
getPagedChildren: function (parentId, type, options) {
|
||||
|
||||
var defaults = {
|
||||
pageSize: 1,
|
||||
pageNumber: 100,
|
||||
filter: '',
|
||||
orderDirection: "Ascending",
|
||||
orderBy: "SortOrder"
|
||||
};
|
||||
if (options === undefined) {
|
||||
options = {};
|
||||
}
|
||||
//overwrite the defaults if there are any specified
|
||||
angular.extend(defaults, options);
|
||||
//now copy back to the options we will use
|
||||
options = defaults;
|
||||
//change asc/desct
|
||||
if (options.orderDirection === "asc") {
|
||||
options.orderDirection = "Ascending";
|
||||
}
|
||||
else if (options.orderDirection === "desc") {
|
||||
options.orderDirection = "Descending";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetPagedChildren",
|
||||
{
|
||||
id: parentId,
|
||||
type: type,
|
||||
pageNumber: options.pageNumber,
|
||||
pageSize: options.pageSize,
|
||||
orderBy: options.orderBy,
|
||||
orderDirection: options.orderDirection,
|
||||
filter: encodeURIComponent(options.filter)
|
||||
}
|
||||
)),
|
||||
'Failed to retrieve child data for id ' + parentId);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.entityResource#getPagedDescendants
|
||||
* @methodOf umbraco.resources.entityResource
|
||||
*
|
||||
* @description
|
||||
* Gets paged descendants of a content item with a given id
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* entityResource.getPagedDescendants(1234, "Content", {pageSize: 10, pageNumber: 2})
|
||||
* .then(function(contentArray) {
|
||||
* var children = contentArray;
|
||||
* alert('they are here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} parentid id of content item to return descendants of
|
||||
* @param {string} type Object type name
|
||||
* @param {Object} options optional options object
|
||||
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 1
|
||||
* @param {Int} options.pageNumber if paging data, current page index, default = 100
|
||||
* @param {String} options.filter if provided, query will only return those with names matching the filter
|
||||
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending`
|
||||
* @param {String} options.orderBy property to order items by, default: `SortOrder`
|
||||
* @returns {Promise} resourcePromise object containing an array of content items.
|
||||
*
|
||||
*/
|
||||
getPagedDescendants: function (parentId, type, options) {
|
||||
|
||||
var defaults = {
|
||||
pageSize: 1,
|
||||
pageNumber: 100,
|
||||
filter: '',
|
||||
orderDirection: "Ascending",
|
||||
orderBy: "SortOrder"
|
||||
};
|
||||
if (options === undefined) {
|
||||
options = {};
|
||||
}
|
||||
//overwrite the defaults if there are any specified
|
||||
angular.extend(defaults, options);
|
||||
//now copy back to the options we will use
|
||||
options = defaults;
|
||||
//change asc/desct
|
||||
if (options.orderDirection === "asc") {
|
||||
options.orderDirection = "Ascending";
|
||||
}
|
||||
else if (options.orderDirection === "desc") {
|
||||
options.orderDirection = "Descending";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetPagedDescendants",
|
||||
{
|
||||
id: parentId,
|
||||
type: type,
|
||||
pageNumber: options.pageNumber,
|
||||
pageSize: options.pageSize,
|
||||
orderBy: options.orderBy,
|
||||
orderDirection: options.orderDirection,
|
||||
filter: encodeURIComponent(options.filter)
|
||||
}
|
||||
)),
|
||||
'Failed to retrieve child data for id ' + parentId);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.macroResource
|
||||
* @description Deals with data for macros
|
||||
*
|
||||
*
|
||||
**/
|
||||
function macroResource($q, $http, umbRequestHelper) {
|
||||
|
||||
//the factory object returned
|
||||
return {
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.macroResource#getMacroParameters
|
||||
@@ -20,7 +20,7 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
* @param {int} macroId The macro id to get parameters for
|
||||
*
|
||||
*/
|
||||
getMacroParameters: function (macroId) {
|
||||
getMacroParameters: function (macroId) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -29,7 +29,7 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
[{ macroId: macroId }])),
|
||||
'Failed to retrieve macro parameters for macro with id ' + macroId);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.macroResource#getMacroResult
|
||||
@@ -55,6 +55,27 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
macroParams: macroParamDictionary
|
||||
}),
|
||||
'Failed to retrieve macro result for macro with alias ' + macroAlias);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {} filename
|
||||
* @returns {}
|
||||
*/
|
||||
createPartialViewMacroWithFile: function(virtualPath, filename) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"macroApiBaseUrl",
|
||||
"CreatePartialViewMacroWithFile"), {
|
||||
virtualPath: virtualPath,
|
||||
filename: filename
|
||||
}
|
||||
),
|
||||
'Failed to create macro "' + filename + '"'
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -485,7 +485,49 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
"mediaApiBaseUrl",
|
||||
"EmptyRecycleBin")),
|
||||
'Failed to empty the recycle bin');
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaResource#search
|
||||
* @methodOf umbraco.resources.mediaResource
|
||||
*
|
||||
* @description
|
||||
* Empties the media recycle bin
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaResource.search("my search", 1, 100, -1)
|
||||
* .then(function(searchResult) {
|
||||
* alert('it's here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {string} query The search query
|
||||
* @param {int} pageNumber The page number
|
||||
* @param {int} pageSize The number of media items on a page
|
||||
* @param {int} searchFrom Id to search from
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
search: function (query, pageNumber, pageSize, searchFrom) {
|
||||
|
||||
var args = [
|
||||
{ "query": query },
|
||||
{ "pageNumber": pageNumber },
|
||||
{ "pageSize": pageSize },
|
||||
{ "searchFrom": searchFrom }
|
||||
];
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaApiBaseUrl",
|
||||
"Search",
|
||||
args)),
|
||||
'Failed to retrieve media items for search: ' + query);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -19,14 +19,14 @@ function memberTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
_.each(filterContentTypes, function (item) {
|
||||
query += "filterContentTypes=" + item + "&";
|
||||
});
|
||||
// if filterContentTypes array is empty we need a empty variable in the querystring otherwise the service returns a error
|
||||
// if filterContentTypes array is empty we need a empty variable in the querystring otherwise the service returns a error
|
||||
if (filterContentTypes.length === 0) {
|
||||
query += "filterContentTypes=&";
|
||||
}
|
||||
_.each(filterPropertyTypes, function (item) {
|
||||
query += "filterPropertyTypes=" + item + "&";
|
||||
});
|
||||
// if filterPropertyTypes array is empty we need a empty variable in the querystring otherwise the service returns a error
|
||||
// if filterPropertyTypes array is empty we need a empty variable in the querystring otherwise the service returns a error
|
||||
if (filterPropertyTypes.length === 0) {
|
||||
query += "filterPropertyTypes=&";
|
||||
}
|
||||
|
||||
@@ -5,15 +5,14 @@
|
||||
**/
|
||||
function ourPackageRepositoryResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
//var baseurl = "http://localhost:24292/webapi/packages/v1";
|
||||
var baseurl = "https://our.umbraco.org/webapi/packages/v1";
|
||||
var baseurl = Umbraco.Sys.ServerVariables.umbracoUrls.packagesRestApiBaseUrl;
|
||||
|
||||
return {
|
||||
|
||||
getDetails: function (packageId) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(baseurl + "/" + packageId),
|
||||
$http.get(baseurl + "/" + packageId + "?version=" + Umbraco.Sys.ServerVariables.application.version),
|
||||
'Failed to get package details');
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.templateResource
|
||||
* @description Loads in data for templates
|
||||
**/
|
||||
function templateResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.templateResource#getById
|
||||
* @methodOf umbraco.resources.templateResource
|
||||
*
|
||||
* @description
|
||||
* Gets a template item with a given id
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* templateResource.getById(1234)
|
||||
* .then(function(template) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id id of template to retrieve
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getById: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateApiBaseUrl",
|
||||
"GetById",
|
||||
[{ id: id }])),
|
||||
"Failed to retrieve data for template id " + id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.templateResource#getByAlias
|
||||
* @methodOf umbraco.resources.templateResource
|
||||
*
|
||||
* @description
|
||||
* Gets a template item with a given alias
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* templateResource.getByAlias("upload")
|
||||
* .then(function(template) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {String} alias Alias of template to retrieve
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getByAlias: function (alias) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateApiBaseUrl",
|
||||
"GetByAlias",
|
||||
[{ alias: alias }])),
|
||||
"Failed to retrieve data for template with alias: " + alias);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.templateResource#getAll
|
||||
* @methodOf umbraco.resources.templateResource
|
||||
*
|
||||
* @description
|
||||
* Gets all templates
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* templateResource.getAll()
|
||||
* .then(function(templates) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getAll: function () {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateApiBaseUrl",
|
||||
"GetAll")),
|
||||
"Failed to retrieve data");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.templateResource#getScaffold
|
||||
* @methodOf umbraco.resources.templateResource
|
||||
*
|
||||
* @description
|
||||
* Returns a scaffold of an empty template item
|
||||
*
|
||||
* The scaffold is used to build editors for templates that has not yet been populated with data.
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* templateResource.getScaffold()
|
||||
* .then(function(template) {
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @returns {Promise} resourcePromise object containing the template scaffold.
|
||||
*
|
||||
*/
|
||||
getScaffold: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateApiBaseUrl",
|
||||
"GetScaffold",
|
||||
[{ id: id }] )),
|
||||
"Failed to retrieve data for empty template");
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.templateResource#deleteById
|
||||
* @methodOf umbraco.resources.templateResource
|
||||
*
|
||||
* @description
|
||||
* Deletes a template with a given id
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* templateResource.deleteById(1234)
|
||||
* .then(function() {
|
||||
* alert('its gone!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id id of template to delete
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
deleteById: function(id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateApiBaseUrl",
|
||||
"DeleteById",
|
||||
[{ id: id }])),
|
||||
"Failed to delete item " + id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.templateResource#save
|
||||
* @methodOf umbraco.resources.templateResource
|
||||
*
|
||||
* @description
|
||||
* Saves or update a template
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* templateResource.save(template)
|
||||
* .then(function(template) {
|
||||
* alert('its saved!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Object} template object to save
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
save: function (template) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateApiBaseUrl",
|
||||
"PostSave"),
|
||||
template),
|
||||
"Failed to save data for template id " + template.id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco.resources").factory("templateResource", templateResource);
|
||||
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.templateQueryResource
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Used by the query builder
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function templateQueryResource($http, umbRequestHelper) {
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.resources.templateQueryResource#getAllowedProperties
|
||||
* @methodOf umbraco.resources.templateQueryResource
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Called to get allowed properties
|
||||
* ##usage
|
||||
* <pre>
|
||||
* templateQueryResource.getAllowedProperties()
|
||||
* .then(function(response) {
|
||||
*
|
||||
* });
|
||||
* </pre>
|
||||
*/
|
||||
function getAllowedProperties() {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateQueryApiBaseUrl",
|
||||
"GetAllowedProperties")),
|
||||
'Failed to retrieve properties');
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.resources.templateQueryResource#getContentTypes
|
||||
* @methodOf umbraco.resources.templateQueryResource
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Called to get content types
|
||||
* ##usage
|
||||
* <pre>
|
||||
* templateQueryResource.getContentTypes()
|
||||
* .then(function(response) {
|
||||
*
|
||||
* });
|
||||
* </pre>
|
||||
*/
|
||||
function getContentTypes() {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateQueryApiBaseUrl",
|
||||
"GetContentTypes")),
|
||||
'Failed to retrieve content types');
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.resources.templateQueryResource#getFilterConditions
|
||||
* @methodOf umbraco.resources.templateQueryResource
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Called to the filter conditions
|
||||
* ##usage
|
||||
* <pre>
|
||||
* templateQueryResource.getFilterConditions()
|
||||
* .then(function(response) {
|
||||
*
|
||||
* });
|
||||
* </pre>
|
||||
*/
|
||||
function getFilterConditions() {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateQueryApiBaseUrl",
|
||||
"GetFilterConditions")),
|
||||
'Failed to retrieve filter conditions');
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.resources.templateQueryResource#postTemplateQuery
|
||||
* @methodOf umbraco.resources.templateQueryResource
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Called to get content types
|
||||
* ##usage
|
||||
* <pre>
|
||||
* var query = {
|
||||
* contentType: {
|
||||
* name: "Everything"
|
||||
* },
|
||||
* source: {
|
||||
* name: "My website"
|
||||
* },
|
||||
* filters: [
|
||||
* {
|
||||
* property: undefined,
|
||||
* operator: undefined
|
||||
* }
|
||||
* ],
|
||||
* sort: {
|
||||
* property: {
|
||||
* alias: "",
|
||||
* name: "",
|
||||
* },
|
||||
* direction: "ascending"
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* templateQueryResource.postTemplateQuery(query)
|
||||
* .then(function(response) {
|
||||
*
|
||||
* });
|
||||
* </pre>
|
||||
* @param {object} query Query to build result
|
||||
*/
|
||||
function postTemplateQuery(query) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateQueryApiBaseUrl",
|
||||
"PostTemplateQuery"),
|
||||
query),
|
||||
'Failed to retrieve query');
|
||||
}
|
||||
|
||||
var resource = {
|
||||
getAllowedProperties: getAllowedProperties,
|
||||
getContentTypes: getContentTypes,
|
||||
getFilterConditions: getFilterConditions,
|
||||
postTemplateQuery: postTemplateQuery
|
||||
};
|
||||
|
||||
return resource;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.resources').factory('templateQueryResource', templateQueryResource);
|
||||
|
||||
})();
|
||||
@@ -51,10 +51,15 @@ function treeResource($q, $http, umbRequestHelper) {
|
||||
if (!options.isDialog) {
|
||||
options.isDialog = false;
|
||||
}
|
||||
|
||||
|
||||
//create the query string for the tree request, these are the mandatory options:
|
||||
var query = "application=" + options.section + "&tree=" + options.tree + "&isDialog=" + options.isDialog;
|
||||
|
||||
//if you need to load a not initialized tree set this value to false - default is true
|
||||
if (options.onlyinitialized) {
|
||||
query += "&onlyInitialized=" + options.onlyinitialized;
|
||||
}
|
||||
|
||||
//the options can contain extra query string parameters
|
||||
if (options.queryString) {
|
||||
query += "&" + options.queryString;
|
||||
|
||||
@@ -27,7 +27,7 @@ angular.module('umbraco.security.interceptor')
|
||||
var headers = config.headers ? config.headers : {};
|
||||
|
||||
//Here we'll check if we should ignore the error (either based on the original header set or the request configuration)
|
||||
if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true) {
|
||||
if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true || (angular.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(originalResponse.status) !== -1)) {
|
||||
//exit/ignore
|
||||
return promise;
|
||||
}
|
||||
|
||||
@@ -522,6 +522,26 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.contentEditingHelper#redirectToRenamedContent
|
||||
* @methodOf umbraco.services.contentEditingHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* For some editors like scripts or entites that have names as ids, these names can change and we need to redirect
|
||||
* to their new paths, this is helper method to do that.
|
||||
*/
|
||||
redirectToRenamedContent: function (id) {
|
||||
//clear the query strings
|
||||
$location.search("");
|
||||
//change to new path
|
||||
$location.path("/" + $routeParams.section + "/" + $routeParams.tree + "/" + $routeParams.method + "/" + id);
|
||||
//don't add a browser history for this
|
||||
$location.replace();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function entityHelper() {
|
||||
|
||||
function getEntityTypeFromSection(section) {
|
||||
if (section === "member") {
|
||||
return "Member";
|
||||
}
|
||||
else if (section === "media") {
|
||||
return "Media";
|
||||
} else {
|
||||
return "Document";
|
||||
}
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
var service = {
|
||||
getEntityTypeFromSection: getEntityTypeFromSection
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.services').factory('entityHelper', entityHelper);
|
||||
|
||||
})();
|
||||
@@ -135,8 +135,13 @@ angular.module('umbraco.services')
|
||||
*
|
||||
* @description
|
||||
* Checks the dictionary for a localized resource string
|
||||
* @param {String} value the area/key to localize
|
||||
* @param {Array} tokens if specified this array will be sent as parameter values
|
||||
* @param {String} value the area/key to localize in the format of 'section_key'
|
||||
* alternatively if no section is set such as 'key' then we assume the key is to be looked in
|
||||
* the 'general' section
|
||||
*
|
||||
* @param {Array} tokens if specified this array will be sent as parameter values
|
||||
* This replaces %0% and %1% etc in the dictionary key value with the passed in strings
|
||||
*
|
||||
* @returns {String} localized resource string
|
||||
*/
|
||||
localize: function (value, tokens) {
|
||||
@@ -146,6 +151,143 @@ angular.module('umbraco.services')
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.localizationService#localizeMany
|
||||
* @methodOf umbraco.services.localizationService
|
||||
*
|
||||
* @description
|
||||
* Checks the dictionary for multipe localized resource strings at once, preventing the need for nested promises
|
||||
* with localizationService.localize
|
||||
*
|
||||
* ##Usage
|
||||
* <pre>
|
||||
* localizationService.localizeMany(["speechBubbles_templateErrorHeader", "speechBubbles_templateErrorText"]).then(function(data){
|
||||
* var header = data[0];
|
||||
* var message = data[1];
|
||||
* notificationService.error(header, message);
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} keys is an array of strings of the area/key to localize in the format of 'section_key'
|
||||
* alternatively if no section is set such as 'key' then we assume the key is to be looked in
|
||||
* the 'general' section
|
||||
*
|
||||
* @returns {Array} An array of localized resource string in the same order
|
||||
*/
|
||||
localizeMany: function(keys) {
|
||||
if(keys){
|
||||
|
||||
//The LocalizationService.localize promises we want to resolve
|
||||
var promises = [];
|
||||
|
||||
for(var i = 0; i < keys.length; i++){
|
||||
promises.push(service.localize(keys[i], undefined));
|
||||
}
|
||||
|
||||
return $q.all(promises).then(function(localizedValues){
|
||||
return localizedValues;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.localizationService#concat
|
||||
* @methodOf umbraco.services.localizationService
|
||||
*
|
||||
* @description
|
||||
* Checks the dictionary for multipe localized resource strings at once & concats them to a single string
|
||||
* Which was not possible with localizationSerivce.localize() due to returning a promise
|
||||
*
|
||||
* ##Usage
|
||||
* <pre>
|
||||
* localizationService.concat(["speechBubbles_templateErrorHeader", "speechBubbles_templateErrorText"]).then(function(data){
|
||||
* var combinedText = data;
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} keys is an array of strings of the area/key to localize in the format of 'section_key'
|
||||
* alternatively if no section is set such as 'key' then we assume the key is to be looked in
|
||||
* the 'general' section
|
||||
*
|
||||
* @returns {String} An concatenated string of localized resource string passed into the function in the same order
|
||||
*/
|
||||
concat: function(keys) {
|
||||
if(keys){
|
||||
|
||||
//The LocalizationService.localize promises we want to resolve
|
||||
var promises = [];
|
||||
|
||||
for(var i = 0; i < keys.length; i++){
|
||||
promises.push(service.localize(keys[i], undefined));
|
||||
}
|
||||
|
||||
return $q.all(promises).then(function(localizedValues){
|
||||
|
||||
//Build a concat string by looping over the array of resolved promises/translations
|
||||
var returnValue = "";
|
||||
|
||||
for(var i = 0; i < localizedValues.length; i++){
|
||||
returnValue += localizedValues[i];
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.localizationService#format
|
||||
* @methodOf umbraco.services.localizationService
|
||||
*
|
||||
* @description
|
||||
* Checks the dictionary for multipe localized resource strings at once & formats a tokenized message
|
||||
* Which was not possible with localizationSerivce.localize() due to returning a promise
|
||||
*
|
||||
* ##Usage
|
||||
* <pre>
|
||||
* localizationService.format(["template_insert", "template_insertSections"], "%0% %1%").then(function(data){
|
||||
* //Will return 'Insert Sections'
|
||||
* var formattedResult = data;
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} keys is an array of strings of the area/key to localize in the format of 'section_key'
|
||||
* alternatively if no section is set such as 'key' then we assume the key is to be looked in
|
||||
* the 'general' section
|
||||
*
|
||||
* @param {String} message is the string you wish to replace containing tokens in the format of %0% and %1%
|
||||
* with the localized resource strings
|
||||
*
|
||||
* @returns {String} An concatenated string of localized resource string passed into the function in the same order
|
||||
*/
|
||||
format: function(keys, message){
|
||||
if(keys){
|
||||
|
||||
//The LocalizationService.localize promises we want to resolve
|
||||
var promises = [];
|
||||
|
||||
for(var i = 0; i < keys.length; i++){
|
||||
promises.push(service.localize(keys[i], undefined));
|
||||
}
|
||||
|
||||
return $q.all(promises).then(function(localizedValues){
|
||||
|
||||
//Replace {0} and {1} etc in message with the localized values
|
||||
for(var i = 0; i < localizedValues.length; i++){
|
||||
var token = "%" + i + "%";
|
||||
var regex = new RegExp(token, "g");
|
||||
|
||||
message = message.replace(regex, localizedValues[i]);
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//This happens after login / auth and assets loading
|
||||
|
||||
@@ -21,7 +21,9 @@ function mediaTypeHelper(mediaTypeResource, $q) {
|
||||
},
|
||||
|
||||
getAllowedImagetypes: function (mediaId){
|
||||
|
||||
|
||||
//TODO: This is horribly inneficient - why make one request per type!?
|
||||
|
||||
// Get All allowedTypes
|
||||
return mediaTypeResource.getAllowedTypes(mediaId)
|
||||
.then(function(types){
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function miniEditorHelper(dialogService, editorState, fileManager, contentEditingHelper, $q) {
|
||||
|
||||
var launched = false;
|
||||
|
||||
function launchMiniEditor(node) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
launched = true;
|
||||
|
||||
//We need to store the current files selected in the file manager locally because the fileManager
|
||||
// is a singleton and is shared globally. The mini dialog will also be referencing the fileManager
|
||||
// and we don't want it to be sharing the same files as the main editor. So we'll store the current files locally here,
|
||||
// clear them out and then launch the dialog. When the dialog closes, we'll reset the fileManager to it's previous state.
|
||||
var currFiles = _.groupBy(fileManager.getFiles(), "alias");
|
||||
fileManager.clearFiles();
|
||||
|
||||
//We need to store the original editorState entity because it will need to change when the mini editor is loaded so that
|
||||
// any property editors that are working with editorState get given the correct entity, otherwise strange things will
|
||||
// start happening.
|
||||
var currEditorState = editorState.getCurrent();
|
||||
|
||||
dialogService.open({
|
||||
template: "views/common/dialogs/content/edit.html",
|
||||
id: node.id,
|
||||
closeOnSave: true,
|
||||
tabFilter: ["Generic properties"],
|
||||
callback: function (data) {
|
||||
|
||||
//set the node name back
|
||||
node.name = data.name;
|
||||
|
||||
//reset the fileManager to what it was
|
||||
fileManager.clearFiles();
|
||||
_.each(currFiles, function (val, key) {
|
||||
fileManager.setFiles(key, _.map(currFiles['upload'], function (i) { return i.file; }));
|
||||
});
|
||||
|
||||
//reset the editor state
|
||||
editorState.set(currEditorState);
|
||||
|
||||
//Now we need to check if the content item that was edited was actually the same content item
|
||||
// as the main content editor and if so, update all property data
|
||||
if (data.id === currEditorState.id) {
|
||||
var changed = contentEditingHelper.reBindChangedProperties(currEditorState, data);
|
||||
}
|
||||
|
||||
launched = false;
|
||||
|
||||
deferred.resolve(data);
|
||||
|
||||
},
|
||||
closeCallback: function () {
|
||||
//reset the fileManager to what it was
|
||||
fileManager.clearFiles();
|
||||
_.each(currFiles, function (val, key) {
|
||||
fileManager.setFiles(key, _.map(currFiles['upload'], function (i) { return i.file; }));
|
||||
});
|
||||
|
||||
//reset the editor state
|
||||
editorState.set(currEditorState);
|
||||
|
||||
launched = false;
|
||||
|
||||
deferred.reject();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
|
||||
}
|
||||
|
||||
var service = {
|
||||
launchMiniEditor: launchMiniEditor
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
|
||||
angular.module('umbraco.services').factory('miniEditorHelper', miniEditorHelper);
|
||||
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,23 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function platformService() {
|
||||
|
||||
function isMac() {
|
||||
return navigator.platform.toUpperCase().indexOf('MAC')>=0;
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
var service = {
|
||||
isMac: isMac
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.services').factory('platformService', platformService);
|
||||
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,186 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function templateHelperService(localizationService) {
|
||||
|
||||
//crappy hack due to dictionary items not in umbracoNode table
|
||||
function getInsertDictionarySnippet(nodeName) {
|
||||
return "@Umbraco.GetDictionaryValue(\"" + nodeName + "\")";
|
||||
}
|
||||
|
||||
function getInsertPartialSnippet(parentId, nodeName) {
|
||||
|
||||
var partialViewName = nodeName.replace(".cshtml", "");
|
||||
|
||||
if(parentId) {
|
||||
partialViewName = parentId + "/" + partialViewName;
|
||||
}
|
||||
|
||||
return "@Html.Partial(\"" + partialViewName + "\")";
|
||||
}
|
||||
|
||||
function getQuerySnippet(queryExpression) {
|
||||
var code = "\n@{\n" + "\tvar selection = " + queryExpression + ";\n}\n";
|
||||
code += "<ul>\n" +
|
||||
"\t@foreach(var item in selection){\n" +
|
||||
"\t\t<li>\n" +
|
||||
"\t\t\t<a href=\"@item.Url\">@item.Name</a>\n" +
|
||||
"\t\t</li>\n" +
|
||||
"\t}\n" +
|
||||
"</ul>\n\n";
|
||||
return code;
|
||||
}
|
||||
|
||||
function getRenderBodySnippet() {
|
||||
return "@RenderBody()";
|
||||
}
|
||||
|
||||
function getRenderSectionSnippet(sectionName, mandatory) {
|
||||
return "@RenderSection(\"" + sectionName + "\", " + mandatory + ")";
|
||||
}
|
||||
|
||||
function getAddSectionSnippet(sectionName) {
|
||||
return "@section " + sectionName + "\r\n{\r\n\r\n\t{0}\r\n\r\n}\r\n";
|
||||
}
|
||||
|
||||
function getGeneralShortcuts(){
|
||||
return {
|
||||
"name": localizationService.localize("shortcuts_generalHeader"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("buttons_undo"),
|
||||
"keys": [{ "key": "ctrl" }, { "key": "z" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("buttons_redo"),
|
||||
"keys": [{ "key": "ctrl" }, { "key": "y" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("buttons_save"),
|
||||
"keys": [{ "key": "ctrl" }, { "key": "s" }]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
function getEditorShortcuts(){
|
||||
return {
|
||||
"name": localizationService.localize("shortcuts_editorHeader"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_commentLine"),
|
||||
"keys": [{ "key": "ctrl" }, { "key": "/" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_removeLine"),
|
||||
"keys": [{ "key": "ctrl" }, { "key": "d" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_copyLineUp"),
|
||||
"keys": {
|
||||
"win": [{ "key": "alt" }, { "key": "shift" }, { "key": "up" }],
|
||||
"mac": [{ "key": "cmd" }, { "key": "alt" }, { "key": "up" }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_copyLineDown"),
|
||||
"keys": {
|
||||
"win": [{ "key": "alt" }, { "key": "shift" }, { "key": "down" }],
|
||||
"mac": [{ "key": "cmd" }, { "key": "alt" }, { "key": "down" }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_moveLineUp"),
|
||||
"keys": [{ "key": "alt" }, { "key": "up" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_moveLineDown"),
|
||||
"keys": [{ "key": "alt" }, { "key": "down" }]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
function getTemplateEditorShortcuts(){
|
||||
return {
|
||||
"name": "Umbraco", //No need to localise Umbraco is the same in all languages :)
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.format(["template_insert", "template_insertPageField"], "%0% %1%"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "v" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.format(["template_insert", "template_insertPartialView"], "%0% %1%"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.format(["template_insert", "template_insertDictionaryItem"], "%0% %1%"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.format(["template_insert", "template_insertMacro"], "%0% %1%"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "m" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("template_queryBuilder"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "q" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.format(["template_insert", "template_insertSections"], "%0% %1%"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "s" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("template_mastertemplate"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
function getPartialViewEditorShortcuts(){
|
||||
return {
|
||||
"name": "Umbraco", //No need to localise Umbraco is the same in all languages :)
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.format(["template_insert", "template_insertPageField"], "%0% %1%"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "v" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.format(["template_insert", "template_insertDictionaryItem"], "%0% %1%"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.format(["template_insert", "template_insertMacro"], "%0% %1%"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "m" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("template_queryBuilder"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "q" }]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
var service = {
|
||||
getInsertDictionarySnippet: getInsertDictionarySnippet,
|
||||
getInsertPartialSnippet: getInsertPartialSnippet,
|
||||
getQuerySnippet: getQuerySnippet,
|
||||
getRenderBodySnippet: getRenderBodySnippet,
|
||||
getRenderSectionSnippet: getRenderSectionSnippet,
|
||||
getAddSectionSnippet: getAddSectionSnippet,
|
||||
getGeneralShortcuts: getGeneralShortcuts,
|
||||
getEditorShortcuts: getEditorShortcuts,
|
||||
getTemplateEditorShortcuts: getTemplateEditorShortcuts,
|
||||
getPartialViewEditorShortcuts: getPartialViewEditorShortcuts
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.services').factory('templateHelper', templateHelperService);
|
||||
|
||||
|
||||
})();
|
||||
@@ -95,11 +95,20 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
|
||||
if(selectedElm.nodeName === 'IMG'){
|
||||
var img = $(selectedElm);
|
||||
|
||||
var hasUdi = img.attr("data-udi") ? true : false;
|
||||
|
||||
currentTarget = {
|
||||
altText: img.attr("alt"),
|
||||
url: img.attr("src"),
|
||||
id: img.attr("rel")
|
||||
url: img.attr("src")
|
||||
};
|
||||
|
||||
if (hasUdi) {
|
||||
currentTarget["udi"] = img.attr("data-udi");
|
||||
}
|
||||
else {
|
||||
currentTarget["id"] = img.attr("rel");
|
||||
}
|
||||
}
|
||||
|
||||
userService.getCurrentUser().then(function(userData) {
|
||||
@@ -115,13 +124,23 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
insertMediaInEditor: function(editor, img) {
|
||||
if(img) {
|
||||
|
||||
var hasUdi = img.udi ? true : false;
|
||||
|
||||
var data = {
|
||||
alt: img.altText || "",
|
||||
src: (img.url) ? img.url : "nothing.jpg",
|
||||
rel: img.id,
|
||||
'data-id': img.id,
|
||||
src: (img.url) ? img.url : "nothing.jpg",
|
||||
id: '__mcenew'
|
||||
};
|
||||
};
|
||||
|
||||
if (hasUdi) {
|
||||
data["data-udi"] = img.udi;
|
||||
}
|
||||
else {
|
||||
//Considering these fixed because UDI will now be used and thus
|
||||
// we have no need for rel http://issues.umbraco.org/issue/U4-6228, http://issues.umbraco.org/issue/U4-6595
|
||||
data["rel"] = img.id;
|
||||
data["data-id"] = img.id;
|
||||
}
|
||||
|
||||
editor.insertContent(editor.dom.createHTML('img', data));
|
||||
|
||||
@@ -672,8 +691,17 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
|
||||
//locallink detection, we do this here, to avoid poluting the dialogservice
|
||||
//so the dialog service can just expect to get a node-like structure
|
||||
if(currentTarget.url.indexOf("localLink:") > 0){
|
||||
currentTarget.id = currentTarget.url.substring(currentTarget.url.indexOf(":")+1,currentTarget.url.length-1);
|
||||
if (currentTarget.url.indexOf("localLink:") > 0) {
|
||||
var linkId = currentTarget.url.substring(currentTarget.url.indexOf(":") + 1, currentTarget.url.length - 1);
|
||||
//we need to check if this is an INT or a UDI
|
||||
var parsedIntId = parseInt(linkId, 10);
|
||||
if (isNaN(parsedIntId)) {
|
||||
//it's a UDI
|
||||
currentTarget.udi = linkId;
|
||||
}
|
||||
else {
|
||||
currentTarget.id = linkId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,27 +744,36 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
insertLinkInEditor: function(editor, target, anchorElm) {
|
||||
|
||||
var href = target.url;
|
||||
// We want to use the Udi. If it is set, we use it, else fallback to id, and finally to null
|
||||
var hasUdi = target.udi ? true : false;
|
||||
var id = hasUdi ? target.udi : (target.id ? target.id : null);
|
||||
|
||||
//Create a json obj used to create the attributes for the tag
|
||||
function createElemAttributes() {
|
||||
var a = {
|
||||
href: href,
|
||||
title: target.name,
|
||||
target: target.target ? target.target : null,
|
||||
rel: target.rel ? target.rel : null
|
||||
};
|
||||
if (hasUdi) {
|
||||
a["data-udi"] = target.udi;
|
||||
}
|
||||
else if (target.id) {
|
||||
a["data-id"] = target.id;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
function insertLink() {
|
||||
if (anchorElm) {
|
||||
editor.dom.setAttribs(anchorElm, {
|
||||
href: href,
|
||||
title: target.name,
|
||||
target: target.target ? target.target : null,
|
||||
rel: target.rel ? target.rel : null,
|
||||
'data-id': target.id ? target.id : null
|
||||
});
|
||||
editor.dom.setAttribs(anchorElm, createElemAttributes());
|
||||
|
||||
editor.selection.select(anchorElm);
|
||||
editor.execCommand('mceEndTyping');
|
||||
} else {
|
||||
editor.execCommand('mceInsertLink', false, {
|
||||
href: href,
|
||||
title: target.name,
|
||||
target: target.target ? target.target : null,
|
||||
rel: target.rel ? target.rel : null,
|
||||
'data-id': target.id ? target.id : null
|
||||
});
|
||||
}
|
||||
else {
|
||||
editor.execCommand('mceInsertLink', false, createElemAttributes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -746,8 +783,10 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
}
|
||||
|
||||
//if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set
|
||||
if(target.id && (angular.isUndefined(target.isMedia) || !target.isMedia)){
|
||||
href = "/{localLink:" + target.id + "}";
|
||||
if(id && (angular.isUndefined(target.isMedia) || !target.isMedia)){
|
||||
|
||||
href = "/{localLink:" + id + "}";
|
||||
|
||||
insertLink();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ angular.module('umbraco.services')
|
||||
var currentUser = null;
|
||||
var lastUserId = null;
|
||||
var loginDialog = null;
|
||||
|
||||
//this tracks the last date/time that the user's remainingAuthSeconds was updated from the server
|
||||
// this is used so that we know when to go and get the user's remaining seconds directly.
|
||||
var lastServerTimeoutSet = null;
|
||||
@@ -25,7 +26,7 @@ angular.module('umbraco.services')
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onLoginDialogClose(success) {
|
||||
loginDialog = null;
|
||||
@@ -182,8 +183,7 @@ angular.module('umbraco.services')
|
||||
/** Internal method to display the login dialog */
|
||||
_showLoginDialog: function () {
|
||||
openLoginDialog();
|
||||
},
|
||||
|
||||
},
|
||||
/** Returns a promise, sends a request to the server to check if the current cookie is authorized */
|
||||
isAuthenticated: function () {
|
||||
//if we've got a current user then just return true
|
||||
@@ -199,17 +199,18 @@ angular.module('umbraco.services')
|
||||
authenticate: function (login, password) {
|
||||
|
||||
return authResource.performLogin(login, password)
|
||||
.then(function (data) {
|
||||
.then(this.setAuthenticationSuccessful);
|
||||
},
|
||||
setAuthenticationSuccessful:function (data) {
|
||||
|
||||
//when it's successful, return the user data
|
||||
setCurrentUser(data);
|
||||
//when it's successful, return the user data
|
||||
setCurrentUser(data);
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "credentials" };
|
||||
|
||||
//broadcast a global event
|
||||
eventsService.emit("app.authenticated", result);
|
||||
return result;
|
||||
});
|
||||
//broadcast a global event
|
||||
eventsService.emit("app.authenticated", result);
|
||||
return result;
|
||||
},
|
||||
|
||||
/** Logs the user out
|
||||
|
||||
@@ -26,10 +26,35 @@ app.run(['userService', '$log', '$rootScope', '$location', 'navigationService',
|
||||
/** execute code on each successful route */
|
||||
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
|
||||
|
||||
if(current.params.section){
|
||||
$rootScope.locationTitle = current.params.section + " - " + $location.$$host;
|
||||
var deployConfig = Umbraco.Sys.ServerVariables.deploy;
|
||||
var deployEnv, deployEnvTitle;
|
||||
if (deployConfig) {
|
||||
deployEnv = Umbraco.Sys.ServerVariables.deploy.CurrentWorkspace;
|
||||
deployEnvTitle = "(" + deployEnv + ") ";
|
||||
}
|
||||
|
||||
if(current.params.section) {
|
||||
|
||||
//Uppercase the current section, content, media, settings, developer, forms
|
||||
var currentSection = current.params.section.charAt(0).toUpperCase() + current.params.section.slice(1);
|
||||
|
||||
var baseTitle = currentSection + " - " + $location.$$host;
|
||||
|
||||
//Check deploy for Global Umbraco.Sys obj workspace
|
||||
if(deployEnv){
|
||||
$rootScope.locationTitle = deployEnvTitle + baseTitle;
|
||||
}
|
||||
else {
|
||||
$rootScope.locationTitle = baseTitle;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if(deployEnv) {
|
||||
$rootScope.locationTitle = deployEnvTitle + "Umbraco - " + $location.$$host;
|
||||
}
|
||||
|
||||
$rootScope.locationTitle = "Umbraco - " + $location.$$host;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
<input type="submit" ng-disabled="myForm.$invalid || checking" ng-class="{disabled:myForm.$invalid}"
|
||||
value="Continue" class="btn btn-success" />
|
||||
|
||||
<button class="btn" ng-click="restart()">Go back</button>
|
||||
<button class="btn btn-info" ng-click="restart()">Go back</button>
|
||||
|
||||
<span class="inline-help" ng-if="checking" ng-animate="'fade'">
|
||||
Validating your database connection...
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To read a report of changes between your current version <strong>{{installer.current.model.currentVersion}}</strong> and this version your upgrading to <strong>{{installer.current.model.newVersion}}</strong>
|
||||
To read a report of changes between your current version <strong>{{installer.current.model.currentVersion}}</strong> and this version you're upgrading to <strong>{{installer.current.model.newVersion}}</strong>
|
||||
</p>
|
||||
<p>
|
||||
<a ng-href="{{installer.current.model.reportUrl}}" target="_blank" class="btn">View Report</a>
|
||||
<a ng-href="{{installer.current.model.reportUrl}}" target="_blank" class="btn btn-info">View Report</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -46,16 +46,21 @@
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" id="subscribeToNewsLetter" name="subscribeToNewsLetter"
|
||||
ng-model="installer.current.model.subscribeToNewsLetter" /> Keep me updated on Umbraco Versions, Security Bulletins and Community News</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="subscribeToNewsLetter"
|
||||
name="subscribeToNewsLetter"
|
||||
ng-model="installer.current.model.subscribeToNewsLetter" />
|
||||
Keep me updated on Umbraco Versions, Security Bulletins and Community News
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{disabled:myForm.$invalid}">
|
||||
<div class="controls">
|
||||
<input type="submit" ng-disabled="myForm.$invalid" value="Install" class="btn btn-success" />
|
||||
<a href class="btn btn-neutral control-customize" ng-disabled="myForm.$invalid" ng-click="validateAndForward()">Customize</a>
|
||||
<a href class="btn btn-info control-customize" ng-disabled="myForm.$invalid" ng-click="validateAndForward()">Customize</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
margin-bottom: @baseLineHeight;
|
||||
background-color: @warningBackground;
|
||||
border: 1px solid @warningBorder;
|
||||
.border-radius(@baseBorderRadius);
|
||||
.border-radius(@alertBorderRadius);
|
||||
}
|
||||
.alert,
|
||||
.alert h4,
|
||||
@@ -67,9 +67,9 @@
|
||||
}
|
||||
|
||||
.alert-form {
|
||||
background-color: #ECECEC;
|
||||
border: 1px solid @gray !important;
|
||||
color: @gray;
|
||||
background-color: @gray-10;
|
||||
border: 1px solid @gray-3 !important;
|
||||
color: @gray-3;
|
||||
}
|
||||
|
||||
.alert-form.-no-border {
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
|
||||
.alert-form h4 {
|
||||
color: @gray;
|
||||
color: @gray-3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@ body {
|
||||
line-height: @baseLineHeight;
|
||||
color: @textColor;
|
||||
background-color: @bodyBackground;
|
||||
|
||||
// better font rendering
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +147,7 @@ body {
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
padding-top: 100px;
|
||||
border-right: 1px solid @grayLight;
|
||||
border-right: 1px solid @purple-l3;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
@@ -197,8 +202,8 @@ body {
|
||||
right: -5px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: @grayLighter;
|
||||
border: solid 1px @grayLight;
|
||||
background-color: @gray-10;
|
||||
border: solid 1px @purple-l3;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
position:absolute;
|
||||
|
||||
@@ -111,17 +111,24 @@
|
||||
@import "components/umb-empty-state.less";
|
||||
@import "components/umb-property-editor.less";
|
||||
@import "components/umb-iconpicker.less";
|
||||
@import "components/umb-insert-code-box.less";
|
||||
@import "components/umb-packages.less";
|
||||
@import "components/umb-package-local-install.less";
|
||||
@import "components/umb-lightbox.less";
|
||||
@import "components/umb-avatar.less";
|
||||
@import "components/umb-progress-bar.less";
|
||||
@import "components/umb-querybuilder.less";
|
||||
@import "components/umb-pagination.less";
|
||||
@import "components/umb-mini-list-view.less";
|
||||
|
||||
@import "components/buttons/umb-button.less";
|
||||
@import "components/buttons/umb-button-group.less";
|
||||
@import "components/buttons/umb-era-button.less";
|
||||
|
||||
@import "components/notifications/umb-notifications.less";
|
||||
@import "components/umb-file-dropzone.less";
|
||||
@import "components/umb-node-preview.less";
|
||||
@import "components/umb-mini-editor.less";
|
||||
|
||||
// Utilities
|
||||
@import "utilities/_flexbox.less";
|
||||
@@ -132,6 +139,7 @@
|
||||
//page specific styles
|
||||
@import "pages/document-type-editor.less";
|
||||
@import "pages/login.less";
|
||||
@import "pages/welcome-dashboard.less";
|
||||
|
||||
|
||||
//used for property editors
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Core
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 4px 12px;
|
||||
padding: 6px 14px;
|
||||
margin-bottom: 0; // For input.btn
|
||||
font-size: @baseFontSize;
|
||||
line-height: @baseLineHeight;
|
||||
@@ -18,14 +18,15 @@
|
||||
cursor: pointer;
|
||||
background: @btnBackground;
|
||||
color: @black;
|
||||
border: 1px solid @btnBorder;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
border-radius: 3px;
|
||||
|
||||
// Hover/focus state
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: @btnBackgroundHighlight;
|
||||
color: @grayDark;
|
||||
color: @gray-4;
|
||||
background-position: 0 -15px;
|
||||
text-decoration: none;
|
||||
|
||||
@@ -64,14 +65,11 @@
|
||||
-webkit-box-shadow:none;
|
||||
}
|
||||
|
||||
.btn-group > .btn:first-child,
|
||||
.btn-group > .btn:last-child,
|
||||
.btn-group > .dropdown-toggle {
|
||||
border-radius: 0;
|
||||
.btn-group .btn.dropdown-toggle {
|
||||
border-left-width: 1px;
|
||||
border-left-style: solid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Button Sizes
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -138,7 +136,7 @@ input[type="button"] {
|
||||
// Round button
|
||||
.btn-round{
|
||||
font-size: 24px;
|
||||
color: @gray;
|
||||
color: @gray-3;
|
||||
background: @white;
|
||||
|
||||
line-height: 32px;
|
||||
@@ -167,6 +165,16 @@ input[type="button"] {
|
||||
color: rgba(255,255,255,.75);
|
||||
}
|
||||
|
||||
.btn-primary,
|
||||
.btn-warning,
|
||||
.btn-danger,
|
||||
.btn-success,
|
||||
.btn-info,
|
||||
.btn-inverse,
|
||||
.btn-neutral {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
// Set the backgrounds
|
||||
// -------------------------
|
||||
.btn-primary {
|
||||
@@ -196,16 +204,16 @@ input[type="button"] {
|
||||
// Neutral appears as lighter gray
|
||||
.btn-neutral {
|
||||
.buttonBackground(@btnNeutralBackground, @btnNeutralBackgroundHighlight);
|
||||
color: #656565;
|
||||
color: @gray-5;
|
||||
// Hover/focus state
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: #656565;
|
||||
color: @gray-5;
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&[disabled] {
|
||||
color:#656565;
|
||||
color: @gray-5;
|
||||
.opacity(65);
|
||||
}
|
||||
|
||||
@@ -217,11 +225,11 @@ input[type="button"] {
|
||||
padding: 15px 50px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
background: @blue;
|
||||
background: @green;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background: #2b8ee3;
|
||||
font-weight: bold;
|
||||
&:hover {
|
||||
background: @green-d1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +289,7 @@ input[type="submit"].btn {
|
||||
}
|
||||
.btn-link[disabled]:hover,
|
||||
.btn-link[disabled]:focus {
|
||||
color: @grayDark;
|
||||
color: @gray-4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ body {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
width: ~"(calc(~'100%' - ~'80px'))"; // 80px is the fixed left menu for toggling the different browser sizes
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
@@ -270,10 +271,10 @@ a, a:hover{
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin-left: -80px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-family: "Lato", Helvetica, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
background: #1D1D1D;
|
||||
background: #413659;
|
||||
-webkit-transition: all 0.2s ease-in-out;
|
||||
-moz-transition: all 0.2s ease-in-out;
|
||||
transition: all 0.2s ease-in-out;
|
||||
@@ -282,8 +283,8 @@ a, a:hover{
|
||||
|
||||
.avatar {
|
||||
text-align:center;
|
||||
padding: 25px 0 29px 0;
|
||||
border-bottom: 1px solid #343434;
|
||||
padding: 27px 0 29px 0;
|
||||
border-bottom: 1px solid #2E2246;
|
||||
}
|
||||
|
||||
.help {
|
||||
@@ -295,7 +296,7 @@ a, a:hover{
|
||||
margin: 0;
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
color: #d9d9d9;
|
||||
color: #D8D7D9;
|
||||
opacity: 0.4;
|
||||
-webkit-transition: all .3s linear;
|
||||
-moz-transition: all .3s linear;
|
||||
@@ -304,7 +305,7 @@ a, a:hover{
|
||||
|
||||
ul.sections {
|
||||
display: block;
|
||||
background: #1d1d1d;
|
||||
background: #413659;
|
||||
height: 100%;
|
||||
position:absolute;
|
||||
top: 90px;
|
||||
@@ -320,7 +321,7 @@ ul.sections {
|
||||
|
||||
ul.sections li {
|
||||
display: block;
|
||||
border-left: 4px #1d1d1d solid;
|
||||
border-left: 4px #413659 solid;
|
||||
-webkit-transition: all .3s linear;
|
||||
-moz-transition: all .3s linear;
|
||||
transition: all .3s linear;
|
||||
@@ -328,7 +329,7 @@ ul.sections li {
|
||||
|
||||
.fix-left-menu ul.sections li a span,
|
||||
.fix-left-menu ul.sections li a i {
|
||||
color: #d9d9d9;
|
||||
color: #8d869b;
|
||||
-webkit-transition: all .3s linear;
|
||||
-moz-transition: all .3s linear;
|
||||
transition: all .3s linear;
|
||||
@@ -342,12 +343,11 @@ ul.sections li a {
|
||||
margin: 0 0 0 -4px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid #343434;
|
||||
border-bottom: 1px solid #2E2246;
|
||||
}
|
||||
|
||||
ul.sections li a i {
|
||||
font-size: 30px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
ul.sections li a span {
|
||||
@@ -357,8 +357,16 @@ ul.sections li a span {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
ul.sections li.current {
|
||||
background-color: #2E2246;
|
||||
}
|
||||
|
||||
ul.sections li.current a i {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
ul.sections li.current, ul.sections li:hover {
|
||||
border-left: 4px #f57020 solid;
|
||||
border-left: 4px #00AEA2 solid;
|
||||
}
|
||||
|
||||
.fix-left-menu:hover ul.sections li a span,
|
||||
@@ -533,7 +541,7 @@ h4.panel-title {
|
||||
.field-title {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
font-size: 11px;
|
||||
font-size: 12px;
|
||||
color: #d9d9d9;
|
||||
}
|
||||
|
||||
@@ -651,7 +659,7 @@ h4.panel-title {
|
||||
padding: 0;
|
||||
margin-top: -9px;
|
||||
margin-right: 1px;
|
||||
font-size: 11px;
|
||||
font-size: 12px;
|
||||
color: #d9d9d9;
|
||||
text-align: right;
|
||||
background-color: transparent;
|
||||
@@ -684,7 +692,7 @@ h4.panel-title {
|
||||
}
|
||||
|
||||
.canvasdesigner select {
|
||||
font-size: 11px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.canvasdesigner .sp-dd {
|
||||
@@ -794,7 +802,7 @@ h4.panel-title {
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
opacity: 1.0;
|
||||
box-shadow: 0 0 0 29px #ECECEC, 0 0 0 30px #C4C4C4;
|
||||
box-shadow: 0 0 0 29px #E9E9EB, 0 0 0 30px #D8D7D9;
|
||||
transition: all 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,46 @@
|
||||
.umb-button-group__toggle {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
.umb-button-group__sub-buttons.-align-right {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
.umb-button-group {
|
||||
|
||||
.umb-button__button {
|
||||
border-radius: 3px 0px 0px 3px;
|
||||
}
|
||||
|
||||
.umb-button-group__toggle {
|
||||
border-radius: 0px 3px 3px 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// hack for umb-era-button
|
||||
.umb-era-button-group {
|
||||
|
||||
display: flex;
|
||||
|
||||
.umb-era-button:first-child {
|
||||
padding-right: 15px;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.umb-era-button.umb-button-group__toggle {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
border-radius: 0 3px 3px 0;
|
||||
border-left-style: solid;
|
||||
border-left-width: 1px;
|
||||
border-left-color: rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.umb-era-button.umb-button-group__toggle .caret {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
.umb-button {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.umb-button__button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.umb-button__button {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.umb-button__content {
|
||||
opacity: 1;
|
||||
transition: opacity 0.25s ease;
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
.umb-era-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
height: 38px;
|
||||
line-height: 1;
|
||||
max-width: 100%;
|
||||
padding: 0 18px;
|
||||
color: #202129;
|
||||
background-color: #edeeee;
|
||||
text-decoration: none !important;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
border-radius: 3px;
|
||||
border: 0 none;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
transition: background-color 80ms ease, color 80ms ease;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.umb-era-button:hover,
|
||||
.umb-era-button:active {
|
||||
color: #484848;
|
||||
background-color: #e1e2e2;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
.umb-era-button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.umb-era-button.-blue {
|
||||
background: @blue;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.umb-era-button.-blue:hover {
|
||||
background-color: @blueDark;
|
||||
}
|
||||
|
||||
.umb-era-button.-red {
|
||||
background: @btnDangerBackground;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.umb-era-button.-red:hover {
|
||||
background-color: darken(@btnDangerBackground, 5%);
|
||||
}
|
||||
|
||||
.umb-era-button.-green {
|
||||
background: @green;
|
||||
color: @white;
|
||||
}
|
||||
|
||||
.umb-era-button.-green:hover {
|
||||
background-color: @green-d1;
|
||||
}
|
||||
|
||||
.umb-era-button.-link {
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.umb-era-button.-link:hover {
|
||||
background-color: transparent;
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.umb-era-button.-inactive {
|
||||
cursor: not-allowed;
|
||||
color: #BBB;
|
||||
background: #EAE7E7;
|
||||
}
|
||||
|
||||
.umb-era-button.-inactive:hover {
|
||||
color: #BBB;
|
||||
background: #EAE7E7;
|
||||
}
|
||||
|
||||
|
||||
.umb-era-button.-full-width {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.umb-era-button.umb-button--s {
|
||||
height: 30px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.umb-era-button.-white {
|
||||
background-color: @white;
|
||||
|
||||
&:hover {
|
||||
opacity: .9;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-era-button.-text-black {
|
||||
color: @black;
|
||||
}
|
||||
|
||||
/* icons */
|
||||
|
||||
.umb-era-button i {
|
||||
margin-right: 5px;
|
||||
}
|
||||