Umbraco 7.15.3

This commit is contained in:
2019-11-23 21:51:02 -05:00
parent 7e9bd9ee5b
commit 866cfa29d7
219 changed files with 66394 additions and 66487 deletions
+411 -96
View File
@@ -1780,6 +1780,19 @@ In the following example you see how to run some custom logic before a step goes
}
angular.module('umbraco.directives').directive('umbTour', TourDirective);
}());
/**
@ngdoc directive
@name umbraco.directives.directive:umbTourStep
@restrict E
@scope
@description
<b>Added in Umbraco 7.8</b>. The tour step component is a component that can be used in custom views for tour steps.
@param {callback} onClose The callback which should be performened when the close button of the tour step is clicked
@param {boolean=} hideClose A boolean indicating if the close button needs to be shown
**/
(function () {
'use strict';
function TourStepDirective() {
@@ -1806,6 +1819,19 @@ In the following example you see how to run some custom logic before a step goes
}
angular.module('umbraco.directives').directive('umbTourStep', TourStepDirective);
}());
/**
@ngdoc directive
@name umbraco.directives.directive:umbTourStepContent
@restrict E
@scope
@description
<b>Added in Umbraco 7.8</b>. The tour step content component is a component that can be used in custom views for tour steps.
It's meant to be used in the umb-tour-step directive.
All markup in the body of the directive will be shown after the content attribute
@param {string} content The content that needs to be shown
**/
(function () {
'use strict';
function TourStepContentDirective() {
@@ -1820,6 +1846,20 @@ In the following example you see how to run some custom logic before a step goes
}
angular.module('umbraco.directives').directive('umbTourStepContent', TourStepContentDirective);
}());
/**
@ngdoc directive
@name umbraco.directives.directive:umbTourStepCounter
@restrict E
@scope
@description
<b>Added in Umbraco 7.8</b>. The tour step counter component is a component that can be used in custom views for tour steps.
It's meant to be used in the umb-tour-step-footer directive. It will show the progress you have made in a tour eg. step 2/12
@param {int} currentStep The current step the tour is on
@param {int} totalSteps The current step the tour is on
**/
(function () {
'use strict';
function TourStepCounterDirective() {
@@ -1836,6 +1876,18 @@ In the following example you see how to run some custom logic before a step goes
}
angular.module('umbraco.directives').directive('umbTourStepCounter', TourStepCounterDirective);
}());
/**
@ngdoc directive
@name umbraco.directives.directive:umbTourStepFooter
@restrict E
@scope
@description
<b>Added in Umbraco 7.8</b>. The tour step footer component is a component that can be used in custom views for tour steps. It's meant to be used in the umb-tour-step directive.
All markup in the body of the directive will be shown as the footer of the tour step
**/
(function () {
'use strict';
function TourStepFooterDirective() {
@@ -1849,6 +1901,18 @@ In the following example you see how to run some custom logic before a step goes
}
angular.module('umbraco.directives').directive('umbTourStepFooter', TourStepFooterDirective);
}());
/**
@ngdoc directive
@name umbraco.directives.directive:umbTourStepHeader
@restrict E
@scope
@description
<b>Added in Umbraco 7.8</b>. The tour step header component is a component that can be used in custom views for tour steps. It's meant to be used in the umb-tour-step directive.
@param {string} title The title that needs to be shown
**/
(function () {
'use strict';
function TourStepHeaderDirective() {
@@ -2131,6 +2195,7 @@ Use this directive to render a button with a dropdown of alternative actions.
<umb-toggle
checked="vm.checked"
disabled="vm.disabled"
on-click="vm.toggle()"
show-labels="true"
label-on="Start"
@@ -2151,6 +2216,7 @@ Use this directive to render a button with a dropdown of alternative actions.
var vm = this;
vm.checked = false;
vm.disabled = false;
vm.toggle = toggle;
@@ -2165,6 +2231,7 @@ Use this directive to render a button with a dropdown of alternative actions.
</pre>
@param {boolean} checked Set to <code>true</code> or <code>false</code> to toggle the switch.
@param {boolean} disabled Set to <code>true</code> or <code>false</code> to disable/enable the switch.
@param {callback} onClick The function which should be called when the toggle is clicked.
@param {string=} showLabels Set to <code>true</code> or <code>false</code> to show a "On" or "Off" label next to the switch.
@param {string=} labelOn Set a custom label for when the switched is turned on. It will default to "On".
@@ -2215,6 +2282,7 @@ Use this directive to render a button with a dropdown of alternative actions.
templateUrl: 'views/components/buttons/umb-toggle.html',
scope: {
checked: '=',
disabled: '=',
onClick: '&',
labelOn: '@?',
labelOff: '@?',
@@ -2248,12 +2316,19 @@ Use this directive to render a button with a dropdown of alternative actions.
createButtons(content);
editorState.set($scope.content);
//We fetch all ancestors of the node to generate the footer breadcrumb navigation
if (!$scope.page.isNew) {
if (content.parentId && content.parentId !== -1) {
entityResource.getAncestors(content.id, 'document').then(function (anc) {
$scope.ancestors = anc;
});
if (content.parentId && content.parentId !== -1) {
var ancestorIds = content.path.split(',');
ancestorIds.shift();
// Remove -1
if ($scope.page.isNew) {
ancestorIds.pop(); // Remove 0
}
entityResource.getByIds(ancestorIds, 'document').then(function (anc) {
$scope.ancestors = anc;
if ($scope.page.isNew) {
$scope.ancestors.push({ name: 'Untitled' });
}
});
}
evts.push(eventsService.on('editors.content.changePublishDate', function (event, args) {
createButtons(args.node);
@@ -2370,6 +2445,9 @@ Use this directive to render a button with a dropdown of alternative actions.
//we are creating so get an empty content item
$scope.getScaffoldMethod()().then(function (data) {
$scope.content = data;
if (data.isChildOfListView && data.trashed === false) {
$scope.page.listViewPath = $routeParams.page ? '/content/content/edit/' + data.parentId + '?page=' + $routeParams.page : '/content/content/edit/' + data.parentId;
}
init($scope.content);
resetLastListPageNumber($scope.content);
$scope.page.loading = false;
@@ -2554,7 +2632,7 @@ Use this directive to render a button with a dropdown of alternative actions.
}());
(function () {
'use strict';
function ContentNodeInfoDirective($timeout, $location, logResource, eventsService, userService, localizationService, dateHelper) {
function ContentNodeInfoDirective($timeout, $location, logResource, eventsService, userService, localizationService, dateHelper, redirectUrlsResource) {
function link(scope, element, attrs, ctrl) {
var evts = [];
var isInfoTab = false;
@@ -2586,10 +2664,19 @@ Use this directive to render a button with a dropdown of alternative actions.
formatDatesToLocal();
// Make sure to set the node status
setNodePublishStatus(scope.node);
//default setting for redirect url management
scope.urlTrackerDisabled = false;
// Declare a fallback URL for the <umb-node-preview/> directive
if (scope.documentType !== null) {
scope.previewOpenUrl = '#/settings/documenttypes/edit/' + scope.documentType.id;
}
// only allow configuring scheduled publishing if the user has publish ("U") and unpublish ("Z") permissions on this node
scope.allowScheduledPublishing = _.contains(scope.node.allowedActions, 'U') && _.contains(scope.node.allowedActions, 'Z');
ensureUniqueUrls();
}
// make sure we don't show duplicate URLs in case multiple URL providers assign the same URLs to the content (see issue 3842 for details)
function ensureUniqueUrls() {
scope.node.urls = _.uniq(scope.node.urls);
}
scope.auditTrailPageChange = function (pageNumber) {
scope.auditTrailOptions.pageNumber = pageNumber;
@@ -2638,6 +2725,22 @@ Use this directive to render a button with a dropdown of alternative actions.
scope.loadingAuditTrail = false;
});
}
function loadRedirectUrls() {
scope.loadingRedirectUrls = true;
//check if Redirect Url Management is enabled
redirectUrlsResource.getEnableState().then(function (response) {
scope.urlTrackerDisabled = response.enabled !== true;
if (scope.urlTrackerDisabled === false) {
redirectUrlsResource.getRedirectsForContentItem(scope.node.udi).then(function (data) {
scope.redirectUrls = data.searchResults;
scope.hasRedirects = typeof data.searchResults !== 'undefined' && data.searchResults.length > 0;
scope.loadingRedirectUrls = false;
});
} else {
scope.loadingRedirectUrls = false;
}
});
}
function setAuditTrailLogTypeColor(auditTrail) {
angular.forEach(auditTrail, function (item) {
switch (item.logType) {
@@ -2750,12 +2853,13 @@ Use this directive to render a button with a dropdown of alternative actions.
scope.node.removeDateTime = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'HH:mm')) : null;
});
}
// load audit trail when on the info tab
// load audit trail and redirects when on the info tab
evts.push(eventsService.on('app.tabChange', function (event, args) {
$timeout(function () {
if (args.id === -1) {
isInfoTab = true;
loadAuditTrail();
loadRedirectUrls();
} else {
isInfoTab = false;
}
@@ -2771,8 +2875,10 @@ Use this directive to render a button with a dropdown of alternative actions.
}
if (isInfoTab) {
loadAuditTrail();
loadRedirectUrls();
formatDatesToLocal();
setNodePublishStatus(scope.node);
ensureUniqueUrls();
}
});
//ensure to unregister from all events!
@@ -3583,7 +3689,7 @@ Use this directive to construct a header inside the main editor window.
icon: '=',
hideIcon: '@',
alias: '=',
hideAlias: '@',
hideAlias: '=',
description: '=',
hideDescription: '@',
descriptionLocked: '@',
@@ -4229,29 +4335,32 @@ Use this directive to construct the main editor window.
return {
restrict: 'A',
link: function (scope, element, attr, formCtrl) {
var origColor = null;
if (attr.hexBgOrig) {
//set the orig based on the attribute if there is one
origColor = attr.hexBgOrig;
}
attr.$observe('hexBgColor', function (newVal) {
if (newVal) {
if (!origColor) {
//get the orig color before changing it
origColor = element.css('border-color');
}
//validate it - test with and without the leading hash.
if (/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(newVal)) {
element.css('background-color', '#' + newVal);
return;
}
if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(newVal)) {
element.css('background-color', newVal);
return;
}
// Only add inline hex background color if defined and not "true".
if (attr.hexBgInline === undefined || attr.hexBgInline !== undefined && attr.hexBgInline === 'true') {
var origColor = null;
if (attr.hexBgOrig) {
// Set the orig based on the attribute if there is one.
origColor = attr.hexBgOrig;
}
element.css('background-color', origColor);
});
attr.$observe('hexBgColor', function (newVal) {
if (newVal) {
if (!origColor) {
// Get the orig color before changing it.
origColor = element.css('border-color');
}
// Validate it - test with and without the leading hash.
if (/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(newVal)) {
element.css('background-color', '#' + newVal);
return;
}
if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(newVal)) {
element.css('background-color', newVal);
return;
}
}
element.css('background-color', origColor);
});
}
}
};
}
@@ -4544,6 +4653,103 @@ Use this directive to prevent default action of an element. Effectively implemen
}
};
});
/**
@ngdoc directive
@name umbraco.directives.directive:umbCheckbox
@restrict E
@scope
@description
<b>Added in Umbraco version 7.14.0</b> Use this directive to render an umbraco checkbox.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-checkbox
name="checkboxlist"
value="{{key}}"
model="true"
text="{{text}}">
</umb-checkbox>
</div>
</pre>
@param {boolean} model Set to <code>true</code> or <code>false</code> to set the checkbox to checked or unchecked.
@param {string} value Set the value of the checkbox.
@param {string} name Set the name of the checkbox.
@param {string} text Set the text for the checkbox label.
**/
(function () {
'use strict';
function CheckboxDirective() {
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/forms/umb-checkbox.html',
scope: {
model: '=',
value: '@',
name: '@',
text: '@',
required: '='
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbCheckbox', CheckboxDirective);
}());
/**
@ngdoc directive
@name umbraco.directives.directive:umbRadiobutton
@restrict E
@scope
@description
<b>Added in Umbraco version 7.14.0</b> Use this directive to render an umbraco radio button.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-radiobutton
name="checkboxlist"
value="{{key}}"
model="true"
text="{{text}}">
</umb-radiobutton>
</div>
</pre>
@param {boolean} model Set to <code>true</code> or <code>false</code> to set the radiobutton to checked or unchecked.
@param {string} value Set the value of the radiobutton.
@param {string} name Set the name of the radiobutton.
@param {string} text Set the text for the radiobutton label.
**/
(function () {
'use strict';
function RadiobuttonDirective() {
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/forms/umb-radiobutton.html',
scope: {
model: '=',
value: '@',
name: '@',
text: '@'
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbRadiobutton', RadiobuttonDirective);
}());
/*
example usage: <textarea json-edit="myObject" rows="8" class="form-control"></textarea>
@@ -4649,7 +4855,7 @@ will override element type to textarea and add own attribute ngModel tied to jso
}
angular.module('umbraco.directives').directive('umbSelectWhen', SelectWhen);
}());
angular.module('umbraco.directives').directive('gridRte', function (tinyMceService, stylesheetResource, angularHelper, assetsService, $q, $timeout) {
angular.module('umbraco.directives').directive('gridRte', function (tinyMceService, stylesheetResource, angularHelper, assetsService, $q, $timeout, eventsService) {
return {
scope: {
uniqueId: '=',
@@ -4968,8 +5174,18 @@ will override element type to textarea and add own attribute ngModel tied to jso
// // is required for our plugins listening to this event to execute
// tinyMceEditor.fire('LoadContent', null);
//};
var tabShownListener = eventsService.on('app.tabChange', function (e, args) {
var tabId = args.id;
var myTabId = element.closest('.umb-tab-pane').attr('rel');
if (String(tabId) === myTabId) {
//the tab has been shown, trigger the mceAutoResize (as it could have timed out before the tab was shown)
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
tinyMceEditor.execCommand('mceAutoResize', false, null, null);
}
}
});
//listen for formSubmitting event (the result is callback used to remove the event subscription)
var unsubscribe = scope.$on('formSubmitting', function () {
var formSubmittingListener = scope.$on('formSubmitting', function () {
//TODO: Here we should parse out the macro rendered content so we can save on a lot of bytes in data xfer
// we do parse it out on the server side but would be nice to do that on the client side before as well.
scope.value = tinyMceEditor ? tinyMceEditor.getContent() : null;
@@ -4978,7 +5194,8 @@ will override element type to textarea and add own attribute ngModel tied to jso
// NOTE: this is very important otherwise if this is part of a modal, the listener still exists because the dom
// element might still be there even after the modal has been hidden.
scope.$on('$destroy', function () {
unsubscribe();
formSubmittingListener();
eventsService.unsubscribe(tabShownListener);
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
tinyMceEditor.destroy();
}
@@ -5284,23 +5501,6 @@ Use this directive to construct a title. Recommended to use it inside an {@link
// scope.dimensions.viewport.width - 2 * scope.dimensions.margin;
scope.dimensions.cropper.height = _viewPortH; // scope.dimensions.viewport.height - 2 * scope.dimensions.margin;
};
//when loading an image without any crop info, we center and fit it
var resizeImageToEditor = function () {
//returns size fitting the cropper
var size = cropperHelper.calculateAspectRatioFit(scope.dimensions.image.width, scope.dimensions.image.height, scope.dimensions.cropper.width, scope.dimensions.cropper.height, true);
//sets the image size and updates the scope
scope.dimensions.image.width = size.width;
scope.dimensions.image.height = size.height;
//calculate the best suited ratios
scope.dimensions.scale.min = size.ratio;
scope.dimensions.scale.max = 2;
scope.dimensions.scale.current = size.ratio;
//center the image
var position = cropperHelper.centerInsideViewPort(scope.dimensions.image, scope.dimensions.cropper);
scope.dimensions.top = position.top;
scope.dimensions.left = position.left;
setConstraints();
};
//resize to a given ratio
var resizeImageToScale = function (ratio) {
//do stuff
@@ -5367,11 +5567,16 @@ Use this directive to construct a title. Recommended to use it inside an {@link
scope.loaded = false;
//set dimensions on image, viewport, cropper etc
setDimensions(image);
//if we have a crop already position the image
if (scope.crop) {
resizeImageToCrop();
} else {
resizeImageToEditor();
//create a default crop if we haven't got one already
var createDefaultCrop = !scope.crop;
if (createDefaultCrop) {
calculateCropBox();
}
resizeImageToCrop();
//if we're creating a new crop, make sure to zoom out fully
if (createDefaultCrop) {
scope.dimensions.scale.current = scope.dimensions.scale.min;
resizeImageToScale(scope.dimensions.scale.min);
}
//sets constaints for the cropper
setConstraints();
@@ -5389,7 +5594,7 @@ Use this directive to construct a title. Recommended to use it inside an {@link
var throttledResizing = _.throttle(function () {
resizeImageToScale(scope.dimensions.scale.current);
calculateCropBox();
}, 100);
}, 16);
//happens when we change the scale
scope.$watch('dimensions.scale.current', function () {
if (scope.loaded) {
@@ -5429,7 +5634,8 @@ Use this directive to construct a title. Recommended to use it inside an {@link
scope: {
src: '=',
center: '=',
onImageLoaded: '='
onImageLoaded: '&',
onGravityChanged: '&'
},
link: function (scope, element, attrs) {
//Internal values for keeping track of the dot and the size of the editor
@@ -5445,7 +5651,7 @@ Use this directive to construct a title. Recommended to use it inside an {@link
var $image = element.find('img');
var $overlay = element.find('.overlay');
scope.style = function () {
if (scope.dimensions.width <= 0) {
if (scope.dimensions.width <= 0 || scope.dimensions.height <= 0) {
setDimensions();
}
return {
@@ -5458,19 +5664,21 @@ Use this directive to construct a title. Recommended to use it inside an {@link
var offsetX = event.offsetX - 10;
var offsetY = event.offsetY - 10;
calculateGravity(offsetX, offsetY);
lazyEndEvent();
gravityChanged();
};
var setDimensions = function () {
scope.dimensions.width = $image.width();
scope.dimensions.height = $image.height();
if (scope.center) {
scope.dimensions.left = scope.center.left * scope.dimensions.width - 10;
scope.dimensions.top = scope.center.top * scope.dimensions.height - 10;
} else {
scope.center = {
left: 0.5,
top: 0.5
};
if (scope.isCroppable) {
scope.dimensions.width = $image.width();
scope.dimensions.height = $image.height();
if (scope.center) {
scope.dimensions.left = scope.center.left * scope.dimensions.width - 10;
scope.dimensions.top = scope.center.top * scope.dimensions.height - 10;
} else {
scope.center = {
left: 0.5,
top: 0.5
};
}
}
};
var calculateGravity = function (offsetX, offsetY) {
@@ -5479,11 +5687,11 @@ Use this directive to construct a title. Recommended to use it inside an {@link
scope.center.left = (scope.dimensions.left + 10) / scope.dimensions.width;
scope.center.top = (scope.dimensions.top + 10) / scope.dimensions.height;
};
var lazyEndEvent = _.debounce(function () {
scope.$apply(function () {
scope.$emit('imageFocalPointStop');
});
}, 2000);
var gravityChanged = function () {
if (angular.isFunction(scope.onGravityChanged)) {
scope.onGravityChanged();
}
};
//Drag and drop positioning, using jquery ui draggable
//TODO ensure that the point doesnt go outside the box
$overlay.draggable({
@@ -5499,16 +5707,34 @@ Use this directive to construct a title. Recommended to use it inside an {@link
var offsetY = $overlay[0].offsetTop;
calculateGravity(offsetX, offsetY);
});
lazyEndEvent();
gravityChanged();
}
});
//// INIT /////
$image.load(function () {
$timeout(function () {
scope.isCroppable = true;
scope.hasDimensions = true;
if (scope.src) {
if (scope.src.endsWith('.svg')) {
scope.isCroppable = false;
scope.hasDimensions = false;
} else {
// From: https://stackoverflow.com/a/51789597/5018
var type = scope.src.substring(scope.src.indexOf('/') + 1, scope.src.indexOf(';base64'));
if (type.startsWith('svg')) {
scope.isCroppable = false;
scope.hasDimensions = false;
}
}
}
setDimensions();
scope.loaded = true;
if (angular.isFunction(scope.onImageLoaded)) {
scope.onImageLoaded();
scope.onImageLoaded({
'isCroppable': scope.isCroppable,
'hasDimensions': scope.hasDimensions
});
}
});
});
@@ -5671,7 +5897,7 @@ Use this directive to construct a title. Recommended to use it inside an {@link
});
(function () {
'use strict';
function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper) {
function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, mediaHelper) {
function link(scope, element, attrs, ctrl) {
var evts = [];
function onInit() {
@@ -5685,6 +5911,8 @@ Use this directive to construct a title. Recommended to use it inside an {@link
setMediaLink();
// make sure dates are formatted to the user's locale
formatDatesToLocal();
// set media file extension initially
setMediaExtension();
}
function formatDatesToLocal() {
// get current backoffice user and format dates
@@ -5696,11 +5924,21 @@ Use this directive to construct a title. Recommended to use it inside an {@link
function setMediaLink() {
scope.nodeUrl = scope.node.mediaLink;
}
function setMediaExtension() {
scope.node.extension = mediaHelper.getFileExtension(scope.nodeUrl);
}
scope.openMediaType = function (mediaType) {
// remove first "#" from url if it is prefixed else the path won't work
var url = '/settings/mediaTypes/edit/' + mediaType.id;
$location.path(url);
};
scope.openSVG = function () {
var popup = window.open('', '_blank');
var html = '<!DOCTYPE html><body><img src="' + scope.nodeUrl + '"/>' + '<script>history.pushState(null, null,"' + $location.$$absUrl + '");</script></body>';
popup.document.open();
popup.document.write(html);
popup.document.close();
};
// watch for content updates - reload content when node is saved, published etc.
scope.$watch('node.updateDate', function (newValue, oldValue) {
if (!newValue) {
@@ -5713,6 +5951,8 @@ Use this directive to construct a title. Recommended to use it inside an {@link
setMediaLink();
// Update the create and update dates
formatDatesToLocal();
//Update the media file format
setMediaExtension();
});
//ensure to unregister from all events!
scope.$on('$destroy', function () {
@@ -6806,7 +7046,15 @@ Opens an overlay to show a custom YSOD. </br>
treeService.syncTree({
node: treeNode,
path: path,
forceReload: forceReload
forceReload: forceReload,
//when the tree node is expanding during sync tree, handle it and raise appropriate events
treeNodeExpanded: function (args) {
emitEvent('treeNodeExpanded', {
tree: scope.tree,
node: args.node,
children: args.children
});
}
}).then(function (data) {
if (activate === undefined || activate === true) {
scope.currentNode = data;
@@ -6970,7 +7218,7 @@ Opens an overlay to show a custom YSOD. </br>
</file>
</example>
*/
angular.module('umbraco.directives').directive('umbTreeItem', function ($compile, $http, $templateCache, $interpolate, $log, $location, $rootScope, $window, treeService, $timeout, localizationService) {
angular.module('umbraco.directives').directive('umbTreeItem', function ($compile, $http, $templateCache, $interpolate, $log, $location, $rootScope, $window, treeService, $timeout, localizationService, appState) {
return {
restrict: 'E',
replace: true,
@@ -7053,6 +7301,18 @@ Opens an overlay to show a custom YSOD. </br>
if (node.selected) {
css.push('umb-tree-node-checked');
}
//is this the current action node (this is not the same as the current selected node!)
var actionNode = appState.getMenuState('currentNode');
if (actionNode) {
if (actionNode.id === node.id && actionNode.id !== '-1') {
css.push('active');
}
// special handling of root nodes with id -1
// as there can be many nodes with id -1 in a tree we need to check the treeAlias instead
if (actionNode.id === '-1' && actionNode.metaData.treeAlias === node.metaData.treeAlias) {
css.push('active');
}
}
return css.join(' ');
};
//add a method to the node which we can use to call to update the node data if we need to ,
@@ -7205,6 +7465,7 @@ Opens an overlay to show a custom YSOD. </br>
searchFromName: '@',
showSearch: '@',
section: '@',
datatypeId: '@',
hideSearchCallback: '=',
searchCallback: '='
},
@@ -7245,6 +7506,10 @@ Opens an overlay to show a custom YSOD. </br>
if (scope.searchFromId) {
searchArgs['searchFrom'] = scope.searchFromId;
}
//append dataTypeId value if there is one
if (scope.datatypeId) {
searchArgs['dataTypeId'] = scope.datatypeId;
}
searcher(searchArgs).then(function (data) {
scope.searchCallback(data);
//set back to null so it can be re-created
@@ -8089,20 +8354,25 @@ Use this directive to generate color swatches to pick from.
</umb-color-swatches>
</pre>
@param {array} colors (<code>attribute</code>): The array of colors.
@param {string} colors (<code>attribute</code>): The array of colors.
@param {string} selectedColor (<code>attribute</code>): The selected color.
@param {string} size (<code>attribute</code>): The size (s, m).
@param {string} useLabel (<code>attribute</code>): Specify if labels should be used.
@param {string} useColorClass (<code>attribute</code>): Specify if color values are css classes.
@param {function} onSelect (<code>expression</code>): Callback function when the item is selected.
**/
(function () {
'use strict';
function ColorSwatchesDirective() {
function link(scope, el, attr, ctrl) {
// Set default to true if not defined
if (angular.isUndefined(scope.useColorClass)) {
scope.useColorClass = false;
}
scope.setColor = function (color) {
//scope.selectedColor({color: color });
scope.selectedColor = color;
if (scope.onSelect) {
scope.onSelect(color);
scope.onSelect({ color: color });
}
};
}
@@ -8115,7 +8385,9 @@ Use this directive to generate color swatches to pick from.
colors: '=?',
size: '@',
selectedColor: '=',
onSelect: '&'
onSelect: '&',
useLabel: '=',
useColorClass: '=?'
},
link: link
};
@@ -8941,7 +9213,7 @@ the directive will use {@link umbraco.directives.directive:umbLockedField umbLoc
@param {string} aliasFrom (<code>binding</code>): The model to generate the alias from.
@param {boolean=} enableLock (<code>binding</code>): Set to <code>true</code> to add a lock next to the alias from where it can be unlocked and changed.
**/
angular.module('umbraco.directives').directive('umbGenerateAlias', function ($timeout, entityResource) {
angular.module('umbraco.directives').directive('umbGenerateAlias', function ($timeout, entityResource, localizationService) {
return {
restrict: 'E',
templateUrl: 'views/components/umb-generate-alias.html',
@@ -8958,26 +9230,37 @@ the directive will use {@link umbraco.directives.directive:umbLockedField umbLoc
var generateAliasTimeout = '';
var updateAlias = false;
scope.locked = true;
scope.placeholderText = 'Enter alias...';
scope.labels = {
idle: 'Enter alias...',
busy: 'Generating alias...'
};
scope.placeholderText = scope.labels.idle;
localizationService.localize('placeholders_enterAlias').then(function (value) {
scope.labels.idle = scope.placeholderText = value;
});
localizationService.localize('placeholders_generatingAlias').then(function (value) {
scope.labels.busy = value;
});
function generateAlias(value) {
if (generateAliasTimeout) {
$timeout.cancel(generateAliasTimeout);
}
if (value !== undefined && value !== '' && value !== null) {
scope.alias = '';
scope.placeholderText = 'Generating Alias...';
scope.placeholderText = scope.labels.busy;
generateAliasTimeout = $timeout(function () {
updateAlias = true;
entityResource.getSafeAlias(encodeURIComponent(value), true).then(function (safeAlias) {
if (updateAlias) {
scope.alias = safeAlias.alias;
}
scope.placeholderText = scope.labels.idle;
});
}, 500);
} else {
updateAlias = true;
scope.alias = '';
scope.placeholderText = 'Enter alias...';
scope.placeholderText = scope.labels.idle;
}
}
// if alias gets unlocked - stop watching alias
@@ -8988,13 +9271,15 @@ the directive will use {@link umbraco.directives.directive:umbLockedField umbLoc
}));
// validate custom entered alias
eventBindings.push(scope.$watch('alias', function (newValue, oldValue) {
if (scope.alias === '' && bindWatcher === true || scope.alias === null && bindWatcher === true) {
// add watcher
eventBindings.push(scope.$watch('aliasFrom', function (newValue, oldValue) {
if (bindWatcher) {
generateAlias(newValue);
}
}));
if (scope.alias === '' || scope.alias === null || scope.alias === undefined) {
if (bindWatcher === true) {
// add watcher
eventBindings.push(scope.$watch('aliasFrom', function (newValue, oldValue) {
if (bindWatcher) {
generateAlias(newValue);
}
}));
}
}
}));
// clean up
@@ -10405,6 +10690,18 @@ Use this directive to generate a thumbnail grid of media items.
scope.items.splice(i, 1);
i--;
}
// If subfolder search is not enabled remove the media items that's not needed
// Make sure that includeSubFolder is not undefined since the directive is used
// in contexts where it should not be used. Currently only used when we trigger
// a media picker
if (scope.includeSubFolders !== undefined) {
if (scope.includeSubFolders !== 'true') {
if (item.parentId !== parseInt(scope.currentFolderId)) {
scope.items.splice(i, 1);
i--;
}
}
}
}
if (scope.items.length > 0) {
setFlexValues(scope.items);
@@ -10545,7 +10842,9 @@ Use this directive to generate a thumbnail grid of media items.
itemMaxHeight: '@',
itemMinWidth: '@',
itemMinHeight: '@',
onlyImages: '@'
onlyImages: '@',
includeSubFolders: '@',
currentFolderId: '@'
},
link: link
};
@@ -10600,6 +10899,8 @@ Use this directive to generate a thumbnail grid of media items.
// update children
miniListView.children = data.items;
_.each(miniListView.children, function (c) {
// child allowed by default
c.allowed = true;
// convert legacy icon for node
if (c.icon) {
c.icon = iconHelper.convertFromLegacyIcon(c.icon);
@@ -10611,6 +10912,15 @@ Use this directive to generate a thumbnail grid of media items.
c.published = c.metaData.IsPublished;
}
}
// filter items if there is a filter and it's not advanced
// ** ignores advanced filter at the moment
if (scope.entityTypeFilter && !scope.entityTypeFilter.filterAdvanced) {
var a = scope.entityTypeFilter.filter.toLowerCase().replace(/\s/g, '').split(',');
var found = a.indexOf(c.metaData.ContentTypeAlias.toLowerCase()) >= 0;
if (!scope.entityTypeFilter.filterExclude && !found || scope.entityTypeFilter.filterExclude && found) {
c.allowed = false;
}
}
});
// update pagination
miniListView.pagination.totalItems = data.totalItems;
@@ -10624,7 +10934,7 @@ Use this directive to generate a thumbnail grid of media items.
event.stopPropagation();
};
scope.selectNode = function (node) {
if (scope.onSelect) {
if (scope.onSelect && node.allowed) {
scope.onSelect({ 'node': node });
}
};
@@ -10719,7 +11029,8 @@ Use this directive to generate a thumbnail grid of media items.
entityType: '@',
startNodeId: '=',
onSelect: '&',
onClose: '&'
onClose: '&',
entityTypeFilter: '='
},
link: link
};
@@ -11315,6 +11626,10 @@ Use this directive make an element sticky and follow the page when scrolling.
var clonedBar = null;
var cloneIsMade = false;
function activate() {
if (bar.parents('.umb-property').length > 1) {
bar.addClass('nested');
return;
}
if (attr.scrollableContainer) {
scrollableContainer = $(attr.scrollableContainer);
} else {