Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 19aae9ffdc | |||
| 218995f9e0 | |||
| 0d167c4f2d | |||
| d44e0d8664 | |||
| f7671ec9a7 | |||
| b9430158ce | |||
| db8954e0a5 | |||
| 05f1a24caf | |||
| b08e922600 | |||
| fbf60fbac4 | |||
| 941baf09ce | |||
| be44741bf9 | |||
| 282ac2b9c5 | |||
| 1224f68297 | |||
| 8d1733fd12 | |||
| 1213551ca9 | |||
| f620d0deca | |||
| d1cfe84723 | |||
| cd6cdcfda4 | |||
| 2ebd7a077c | |||
| 9e33581391 | |||
| 59349dd355 | |||
| 4170faf76e | |||
| cc13b99787 | |||
| d41dbce601 | |||
| 0f61de8bcd | |||
| caf7a6a1ca | |||
| e0a38a4d9b | |||
| 086157cff8 | |||
| 21612454d0 | |||
| d53d0b4271 | |||
| 4564623899 | |||
| cc6c16894c | |||
| 0852b20b31 | |||
| 08e13ac530 | |||
| 71f2b7ee06 | |||
| 7ead62730b | |||
| 0aa1dc1dc7 | |||
| bb60d5e035 | |||
| 247f213d26 | |||
| d7696e8d91 | |||
| 8518aaf4c1 | |||
| 9edafe37e1 | |||
| 914d956ada |
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.13.1")]
|
||||
[assembly: AssemblyInformationalVersion("7.13.1")]
|
||||
[assembly: AssemblyFileVersion("7.13.2")]
|
||||
[assembly: AssemblyInformationalVersion("7.13.2")]
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.13.1");
|
||||
private static readonly Version Version = new Version("7.13.2");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourteenZero
|
||||
{
|
||||
/// <summary>
|
||||
/// Migrates member group picker properties from NVarchar to NText. See https://github.com/umbraco/Umbraco-CMS/issues/3268.
|
||||
/// </summary>
|
||||
[Migration("7.14.0", 1, Constants.System.UmbracoMigrationName)]
|
||||
public class UpdateMemberGroupPickerData : MigrationBase
|
||||
{
|
||||
public UpdateMemberGroupPickerData(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
// move the data for all member group properties from the NVarchar to the NText column and clear the NVarchar column
|
||||
Execute.Sql(@"UPDATE cmsPropertyData SET dataNtext = dataNvarchar, dataNvarchar = NULL
|
||||
WHERE dataNtext IS NULL AND id IN (
|
||||
SELECT id FROM cmsPropertyData WHERE propertyTypeId in (
|
||||
SELECT id from cmsPropertyType where dataTypeID IN (
|
||||
SELECT nodeId FROM cmsDataType WHERE propertyEditorAlias = 'Umbraco.MemberGroupPicker'
|
||||
)
|
||||
)
|
||||
)");
|
||||
|
||||
// ensure that all exising member group properties are defined as NText
|
||||
Execute.Sql("UPDATE cmsDataType SET dbType = 'Ntext' WHERE propertyEditorAlias = 'Umbraco.MemberGroupPicker'");
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,7 +189,6 @@ namespace Umbraco.Core
|
||||
outputArray[i] = char.IsLetterOrDigit(inputArray[i]) ? inputArray[i] : replacement;
|
||||
return new string(outputArray);
|
||||
}
|
||||
|
||||
private static readonly char[] CleanForXssChars = "*?(){}[];:%<>/\\|&'\"".ToCharArray();
|
||||
|
||||
/// <summary>
|
||||
@@ -542,7 +541,7 @@ namespace Umbraco.Core
|
||||
public static string StripHtml(this string text)
|
||||
{
|
||||
const string pattern = @"<(.|\n)*?>";
|
||||
return Regex.Replace(text, pattern, String.Empty);
|
||||
return Regex.Replace(text, pattern, string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -572,6 +572,7 @@
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenEightZero\AddInstructionCountColumn.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenEightZero\AddCmsMediaTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenEightZero\AddUserLoginTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFourteenZero\UpdateMemberGroupPickerData.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\RenameTrueFalseField.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\SetDefaultTagsStorageType.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenNineZero\AddUmbracoAuditTable.cs" />
|
||||
|
||||
@@ -61,6 +61,17 @@ namespace Umbraco.Tests.Strings
|
||||
Assert.AreEqual(stripped, result);
|
||||
}
|
||||
|
||||
[TestCase("'+alert(1234)+'", "+alert1234+")]
|
||||
[TestCase("'+alert(56+78)+'", "+alert56+78+")]
|
||||
[TestCase("{{file}}", "file")]
|
||||
[TestCase("'+alert('hello')+'", "+alerthello+")]
|
||||
[TestCase("Test", "Test")]
|
||||
public void Clean_From_XSS(string input, string result)
|
||||
{
|
||||
var cleaned = input.CleanForXss();
|
||||
Assert.AreEqual(cleaned, result);
|
||||
}
|
||||
|
||||
[TestCase("This is a string to encrypt")]
|
||||
[TestCase("This is a string to encrypt\nThis is a second line")]
|
||||
[TestCase(" White space is preserved ")]
|
||||
|
||||
@@ -29,5 +29,30 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"});
|
||||
Assert.AreEqual("<div style=\"color:red;\" onclick=\"void();\">hello world</div>", output.ToHtmlString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetRelatedLinkHtml_Simple()
|
||||
{
|
||||
var relatedLink = new Umbraco.Web.Models.RelatedLink {
|
||||
Caption = "Link Caption",
|
||||
NewWindow = true,
|
||||
Link = "https://www.google.com/"
|
||||
};
|
||||
var output = _htmlHelper.GetRelatedLinkHtml(relatedLink);
|
||||
Assert.AreEqual("<a href=\"https://www.google.com/\" target=\"_blank\">Link Caption</a>", output.ToHtmlString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetRelatedLinkHtml_HtmlAttributes()
|
||||
{
|
||||
var relatedLink = new Umbraco.Web.Models.RelatedLink
|
||||
{
|
||||
Caption = "Link Caption",
|
||||
NewWindow = true,
|
||||
Link = "https://www.google.com/"
|
||||
};
|
||||
var output = _htmlHelper.GetRelatedLinkHtml(relatedLink, new { @class = "test-class"});
|
||||
Assert.AreEqual("<a class=\"test-class\" href=\"https://www.google.com/\" target=\"_blank\">Link Caption</a>", output.ToHtmlString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ LazyLoad.js([
|
||||
'../js/umbraco.security.js',
|
||||
'../ServerVariables',
|
||||
'../lib/spectrum/spectrum.js',
|
||||
'../js/umbraco.canvasdesigner.js',
|
||||
'../js/canvasdesigner.panel.js'
|
||||
'../js/umbraco.canvasdesigner.js'
|
||||
], function () {
|
||||
jQuery(document).ready(function () {
|
||||
angular.bootstrap(document, ['Umbraco.canvasdesigner']);
|
||||
|
||||
+4
@@ -18,6 +18,7 @@
|
||||
|
||||
<umb-toggle
|
||||
checked="vm.checked"
|
||||
disabled="vm.disabled"
|
||||
on-click="vm.toggle()"
|
||||
show-labels="true"
|
||||
label-on="Start"
|
||||
@@ -38,6 +39,7 @@
|
||||
|
||||
var vm = this;
|
||||
vm.checked = false;
|
||||
vm.disabled = false;
|
||||
|
||||
vm.toggle = toggle;
|
||||
|
||||
@@ -52,6 +54,7 @@
|
||||
</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".
|
||||
@@ -115,6 +118,7 @@
|
||||
templateUrl: 'views/components/buttons/umb-toggle.html',
|
||||
scope: {
|
||||
checked: "=",
|
||||
disabled: "=",
|
||||
onClick: "&",
|
||||
labelOn: "@?",
|
||||
labelOff: "@?",
|
||||
|
||||
+3
@@ -53,6 +53,9 @@
|
||||
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");
|
||||
}
|
||||
|
||||
scope.auditTrailPageChange = function (pageNumber) {
|
||||
|
||||
+9
-9
@@ -14,7 +14,8 @@ angular.module("umbraco.directives")
|
||||
scope: {
|
||||
src: '=',
|
||||
center: "=",
|
||||
onImageLoaded: "&"
|
||||
onImageLoaded: "&",
|
||||
onGravityChanged: "&"
|
||||
},
|
||||
link: function(scope, element, attrs) {
|
||||
|
||||
@@ -52,7 +53,7 @@ angular.module("umbraco.directives")
|
||||
|
||||
calculateGravity(offsetX, offsetY);
|
||||
|
||||
lazyEndEvent();
|
||||
gravityChanged();
|
||||
};
|
||||
|
||||
var setDimensions = function () {
|
||||
@@ -77,12 +78,11 @@ angular.module("umbraco.directives")
|
||||
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
|
||||
@@ -100,7 +100,7 @@ angular.module("umbraco.directives")
|
||||
calculateGravity(offsetX, offsetY);
|
||||
});
|
||||
|
||||
lazyEndEvent();
|
||||
gravityChanged();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+17
-17
@@ -86,20 +86,21 @@ angular.module("umbraco.directives")
|
||||
function generateAlias(value) {
|
||||
|
||||
if (generateAliasTimeout) {
|
||||
$timeout.cancel(generateAliasTimeout);
|
||||
$timeout.cancel(generateAliasTimeout);
|
||||
}
|
||||
|
||||
if( value !== undefined && value !== "" && value !== null) {
|
||||
if (value !== undefined && value !== "" && value !== null) {
|
||||
|
||||
scope.alias = "";
|
||||
scope.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.alias = safeAlias.alias;
|
||||
}
|
||||
scope.placeholderText = scope.labels.idle;
|
||||
});
|
||||
}, 500);
|
||||
|
||||
@@ -108,7 +109,6 @@ angular.module("umbraco.directives")
|
||||
scope.alias = "";
|
||||
scope.placeholderText = scope.labels.idle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if alias gets unlocked - stop watching alias
|
||||
@@ -119,17 +119,17 @@ angular.module("umbraco.directives")
|
||||
}));
|
||||
|
||||
// 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);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
eventBindings.push(scope.$watch('alias', function (newValue, oldValue) {
|
||||
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
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ Use this directive to generate color swatches to pick from.
|
||||
scope.selectedColor = color;
|
||||
|
||||
if (scope.onSelect) {
|
||||
scope.onSelect(color);
|
||||
scope.onSelect({color: color });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @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) {
|
||||
function codefileResource($q, $http, umbDataFormatter, umbRequestHelper, localizationService) {
|
||||
|
||||
return {
|
||||
|
||||
@@ -106,13 +106,16 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*
|
||||
*/
|
||||
deleteByPath: function (type, virtualpath) {
|
||||
|
||||
var promise = localizationService.localize("codefile_deleteItemFailed", [virtualpath]);
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"Delete",
|
||||
[{ type: type }, { virtualPath: virtualpath}])),
|
||||
"Failed to delete item: " + virtualpath);
|
||||
promise);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -236,13 +239,19 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*
|
||||
*/
|
||||
|
||||
createContainer: function(type, parentId, name) {
|
||||
createContainer: function (type, parentId, name) {
|
||||
|
||||
// Is the parent ID numeric?
|
||||
var key = "codefile_createFolderFailedBy" + (isNaN(parseInt(parentId)) ? "Name" : "Id");
|
||||
|
||||
var promise = localizationService.localize(key, [parentId]);
|
||||
|
||||
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);
|
||||
promise);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @name umbraco.resources.templateResource
|
||||
* @description Loads in data for templates
|
||||
**/
|
||||
function templateResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
function templateResource($q, $http, umbDataFormatter, umbRequestHelper, localizationService) {
|
||||
|
||||
return {
|
||||
|
||||
@@ -152,13 +152,16 @@ function templateResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*
|
||||
*/
|
||||
deleteById: function(id) {
|
||||
|
||||
var promise = localizationService.localize("template_deleteByIdFailed", [id]);
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"templateApiBaseUrl",
|
||||
"DeleteById",
|
||||
[{ id: id }])),
|
||||
"Failed to delete item " + id);
|
||||
promise);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
|
||||
.umb-toggle__toggle {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
width: 48px;
|
||||
height: 24px;
|
||||
background: @gray-8;
|
||||
@@ -41,6 +42,11 @@
|
||||
background-color: @green;
|
||||
}
|
||||
|
||||
.umb-toggle--disabled .umb-toggle__toggle {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.umb-toggle--checked .umb-toggle__handler {
|
||||
transform: translate3d(24px, 0, 0) rotate(0);
|
||||
}
|
||||
@@ -63,7 +69,7 @@
|
||||
|
||||
.umb-toggle__icon {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
line-height: 1em;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ input.umb-table__input {
|
||||
|
||||
}
|
||||
|
||||
.-content :not(.with-unpublished-version).-unpublished {
|
||||
.-content .-unpublished:not(.with-unpublished-version) {
|
||||
.umb-table__name > * {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.umb-permission--disabled .umb-permission__toggle,
|
||||
.umb-permission--disabled .umb-permission__content {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.umb-permission__description {
|
||||
font-size: 13px;
|
||||
color: @gray-5;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@checkered-background: url(../img/checkered-background.png);
|
||||
|
||||
//
|
||||
// Container styles
|
||||
// --------------------------------------------------
|
||||
@@ -386,7 +388,7 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
max-height:100%;
|
||||
margin:auto;
|
||||
display:block;
|
||||
background-image: url(../img/checkered-background.png);
|
||||
background-image: @checkered-background;
|
||||
}
|
||||
|
||||
.umb-sortable-thumbnails li .trashed {
|
||||
@@ -599,12 +601,18 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.gravity-container .viewport {
|
||||
max-width: 600px;
|
||||
}
|
||||
.gravity-container {
|
||||
border: 1px solid @gray-8;
|
||||
line-height: 0;
|
||||
|
||||
.gravity-container .viewport:hover {
|
||||
cursor: pointer;
|
||||
.viewport {
|
||||
max-width: 600px;
|
||||
background: @checkered-background;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.imagecropper {
|
||||
@@ -617,6 +625,10 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
float: left;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.viewport img {
|
||||
background: @checkered-background;
|
||||
}
|
||||
}
|
||||
|
||||
.imagecropper .umb-cropper__container {
|
||||
@@ -884,6 +896,10 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
list-style: none;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 0;
|
||||
|
||||
img {
|
||||
background: @checkered-background;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-fileupload label {
|
||||
|
||||
+24
-17
@@ -25,30 +25,31 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
||||
$scope.showTarget = $scope.model.hideTarget !== true;
|
||||
|
||||
if (dialogOptions.currentTarget) {
|
||||
$scope.model.target = dialogOptions.currentTarget;
|
||||
// clone the current target so we don't accidentally update the caller's model while manipulating $scope.model.target
|
||||
$scope.model.target = angular.copy(dialogOptions.currentTarget);
|
||||
//if we have a node ID, we fetch the current node to build the form data
|
||||
if ($scope.model.target.id || $scope.model.target.udi) {
|
||||
|
||||
//will be either a udi or an int
|
||||
var id = $scope.model.target.udi ? $scope.model.target.udi : $scope.model.target.id;
|
||||
|
||||
if (!$scope.model.target.path) {
|
||||
// is it a content link?
|
||||
if (!$scope.model.target.isMedia) {
|
||||
// get the content path
|
||||
entityResource.getPath(id, "Document").then(function(path) {
|
||||
//now sync the tree to this path
|
||||
$scope.dialogTreeEventHandler.syncTree({
|
||||
path: path,
|
||||
tree: "content"
|
||||
});
|
||||
});
|
||||
|
||||
entityResource.getPath(id, "Document").then(function (path) {
|
||||
$scope.model.target.path = path;
|
||||
//now sync the tree to this path
|
||||
$scope.dialogTreeEventHandler.syncTree({
|
||||
path: $scope.model.target.path,
|
||||
tree: "content"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// if a link exists, get the properties to build the anchor name list
|
||||
contentResource.getById(id).then(function (resp) {
|
||||
$scope.model.target.url = resp.urls[0];
|
||||
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
|
||||
});
|
||||
// get the content properties to build the anchor name list
|
||||
contentResource.getById(id).then(function (resp) {
|
||||
$scope.model.target.url = resp.urls[0];
|
||||
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
|
||||
});
|
||||
}
|
||||
} else if ($scope.model.target.url.length) {
|
||||
// a url but no id/udi indicates an external link - trim the url to remove the anchor/qs
|
||||
// only do the substring if there's a # or a ?
|
||||
@@ -122,6 +123,12 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
||||
|
||||
$scope.mediaPickerOverlay.show = false;
|
||||
$scope.mediaPickerOverlay = null;
|
||||
|
||||
// make sure the content tree has nothing highlighted
|
||||
$scope.dialogTreeEventHandler.syncTree({
|
||||
path: "-1",
|
||||
tree: "content"
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<button ng-click="click()" type="button" class="umb-toggle" ng-class="{'umb-toggle--checked': checked}">
|
||||
<button ng-click="click()" type="button" class="umb-toggle" ng-disabled="disabled" ng-class="{'umb-toggle--checked': checked, 'umb-toggle--disabled': disabled}">
|
||||
|
||||
<span ng-if="!labelPosition && showLabels === 'true' || labelPosition === 'left' && showLabels === 'true'">
|
||||
<span ng-if="!checked" class="umb-toggle__label umb-toggle__label--left">{{ displayLabelOff }}</span>
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__sidebar">
|
||||
<umb-box data-element="node-info-scheduled-publishing">
|
||||
<umb-box data-element="node-info-scheduled-publishing" ng-if="allowScheduledPublishing">
|
||||
<umb-box-header title-key="general_scheduledPublishing"></umb-box-header>
|
||||
<umb-box-content class="block-form">
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<!-- Icon for files -->
|
||||
<span class="umb-media-grid__item-file-icon" ng-if="!item.thumbnail && item.extension != 'svg'">
|
||||
<i class="umb-media-grid__item-icon {{item.icon}}"></i>
|
||||
<span>.{{item.extension}}</span>
|
||||
<span ng-if="item.extension">.{{item.extension}}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<umb-control-group label="Enter a folder name" hide-label="false">
|
||||
<umb-control-group label="@create_enterFolderName" localize="label" hide-label="false">
|
||||
<input type="text" name="folderName" ng-model="vm.folderName" class="umb-textstring textstring input-block-level" umb-auto-focus required />
|
||||
</umb-control-group>
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ function PartialViewsDeleteController($scope, codefileResource, treeService, nav
|
||||
|
||||
//mark it for deletion (used in the UI)
|
||||
$scope.currentNode.loading = true;
|
||||
|
||||
// Reset the error message
|
||||
$scope.error = null;
|
||||
|
||||
codefileResource.deleteByPath('partialViews', $scope.currentNode.id)
|
||||
.then(function() {
|
||||
@@ -21,6 +24,9 @@ function PartialViewsDeleteController($scope, codefileResource, treeService, nav
|
||||
//TODO: Need to sync tree, etc...
|
||||
treeService.removeNode($scope.currentNode);
|
||||
navigationService.hideMenu();
|
||||
}, function (err) {
|
||||
$scope.currentNode.loading = false;
|
||||
$scope.error = err;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
<div class="umb-dialog umb-pane" ng-controller="Umbraco.Editors.PartialViews.DeleteController">
|
||||
<div class="umb-dialog-body">
|
||||
|
||||
<div ng-show="error">
|
||||
<div class="alert alert-error">
|
||||
<div><strong>{{error.errorMsg}}</strong></div>
|
||||
<div>{{error.data.message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="umb-abstract">
|
||||
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize> <strong>{{currentNode.name}}</strong> ?
|
||||
</p>
|
||||
|
||||
+36
-67
@@ -1,4 +1,4 @@
|
||||
function ColorPickerController($scope) {
|
||||
function ColorPickerController($scope, angularHelper) {
|
||||
|
||||
//setup the default config
|
||||
var config = {
|
||||
@@ -12,32 +12,13 @@ function ColorPickerController($scope) {
|
||||
//map back to the model
|
||||
$scope.model.config = config;
|
||||
|
||||
function convertArrayToDictionaryArray(model) {
|
||||
//now we need to format the items in the dictionary because we always want to have an array
|
||||
var newItems = [];
|
||||
for (var i = 0; i < model.length; i++) {
|
||||
newItems.push({ id: model[i], sortOrder: 0, value: model[i] });
|
||||
}
|
||||
|
||||
return newItems;
|
||||
}
|
||||
|
||||
|
||||
function convertObjectToDictionaryArray(model) {
|
||||
//now we need to format the items in the dictionary because we always want to have an array
|
||||
var newItems = [];
|
||||
var vals = _.values($scope.model.config.items);
|
||||
var keys = _.keys($scope.model.config.items);
|
||||
|
||||
for (var i = 0; i < vals.length; i++) {
|
||||
var label = vals[i].value ? vals[i].value : vals[i];
|
||||
newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label });
|
||||
}
|
||||
|
||||
return newItems;
|
||||
}
|
||||
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
|
||||
|
||||
$scope.model.activeColor = {
|
||||
value: "",
|
||||
label: ""
|
||||
};
|
||||
|
||||
if ($scope.isConfigured) {
|
||||
|
||||
for (var key in $scope.model.config.items) {
|
||||
@@ -77,29 +58,7 @@ function ColorPickerController($scope) {
|
||||
//now make the editor model the array
|
||||
$scope.model.config.items = items;
|
||||
}
|
||||
|
||||
$scope.toggleItem = function (color) {
|
||||
|
||||
var currentColor = ($scope.model.value && $scope.model.value.hasOwnProperty("value"))
|
||||
? $scope.model.value.value
|
||||
: $scope.model.value;
|
||||
|
||||
var newColor;
|
||||
if (currentColor === color.value) {
|
||||
// deselect
|
||||
$scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
|
||||
newColor = "";
|
||||
}
|
||||
else {
|
||||
// select
|
||||
$scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
|
||||
newColor = color.value;
|
||||
}
|
||||
|
||||
// this is required to re-validate
|
||||
$scope.propertyForm.modelValue.$setViewValue(newColor);
|
||||
};
|
||||
|
||||
|
||||
// Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected)
|
||||
$scope.validateMandatory = function () {
|
||||
var isValid = !$scope.model.validation.mandatory || (
|
||||
@@ -115,27 +74,41 @@ function ColorPickerController($scope) {
|
||||
}
|
||||
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
|
||||
|
||||
// A color is active if it matches the value and label of the model.
|
||||
// If the model doesn't store the label, ignore the label during the comparison.
|
||||
$scope.isActiveColor = function (color) {
|
||||
$scope.onSelect = function (color) {
|
||||
// did the value change?
|
||||
if ($scope.model.value.value === color) {
|
||||
// User clicked the currently selected color
|
||||
// to remove the selection, they don't want
|
||||
// to select any color after all.
|
||||
// Unselect the color and mark as dirty
|
||||
$scope.model.activeColor = null;
|
||||
$scope.model.value = null;
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
|
||||
// no value
|
||||
if (!$scope.model.value)
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Complex color (value and label)?
|
||||
if (!$scope.model.value.hasOwnProperty("value"))
|
||||
return $scope.model.value === color.value;
|
||||
|
||||
return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
|
||||
};
|
||||
// yes, update the model (label + value) according to the new color
|
||||
var selectedItem = _.find($scope.model.config.items, function (item) {
|
||||
return item.value === color;
|
||||
});
|
||||
if (!selectedItem) {
|
||||
return;
|
||||
}
|
||||
$scope.model.value = {
|
||||
label: selectedItem.label,
|
||||
value: selectedItem.value
|
||||
};
|
||||
// make sure to set dirty
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
}
|
||||
|
||||
// Finds the color best matching the model's color,
|
||||
// and sets the model color to that one. This is useful when
|
||||
// either the value or label was changed on the data type.
|
||||
function initActiveColor() {
|
||||
|
||||
// no value
|
||||
// no value - initialize default value
|
||||
if (!$scope.model.value)
|
||||
return;
|
||||
|
||||
@@ -144,10 +117,6 @@ function ColorPickerController($scope) {
|
||||
$scope.model.value = { value: $scope.model.value, label: $scope.model.value };
|
||||
}
|
||||
|
||||
// Complex color (value and label)?
|
||||
if (!$scope.model.value.hasOwnProperty("value"))
|
||||
return;
|
||||
|
||||
var modelColor = $scope.model.value.value;
|
||||
var modelLabel = $scope.model.value.label;
|
||||
|
||||
@@ -187,8 +156,8 @@ function ColorPickerController($scope) {
|
||||
|
||||
// If a match was found, set it as the active color.
|
||||
if (foundItem) {
|
||||
$scope.model.value.value = foundItem.value;
|
||||
$scope.model.value.label = foundItem.label;
|
||||
$scope.model.activeColor.value = foundItem.value;
|
||||
$scope.model.activeColor.label = foundItem.label;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
</div>
|
||||
|
||||
<umb-color-swatches colors="model.config.items"
|
||||
selected-color="model.value.value"
|
||||
selected-color="model.activeColor.value"
|
||||
size="m"
|
||||
use-label="model.useLabel">
|
||||
use-label="model.useLabel"
|
||||
on-select="onSelect(color)">
|
||||
</umb-color-swatches>
|
||||
|
||||
<input type="hidden" name="modelValue" ng-model="model.value" val-property-validator="validateMandatory" />
|
||||
|
||||
+5
@@ -52,6 +52,7 @@ angular.module('umbraco')
|
||||
});
|
||||
editedCrop.coordinates = $scope.currentCrop.coordinates;
|
||||
$scope.close();
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
};
|
||||
|
||||
//reset the current crop
|
||||
@@ -98,6 +99,10 @@ angular.module('umbraco')
|
||||
$scope.hasDimensions = hasDimensions;
|
||||
};
|
||||
|
||||
$scope.focalPointChanged = function () {
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
}
|
||||
|
||||
//on image selected, update the cropper
|
||||
$scope.$on("filesSelected", function (ev, args) {
|
||||
$scope.model.value = config;
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
<umb-image-gravity
|
||||
src="imageSrc"
|
||||
center="model.value.focalPoint"
|
||||
on-image-loaded="imageLoaded(isCroppable, hasDimensions)">
|
||||
on-image-loaded="imageLoaded(isCroppable, hasDimensions)"
|
||||
on-gravity-changed="focalPointChanged()">
|
||||
</umb-image-gravity>
|
||||
<a href class="btn btn-link btn-crop-delete" ng-click="clear()"><i class="icon-delete red"></i> <localize key="content_uploadClear">Remove file</localize></a>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService, navigationService, treeService) {
|
||||
function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService, navigationService, treeService, mediaHelper) {
|
||||
|
||||
//this is a quick check to see if we're in create mode, if so just exit - we cannot show children for content
|
||||
// that isn't created yet, if we continue this will use the parent id in the route params which isn't what
|
||||
@@ -269,10 +269,12 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie
|
||||
$scope.listViewResultSet = data;
|
||||
|
||||
//update all values for display
|
||||
var section = appState.getSectionState("currentSection");
|
||||
if ($scope.listViewResultSet.items) {
|
||||
_.each($scope.listViewResultSet.items, function (e, index) {
|
||||
setPropertyValues(e);
|
||||
if (e.contentTypeAlias === 'Folder') {
|
||||
// create the folders collection (only for media list views)
|
||||
if (section === "media" && !mediaHelper.hasFilePropertyType(e)) {
|
||||
$scope.folders.push(e);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -12,6 +12,10 @@ function TemplatesDeleteController($scope, templateResource , treeService, navig
|
||||
|
||||
//mark it for deletion (used in the UI)
|
||||
$scope.currentNode.loading = true;
|
||||
|
||||
// Reset the error message
|
||||
$scope.error = null;
|
||||
|
||||
templateResource.deleteById($scope.currentNode.id).then(function () {
|
||||
$scope.currentNode.loading = false;
|
||||
|
||||
@@ -21,6 +25,9 @@ function TemplatesDeleteController($scope, templateResource , treeService, navig
|
||||
//TODO: Need to sync tree, etc...
|
||||
treeService.removeNode($scope.currentNode);
|
||||
navigationService.hideMenu();
|
||||
}, function (err) {
|
||||
$scope.currentNode.loading = false;
|
||||
$scope.error = err;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
<div class="umb-dialog umb-pane" ng-controller="Umbraco.Editors.Templates.DeleteController">
|
||||
<div class="umb-dialog-body">
|
||||
|
||||
<div ng-show="error">
|
||||
<div class="alert alert-error">
|
||||
<div><strong>{{error.errorMsg}}</strong></div>
|
||||
<div>{{error.data.message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="umb-abstract">
|
||||
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize> <strong>{{currentNode.name}}</strong> ?
|
||||
</p>
|
||||
|
||||
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
|
||||
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
|
||||
</umb-confirm>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1038,9 +1038,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7131</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7132</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7131</IISUrl>
|
||||
<IISUrl>http://localhost:7132</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -182,6 +182,11 @@
|
||||
<key alias="validationErrorPropertyWithMoreThanOneMapping">Overførsel af egenskaber kunne ikke fuldføres, da en eller flere egenskaber er indstillet til at blive overført mere end én gang.</key>
|
||||
<key alias="validDocTypesNote">Kun andre dokumenttyper, der er gyldige på denne placering, vises.</key>
|
||||
</area>
|
||||
<area alias="codefile">
|
||||
<key alias="createFolderFailedById">Oprettelse af mappen under parent med ID %0% fejlede</key>
|
||||
<key alias="createFolderFailedByName">Oprettelse af mappen under parent med navnet %0% fejlede</key>
|
||||
<key alias="deleteItemFailed">Sletning af filen/mappen fejlede: %0%</key>
|
||||
</area>
|
||||
<area alias="content">
|
||||
<key alias="isPublished" version="7.2">Udgivet</key>
|
||||
<key alias="about">Om siden</key>
|
||||
@@ -282,6 +287,7 @@
|
||||
<key alias="chooseNode">Hvor ønsker du at oprette den nye %0%</key>
|
||||
<key alias="createUnder">Opret under</key>
|
||||
<key alias="createContentBlueprint">Vælg den dokumenttype, du vil oprette en indholdsskabelon til</key>
|
||||
<key alias="enterFolderName">Angiv et navn for mappen</key>
|
||||
<key alias="updateData">Vælg en type og skriv en titel</key>
|
||||
<key alias="noDocumentTypes" version="7.0"><![CDATA[Der kunne ikke findes nogen tilladte dokument typer. Du skal tillade disse i indstillinger under <strong>"dokument typer"</strong>.]]></key>
|
||||
<key alias="noMediaTypes" version="7.0"><![CDATA[Der kunne ikke findes nogen tilladte media typer. Du skal tillade disse i indstillinger under <strong>"media typer"</strong>.]]></key>
|
||||
@@ -1158,6 +1164,7 @@ Mange hilsner fra Umbraco robotten
|
||||
</area>
|
||||
|
||||
<area alias="template">
|
||||
<key alias="deleteByIdFailed">Sletning af skabelonen med ID %0% fejlede</key>
|
||||
<key alias="edittemplate">Rediger skabelon</key>
|
||||
|
||||
<key alias="insertSections">Sektioner</key>
|
||||
|
||||
@@ -188,6 +188,11 @@
|
||||
<key alias="validationErrorPropertyWithMoreThanOneMapping">Could not complete property mapping as one or more properties have more than one mapping defined.</key>
|
||||
<key alias="validDocTypesNote">Only alternate types valid for the current location are displayed.</key>
|
||||
</area>
|
||||
<area alias="codefile">
|
||||
<key alias="createFolderFailedById">Failed to create a folder under parent with ID %0%</key>
|
||||
<key alias="createFolderFailedByName">Failed to create a folder under parent with name %0%</key>
|
||||
<key alias="deleteItemFailed">Failed to delete item: %0%</key>
|
||||
</area>
|
||||
<area alias="content">
|
||||
<key alias="isPublished" version="7.2">Is Published</key>
|
||||
<key alias="about">About this page</key>
|
||||
@@ -290,6 +295,7 @@
|
||||
<key alias="chooseNode">Where do you want to create the new %0%</key>
|
||||
<key alias="createUnder">Create an item under</key>
|
||||
<key alias="createContentBlueprint">Select the document type you want to make a content template for</key>
|
||||
<key alias="enterFolderName">Enter a folder name</key>
|
||||
<key alias="updateData">Choose a type and a title</key>
|
||||
<key alias="noDocumentTypes" version="7.0"><![CDATA[There are no allowed document types available. You must enable these in the settings section under <strong>"document types"</strong>.]]></key>
|
||||
<key alias="noMediaTypes" version="7.0"><![CDATA[There are no allowed media types available. You must enable these in the settings section under <strong>"media types"</strong>.]]></key>
|
||||
@@ -1483,6 +1489,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
</area>
|
||||
|
||||
<area alias="template">
|
||||
<key alias="deleteByIdFailed">Failed to delete template with ID %0%</key>
|
||||
<key alias="edittemplate">Edit template</key>
|
||||
|
||||
<key alias="insertSections">Sections</key>
|
||||
|
||||
@@ -189,6 +189,11 @@
|
||||
<key alias="validationErrorPropertyWithMoreThanOneMapping">Could not complete property mapping as one or more properties have more than one mapping defined.</key>
|
||||
<key alias="validDocTypesNote">Only alternate types valid for the current location are displayed.</key>
|
||||
</area>
|
||||
<area alias="codefile">
|
||||
<key alias="createFolderFailedById">Failed to create a folder under parent with ID %0%</key>
|
||||
<key alias="createFolderFailedByName">Failed to create a folder under parent with name %0%</key>
|
||||
<key alias="deleteItemFailed">Failed to delete item: %0%</key>
|
||||
</area>
|
||||
<area alias="content">
|
||||
<key alias="isPublished" version="7.2">Is Published</key>
|
||||
<key alias="about">About this page</key>
|
||||
@@ -292,6 +297,7 @@
|
||||
<key alias="chooseNode">Where do you want to create the new %0%</key>
|
||||
<key alias="createUnder">Create an item under</key>
|
||||
<key alias="createContentBlueprint">Select the document type you want to make a content template for</key>
|
||||
<key alias="enterFolderName">Enter a folder name</key>
|
||||
<key alias="updateData">Choose a type and a title</key>
|
||||
<key alias="noDocumentTypes" version="7.0"><![CDATA[There are no allowed document types available. You must enable these in the settings section under <strong>"document types"</strong>.]]></key>
|
||||
<key alias="noMediaTypes" version="7.0"><![CDATA[There are no allowed media types available. You must enable these in the settings section under <strong>"media types"</strong>.]]></key>
|
||||
@@ -1481,6 +1487,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="styles">Styles</key>
|
||||
</area>
|
||||
<area alias="template">
|
||||
<key alias="deleteByIdFailed">Failed to delete template with ID %0%</key>
|
||||
<key alias="edittemplate">Edit template</key>
|
||||
|
||||
<key alias="insertSections">Sections</key>
|
||||
|
||||
@@ -53,6 +53,16 @@ namespace Umbraco.Web.Editors
|
||||
if (currentUser.IsAdmin())
|
||||
return Attempt<string>.Succeed();
|
||||
|
||||
var existingGroups = _userService.GetUserGroupsByAlias(groupAliases);
|
||||
|
||||
if(!existingGroups.Any())
|
||||
{
|
||||
// We're dealing with new groups,
|
||||
// so authorization should be given to any user with access to Users section
|
||||
if (currentUser.AllowedSections.Contains(Constants.Applications.Users))
|
||||
return Attempt<string>.Succeed();
|
||||
}
|
||||
|
||||
var userGroups = currentUser.Groups.Select(x => x.Alias).ToArray();
|
||||
var missingAccess = groupAliases.Except(userGroups).ToArray();
|
||||
return missingAccess.Length == 0
|
||||
@@ -119,4 +129,4 @@ namespace Umbraco.Web.Editors
|
||||
return Attempt<string>.Succeed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Umbraco.Web.Editors
|
||||
//authorize that the user has access to save this user group
|
||||
var authHelper = new UserGroupEditorAuthorizationHelper(
|
||||
Services.UserService, Services.ContentService, Services.MediaService, Services.EntityService);
|
||||
|
||||
var isAuthorized = authHelper.AuthorizeGroupAccess(Security.CurrentUser, userGroupSave.Alias);
|
||||
if (isAuthorized == false)
|
||||
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Unauthorized, isAuthorized.Result));
|
||||
@@ -50,6 +51,14 @@ namespace Umbraco.Web.Editors
|
||||
if (isAuthorized == false)
|
||||
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Unauthorized, isAuthorized.Result));
|
||||
|
||||
//current user needs to be added to a new group if not an admin (possibly only if no other users are added?) to avoid a 401
|
||||
if(!Security.CurrentUser.IsAdmin() && (userGroupSave.Id == null || Convert.ToInt32(userGroupSave.Id) >= 0)/* && !userGroupSave.Users.Any() */)
|
||||
{
|
||||
var userIds = userGroupSave.Users.ToList();
|
||||
userIds.Add(Security.CurrentUser.Id);
|
||||
userGroupSave.Users = userIds;
|
||||
}
|
||||
|
||||
//save the group
|
||||
Services.UserService.Save(userGroupSave.PersistedUserGroup, userGroupSave.Users.ToArray());
|
||||
|
||||
@@ -148,4 +157,4 @@ namespace Umbraco.Web.Editors
|
||||
Services.TextService.Localize("speechBubbles/deleteUserGroupSuccess", new[] {userGroups[0].Name}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -965,5 +965,37 @@ namespace Umbraco.Web
|
||||
|
||||
#endregion
|
||||
|
||||
#region RelatedLink
|
||||
|
||||
/// <summary>
|
||||
/// Renders an anchor element for a RelatedLink instance.
|
||||
/// Format: <a href="relatedLink.Link" target="_blank/_self">relatedLink.Caption</a>
|
||||
/// </summary>
|
||||
/// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
|
||||
/// <param name="relatedLink">The RelatedLink instance</param>
|
||||
/// <returns>An anchor element </returns>
|
||||
public static MvcHtmlString GetRelatedLinkHtml(this HtmlHelper htmlHelper, RelatedLink relatedLink)
|
||||
{
|
||||
return htmlHelper.GetRelatedLinkHtml(relatedLink, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders an anchor element for a RelatedLink instance, accepting htmlAttributes.
|
||||
/// Format: <a href="relatedLink.Link" target="_blank/_self" htmlAttributes>relatedLink.Caption</a>
|
||||
/// </summary>
|
||||
/// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
|
||||
/// <param name="relatedLink">The RelatedLink instance</param>
|
||||
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.</param>
|
||||
/// <returns></returns>
|
||||
public static MvcHtmlString GetRelatedLinkHtml(this HtmlHelper htmlHelper, RelatedLink relatedLink, object htmlAttributes)
|
||||
{
|
||||
var tagBuilder = new TagBuilder("a");
|
||||
tagBuilder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
|
||||
tagBuilder.MergeAttribute("href", relatedLink.Link);
|
||||
tagBuilder.MergeAttribute("target", relatedLink.NewWindow ? "_blank" : "_self");
|
||||
tagBuilder.InnerHtml = HttpUtility.HtmlEncode(relatedLink.Caption);
|
||||
return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
[PropertyEditor(Constants.PropertyEditors.MemberGroupPickerAlias, "Member Group Picker", "membergrouppicker", Group="People", Icon="icon-users")]
|
||||
[PropertyEditor(Constants.PropertyEditors.MemberGroupPickerAlias, "Member Group Picker", PropertyEditorValueTypes.Text, "membergrouppicker", Group="People", Icon="icon-users")]
|
||||
public class MemberGroupPickerPropertyEditor : PropertyEditor
|
||||
{
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -63,10 +63,11 @@ namespace Umbraco.Web.Scheduling
|
||||
private async Task<bool> GetTaskByHttpAync(string url, CancellationToken token)
|
||||
{
|
||||
if (_httpClient == null)
|
||||
_httpClient = new HttpClient();
|
||||
|
||||
if (Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri))
|
||||
_httpClient.BaseAddress = baseUri;
|
||||
{
|
||||
_httpClient = Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri)
|
||||
? new HttpClient { BaseAddress = baseUri }
|
||||
: new HttpClient();
|
||||
}
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
|
||||
|
||||
@@ -238,7 +238,10 @@ namespace Umbraco.Web.Trees
|
||||
menu.Items.Add<ActionRights>(ui.Text("actions", ActionRights.Instance.Alias), true);
|
||||
menu.Items.Add<ActionProtect>(ui.Text("actions", ActionProtect.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
|
||||
|
||||
menu.Items.Add<ActionNotify>(ui.Text("actions", ActionNotify.Instance.Alias), true);
|
||||
if (EmailSender.CanSendRequiredEmail)
|
||||
{
|
||||
menu.Items.Add<ActionNotify>(ui.Text("actions", ActionNotify.Instance.Alias), true);
|
||||
}
|
||||
menu.Items.Add<ActionSendToTranslate>(ui.Text("actions", ActionSendToTranslate.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
|
||||
|
||||
menu.Items.Add<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace Umbraco.Web.UI
|
||||
|
||||
typeInstance.TypeID = typeId;
|
||||
typeInstance.ParentID = nodeId;
|
||||
typeInstance.Alias = text;
|
||||
typeInstance.Alias = text.CleanForXss();
|
||||
|
||||
// check for returning url
|
||||
ITaskReturnUrl returnUrlTask = typeInstance as LegacyDialogTask;
|
||||
|
||||
@@ -243,7 +243,7 @@ namespace Umbraco.Web.WebServices
|
||||
// sanitize input - stylesheet names have no extension
|
||||
var svce = (FileService)Services.FileService;
|
||||
|
||||
filename = CleanFilename(filename);
|
||||
filename = CleanFilename(filename.CleanForXss());
|
||||
oldName = CleanFilename(oldName);
|
||||
|
||||
if (filename != oldName)
|
||||
|
||||
@@ -84,14 +84,19 @@ namespace umbraco.presentation.umbraco.translation {
|
||||
pageRow[ui.Text("name")] = ui.Text("nodeName");
|
||||
pageRow[ui.Text("value")] = page.Text;
|
||||
pageTable.Rows.Add(pageRow);
|
||||
|
||||
foreach (PropertyType pt in page.ContentType.PropertyTypes) {
|
||||
|
||||
foreach (PropertyType pt in page.ContentType.PropertyTypes)
|
||||
{
|
||||
pageRow = pageTable.NewRow();
|
||||
pageRow[ui.Text("name")] = pt.Name;
|
||||
pageRow[ui.Text("value")] = page.getProperty(pt.Alias).Value;
|
||||
var property = page.getProperty(pt.Alias);
|
||||
if (property != null && property.Value != null)
|
||||
{
|
||||
pageRow[ui.Text("value")] = property.Value;
|
||||
}
|
||||
pageTable.Rows.Add(pageRow);
|
||||
}
|
||||
|
||||
|
||||
dg_fields.DataSource = pageTable;
|
||||
dg_fields.DataBind();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user