Compare commits

..

1 Commits

Author SHA1 Message Date
Anders Bjerner e8b320d7b4 Introduced properties overlay 2018-12-23 02:13:57 +01:00
70 changed files with 668 additions and 962 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ This document gives you a quick overview on how to get started, we will link to
## Guidelines for contributions we welcome
Not all changes are wanted, so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valuable time.
Not all changes are wanted, so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valueable time.
We have [documented what we consider small and large changes](CONTRIBUTION_GUIDELINES.md). Make sure to talk to us before making large changes.
+20 -20
View File
@@ -3,57 +3,57 @@
[string]$Directory
)
$workingDirectory = $Directory
CD "$($workingDirectory)"
CD $workingDirectory
# Clone repo
$fullGitUrl = "https://$($env:GIT_URL)/$($env:GIT_REPOSITORYNAME).git"
git clone $($fullGitUrl) $($env:GIT_REPOSITORYNAME) 2>&1 | % { $_.ToString() }
$fullGitUrl = "https://$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
git clone $fullGitUrl 2>&1 | % { $_.ToString() }
# Remove everything so that unzipping the release later will update everything
# Don't remove the readme file nor the git directory
Write-Host "Cleaning up git directory before adding new version"
Remove-Item -Recurse "$($workingDirectory)\$($env:GIT_REPOSITORYNAME)\*" -Exclude README.md,.git
Remove-Item -Recurse $workingDirectory\$env:GIT_REPOSITORYNAME\* -Exclude README.md,.git
# Find release zip
$zipsDir = "$($workingDirectory)\$($env:BUILD_DEFINITIONNAME)\zips"
$zipsDir = "$workingDirectory\$env:BUILD_DEFINITIONNAME\zips"
$pattern = "UmbracoCms.([0-9]{1,2}.[0-9]{1,3}.[0-9]{1,3}).zip"
Write-Host "Searching for Umbraco release files in $($zipsDir) for a file with pattern $($pattern)"
$file = (Get-ChildItem "$($zipsDir)" | Where-Object { $_.Name -match "$($pattern)" })
Write-Host "Searching for Umbraco release files in $workingDirectory\$zipsDir for a file with pattern $pattern"
$file = (Get-ChildItem $zipsDir | Where-Object { $_.Name -match "$pattern" })
if($file)
{
# Get release name
$version = [regex]::Match($($file.Name), $($pattern)).captures.groups[1].value
$releaseName = "Umbraco $($version)"
Write-Host "Found $($releaseName)"
$version = [regex]::Match($file.Name, $pattern).captures.groups[1].value
$releaseName = "Umbraco $version"
Write-Host "Found $releaseName"
# Unzip into repository to update release
Add-Type -AssemblyName System.IO.Compression.FileSystem
Write-Host "Unzipping $($file.FullName) to $($workingDirectory)\$($env:GIT_REPOSITORYNAME)"
[System.IO.Compression.ZipFile]::ExtractToDirectory("$($file.FullName)", "$($workingDirectory)\$($env:GIT_REPOSITORYNAME)")
Write-Host "Unzipping $($file.FullName) to $workingDirectory\$env:GIT_REPOSITORYNAME"
[System.IO.Compression.ZipFile]::ExtractToDirectory("$($file.FullName)", "$workingDirectory\$env:GIT_REPOSITORYNAME")
# Telling git who we are
git config --global user.email "coffee@umbraco.com" 2>&1 | % { $_.ToString() }
git config --global user.name "Umbraco HQ" 2>&1 | % { $_.ToString() }
# Commit
CD "$($workingDirectory)\$($env:GIT_REPOSITORYNAME)"
Write-Host "Committing Umbraco $($version) Release from Build Output"
CD $env:GIT_REPOSITORYNAME
Write-Host "Committing Umbraco $version Release from Build Output"
git add . 2>&1 | % { $_.ToString() }
git commit -m " Release $($releaseName) from Build Output" 2>&1 | % { $_.ToString() }
git commit -m " Release $releaseName from Build Output" 2>&1 | % { $_.ToString() }
# Tag the release
git tag -a "v$($version)" -m "v$($version)"
git tag -a "v$version" -m "v$version"
# Push release to master
$fullGitAuthUrl = "https://$($env:GIT_USERNAME):$($GitHubPersonalAccessToken)@$($env:GIT_URL)/$($env:GIT_REPOSITORYNAME).git"
git push $($fullGitAuthUrl) 2>&1 | % { $_.ToString() }
$fullGitAuthUrl = "https://$($env:GIT_USERNAME):$GitHubPersonalAccessToken@$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
git push $fullGitAuthUrl 2>&1 | % { $_.ToString() }
#Push tag to master
git push $($fullGitAuthUrl) --tags 2>&1 | % { $_.ToString() }
git push $fullGitAuthUrl --tags 2>&1 | % { $_.ToString() }
}
else
{
Write-Error "Umbraco release file not found, searched in $($workingDirectory)\$($zipsDir) for a file with pattern $($pattern) - canceling"
Write-Error "Umbraco release file not found, searched in $workingDirectory\$zipsDir for a file with pattern $pattern - cancelling"
}
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.13.2")]
[assembly: AssemblyInformationalVersion("7.13.2")]
[assembly: AssemblyFileVersion("7.13.0")]
[assembly: AssemblyInformationalVersion("7.13.0")]
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.13.2");
private static readonly Version Version = new Version("7.13.0");
/// <summary>
/// Gets the current version of Umbraco.
+2 -11
View File
@@ -1,6 +1,4 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
@@ -295,12 +293,6 @@ namespace Umbraco.Core.IO
{
var property = GetProperty(content, propertyTypeAlias);
var svalue = property.Value as string;
if (svalue != null && svalue.DetectIsJson())
{
// the property value is a JSON serialized image crop data set - grab the "src" property as the file source
var jObject = JsonConvert.DeserializeObject<JObject>(svalue);
svalue = jObject != null ? jObject.GetValueAsString("src") : svalue;
}
var oldpath = svalue == null ? null : GetRelativePath(svalue);
var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath);
property.Value = GetUrl(filepath);
@@ -365,8 +357,7 @@ namespace Umbraco.Core.IO
{
var jpgInfo = ImageFile.FromStream(stream);
if (jpgInfo != null
&& jpgInfo.Format != ImageFileFormat.Unknown
if (jpgInfo.Format != ImageFileFormat.Unknown
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension)
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension))
{
+4 -5
View File
@@ -118,9 +118,9 @@ namespace Umbraco.Core.Media.Exif
/// <param name="encoding">The encoding to be used for text metadata when the source encoding is unknown.</param>
/// <returns>The <see cref="ImageFile"/> created from the file.</returns>
public static ImageFile FromStream(Stream stream, Encoding encoding)
{
{
// JPEG
if (JPEGDetector.IsOfType(stream))
if(JPEGDetector.IsOfType(stream))
{
return new JPEGFile(stream, encoding);
}
@@ -137,9 +137,8 @@ namespace Umbraco.Core.Media.Exif
return new SVGFile(stream);
}
// We don't know
return null;
}
throw new NotValidImageFileException ();
}
#endregion
}
}
@@ -7,7 +7,8 @@ namespace Umbraco.Core.Media.TypeDetector
public static bool IsOfType(Stream fileStream)
{
var header = GetFileHeader(fileStream);
return header != null && header[0] == 0xff && header[1] == 0xD8;
return header[0] == 0xff && header[1] == 0xD8;
}
}
}
@@ -7,13 +7,9 @@ namespace Umbraco.Core.Media.TypeDetector
public static byte[] GetFileHeader(Stream fileStream)
{
fileStream.Seek(0, SeekOrigin.Begin);
var header = new byte[8];
byte[] header = new byte[8];
fileStream.Seek(0, SeekOrigin.Begin);
// Invalid header
if (fileStream.Read(header, 0, header.Length) != header.Length)
return null;
return header;
}
}
@@ -7,17 +7,17 @@ namespace Umbraco.Core.Media.TypeDetector
{
public static bool IsOfType(Stream fileStream)
{
var tiffHeader = GetFileHeader(fileStream);
return tiffHeader != null && tiffHeader == "MM\x00\x2a" || tiffHeader == "II\x2a\x00";
string tiffHeader = GetFileHeader(fileStream);
return tiffHeader == "MM\x00\x2a" || tiffHeader == "II\x2a\x00";
}
public static string GetFileHeader(Stream fileStream)
{
var header = RasterizedTypeDetector.GetFileHeader(fileStream);
if (header == null)
return null;
var tiffHeader = Encoding.ASCII.GetString(header, 0, 4);
string tiffHeader = Encoding.ASCII.GetString(header, 0, 4);
return tiffHeader;
}
}
@@ -1,36 +0,0 @@
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()
{
}
}
}
@@ -42,22 +42,16 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
var sourceAsString = source?.ToString();
if(sourceAsString.IsNullOrWhiteSpace())
{
return new string[0];
}
// if Json storage type deserialzie and return as string array
if (JsonStorageType(propertyType.DataTypeId))
{
var jArray = JsonConvert.DeserializeObject<JArray>(sourceAsString);
var jArray = JsonConvert.DeserializeObject<JArray>(source.ToString());
return jArray.ToObject<string[]>();
}
// Otherwise assume CSV storage type and return as string array
var csvTags =
sourceAsString
source.ToString()
.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
.ToArray();
return csvTags;
+1 -1
View File
@@ -509,7 +509,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IMedia> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren,
string orderBy, Direction orderDirection, bool orderBySystemField, string filter)
{
return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter, null);
return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filter, null);
}
/// <summary>
+2 -1
View File
@@ -189,6 +189,7 @@ namespace Umbraco.Core
outputArray[i] = char.IsLetterOrDigit(inputArray[i]) ? inputArray[i] : replacement;
return new string(outputArray);
}
private static readonly char[] CleanForXssChars = "*?(){}[];:%<>/\\|&'\"".ToCharArray();
/// <summary>
@@ -541,7 +542,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>
-1
View File
@@ -572,7 +572,6 @@
<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,17 +61,6 @@ 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,30 +29,5 @@ 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,7 +11,8 @@ LazyLoad.js([
'../js/umbraco.security.js',
'../ServerVariables',
'../lib/spectrum/spectrum.js',
'../js/umbraco.canvasdesigner.js'
'../js/umbraco.canvasdesigner.js',
'../js/canvasdesigner.panel.js'
], function () {
jQuery(document).ready(function () {
angular.bootstrap(document, ['Umbraco.canvasdesigner']);
@@ -18,7 +18,6 @@
<umb-toggle
checked="vm.checked"
disabled="vm.disabled"
on-click="vm.toggle()"
show-labels="true"
label-on="Start"
@@ -39,7 +38,6 @@
var vm = this;
vm.checked = false;
vm.disabled = false;
vm.toggle = toggle;
@@ -54,7 +52,6 @@
</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".
@@ -118,7 +115,6 @@
templateUrl: 'views/components/buttons/umb-toggle.html',
scope: {
checked: "=",
disabled: "=",
onClick: "&",
labelOn: "@?",
labelOff: "@?",
@@ -53,9 +53,6 @@
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) {
@@ -14,8 +14,7 @@ angular.module("umbraco.directives")
scope: {
src: '=',
center: "=",
onImageLoaded: "&",
onGravityChanged: "&"
onImageLoaded: "&"
},
link: function(scope, element, attrs) {
@@ -53,7 +52,7 @@ angular.module("umbraco.directives")
calculateGravity(offsetX, offsetY);
gravityChanged();
lazyEndEvent();
};
var setDimensions = function () {
@@ -78,11 +77,12 @@ angular.module("umbraco.directives")
scope.center.top = (scope.dimensions.top+10) / scope.dimensions.height;
};
var gravityChanged = function () {
if (angular.isFunction(scope.onGravityChanged)) {
scope.onGravityChanged();
}
};
var lazyEndEvent = _.debounce(function(){
scope.$apply(function(){
scope.$emit("imageFocalPointStop");
});
}, 2000);
//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);
});
gravityChanged();
lazyEndEvent();
}
});
@@ -86,21 +86,20 @@ 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.placeholderText = scope.labels.idle;
scope.alias = safeAlias.alias;
}
});
}, 500);
@@ -109,6 +108,7 @@ 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 === "" || scope.alias === null || scope.alias === undefined) {
if (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 === "" && bindWatcher === true || scope.alias === null && bindWatcher === true) {
// add watcher
eventBindings.push(scope.$watch('aliasFrom', function(newValue, oldValue) {
if(bindWatcher) {
generateAlias(newValue);
}
}));
}
}));
// clean up
@@ -38,7 +38,7 @@ Use this directive to generate color swatches to pick from.
scope.selectedColor = color;
if (scope.onSelect) {
scope.onSelect({color: color });
scope.onSelect(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, localizationService) {
function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
return {
@@ -106,16 +106,13 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper, localiz
*
*/
deleteByPath: function (type, virtualpath) {
var promise = localizationService.localize("codefile_deleteItemFailed", [virtualpath]);
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"codeFileApiBaseUrl",
"Delete",
[{ type: type }, { virtualPath: virtualpath}])),
promise);
"Failed to delete item: " + virtualpath);
},
/**
@@ -239,19 +236,13 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper, localiz
*
*/
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]);
createContainer: function(type, parentId, name) {
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl(
"codeFileApiBaseUrl",
"PostCreateContainer",
{ type: type, parentId: parentId, name: encodeURIComponent(name) })),
promise);
'Failed to create a folder under parent id ' + parentId);
}
};
@@ -3,7 +3,7 @@
* @name umbraco.resources.templateResource
* @description Loads in data for templates
**/
function templateResource($q, $http, umbDataFormatter, umbRequestHelper, localizationService) {
function templateResource($q, $http, umbDataFormatter, umbRequestHelper) {
return {
@@ -152,16 +152,13 @@ function templateResource($q, $http, umbDataFormatter, umbRequestHelper, localiz
*
*/
deleteById: function(id) {
var promise = localizationService.localize("template_deleteByIdFailed", [id]);
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"templateApiBaseUrl",
"DeleteById",
[{ id: id }])),
promise);
"Failed to delete item " + id);
},
/**
@@ -28,8 +28,7 @@
.umb-toggle__toggle {
cursor: pointer;
align-items: center;
display: flex;
display: inline-block;
width: 48px;
height: 24px;
background: @gray-8;
@@ -42,11 +41,6 @@
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);
}
@@ -69,7 +63,7 @@
.umb-toggle__icon {
position: absolute;
line-height: 1em;
top: 3px;
text-decoration: none;
transition: all 0.2s ease;
}
@@ -165,7 +165,7 @@ input.umb-table__input {
}
.-content .-unpublished:not(.with-unpublished-version) {
.-content :not(.with-unpublished-version).-unpublished {
.umb-table__name > * {
opacity: .4;
}
@@ -21,12 +21,6 @@
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;
@@ -17,14 +17,12 @@
-webkit-font-smoothing: antialiased;
*margin-right: .3em;
}
[class^="icon-"]:before,
[class*=" icon-"]:before {
text-decoration: inherit;
display: inline-block;
speak: none;
}
/*
[class^="icon-"]:before, [class*=" icon-"]:before {
font-family: 'icomoon';
@@ -40,6 +38,7 @@
i.large{
font-size: 32px;
}
i.medium{
font-size: 24px;
}
@@ -188,6 +187,8 @@ i.small{
.icon-umb-translation:before, .traytranslation:before {
content: "\e1fd";
}
.icon-tv:before {
content: "\e02e";
}
@@ -212,8 +213,7 @@ i.small{
.icon-train:before {
content: "\e035";
}
.icon-trafic:before,
.icon-traffic:before {
.icon-trafic:before {
content: "\e036";
}
.icon-traffic-alt:before {
@@ -255,7 +255,6 @@ i.small{
.icon-target:before {
content: "\e043";
}
.icon-temperature-alt:before,
.icon-temperatrure-alt:before {
content: "\e044";
}
@@ -268,7 +267,6 @@ i.small{
.icon-theater:before {
content: "\e047";
}
.icon-thief:before,
.icon-theif:before {
content: "\e048";
}
@@ -377,7 +375,6 @@ i.small{
.icon-shuffle:before {
content: "\e06b";
}
.icon-science:before,
.icon-sience:before {
content: "\e06c";
}
@@ -750,7 +747,6 @@ i.small{
.icon-pictures-alt-2:before {
content: "\e0e7";
}
.icon-panel-close:before,
.icon-pannel-close:before {
content: "\e0e8";
}
@@ -1631,7 +1627,6 @@ i.small{
.icon-alarm-clock:before {
content: "\e20c";
}
.icon-addressbook:before,
.icon-adressbook:before {
content: "\e20d";
}
@@ -1,5 +1,3 @@
@checkered-background: url(../img/checkered-background.png);
//
// Container styles
// --------------------------------------------------
@@ -388,7 +386,7 @@ div.umb-codeeditor .umb-btn-toolbar {
max-height:100%;
margin:auto;
display:block;
background-image: @checkered-background;
background-image: url(../img/checkered-background.png);
}
.umb-sortable-thumbnails li .trashed {
@@ -601,18 +599,12 @@ div.umb-codeeditor .umb-btn-toolbar {
vertical-align: top;
}
.gravity-container {
border: 1px solid @gray-8;
line-height: 0;
.gravity-container .viewport {
max-width: 600px;
}
.viewport {
max-width: 600px;
background: @checkered-background;
&:hover {
cursor: pointer;
}
}
.gravity-container .viewport:hover {
cursor: pointer;
}
.imagecropper {
@@ -625,10 +617,6 @@ div.umb-codeeditor .umb-btn-toolbar {
float: left;
max-width: 100%;
}
.viewport img {
background: @checkered-background;
}
}
.imagecropper .umb-cropper__container {
@@ -896,10 +884,6 @@ div.umb-codeeditor .umb-btn-toolbar {
list-style: none;
vertical-align: middle;
margin-bottom: 0;
img {
background: @checkered-background;
}
}
.umb-fileupload label {
@@ -25,31 +25,30 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
$scope.showTarget = $scope.model.hideTarget !== true;
if (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);
$scope.model.target = 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;
// 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"
});
});
if (!$scope.model.target.path) {
// 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));
});
}
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));
});
} 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 ?
@@ -123,12 +122,6 @@ 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"
});
}
};
});
@@ -0,0 +1,7 @@
<div>
<form ng-submit="model.submit(model)">
<umb-property property="property" ng-repeat="property in model.properties">
<umb-property-editor model="property"></umb-property-editor>
</umb-property>
</form>
</div>
@@ -1,4 +1,4 @@
<button ng-click="click()" type="button" class="umb-toggle" ng-disabled="disabled" ng-class="{'umb-toggle--checked': checked, 'umb-toggle--disabled': disabled}">
<button ng-click="click()" type="button" class="umb-toggle" ng-class="{'umb-toggle--checked': checked}">
<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" ng-if="allowScheduledPublishing">
<umb-box data-element="node-info-scheduled-publishing">
<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 ng-if="item.extension">.{{item.extension}}</span>
<span>.{{item.extension}}</span>
</span>
</div>
</div>
@@ -3,8 +3,7 @@
$scope,
contentResource,
navigationService,
angularHelper,
localizationService) {
angularHelper) {
var vm = this;
var currentForm;
vm.notifyOptions = [];
@@ -12,8 +11,7 @@
vm.cancel = cancel;
vm.message = {
name: $scope.currentNode.name
};
vm.labels = {};
};;
function onInit() {
vm.loading = true;
contentResource.getNotifySettingsById($scope.currentNode.id).then(function (options) {
@@ -21,9 +19,6 @@
vm.loading = false;
vm.notifyOptions = options;
});
localizationService.localize("notifications_editNotifications", [$scope.currentNode.name]).then(function(value) {
vm.labels.headline = value;
});
}
function cancel() {
navigationService.hideMenu();
@@ -11,17 +11,14 @@
<div ng-show="success">
<div class="alert alert-success">
<strong>{{currentNode.name}}</strong>
<localize key="actions_wasCopiedTo">was copied to</localize>
<strong>{{currentNode.name}}</strong> was copied to
<strong>{{target.name}}</strong>
</div>
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
</div>
<p class="abstract" ng-hide="success">
<localize key="actions_chooseWhereToCopy">Choose where to copy</localize>
<strong>{{currentNode.name}}</strong>
<localize key="actions_toInTheTreeStructureBelow">to in the tree structure below</localize>
Choose where to copy <strong>{{currentNode.name}}</strong> to in the tree structure below
</p>
<div class="umb-loader-wrapper" ng-show="busy">
@@ -11,9 +11,7 @@
<div ng-show="success">
<div class="alert alert-success">
<strong>{{currentNode.name}}</strong>
<localize key="actions_wasMovedTo">was moved to</localize>
<strong>{{target.name}}</strong>
<strong>{{currentNode.name}}</strong> was moved underneath&nbsp;<strong>{{target.name}}</strong>
</div>
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
</div>
@@ -13,13 +13,13 @@
</div>
<div ng-show="vm.saveSuccces" ng-cloak>
<div class="alert alert-success">
<localize key="notifications_notificationsSavedFor"></localize> <strong>{{currentNode.name}}</strong>
<localize key="notify_notificationsSavedFor"></localize><strong> {{currentNode.name}}</strong>
</div>
<button class="btn btn-primary" ng-click="vm.cancel()"><localize key="general_ok">Ok</localize></button>
</div>
<div ng-hide="vm.saveSuccces || vm.saveError" ng-cloak>
<div class="block-form" ng-show="!vm.loading">
<span ng-bind-html="vm.labels.headline"></span>
<localize key="notify_notifySet">Set your notification for</localize> <strong>{{ currentNode.name }}</strong>
<umb-control-group>
<umb-permission ng-repeat="option in vm.notifyOptions"
name="option.name"
@@ -11,9 +11,7 @@
<div ng-show="success">
<div class="alert alert-success">
<strong>{{currentNode.name}}</strong>
<localize key="actions_wasMovedTo">was moved to</localize>
<strong>{{target.name}}</strong>
<strong>{{currentNode.name}}</strong> was moved underneath <strong>{{target.name}}</strong>
</div>
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
</div>
@@ -57,7 +57,7 @@
</div>
</div>
<umb-control-group label="@create_enterFolderName" localize="label" hide-label="false">
<umb-control-group label="Enter a folder name" 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,9 +12,6 @@ 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() {
@@ -24,9 +21,6 @@ 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,13 +1,6 @@
<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>
@@ -1,4 +1,4 @@
function ColorPickerController($scope, angularHelper) {
function ColorPickerController($scope) {
//setup the default config
var config = {
@@ -12,12 +12,31 @@ function ColorPickerController($scope, angularHelper) {
//map back to the model
$scope.model.config = config;
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
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] });
}
$scope.model.activeColor = {
value: "",
label: ""
};
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;
if ($scope.isConfigured) {
@@ -58,7 +77,29 @@ function ColorPickerController($scope, angularHelper) {
//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 || (
@@ -74,48 +115,33 @@ function ColorPickerController($scope, angularHelper) {
}
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
$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();
// 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) {
return;
}
// no value
if (!$scope.model.value)
return false;
// 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();
}
// 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;
};
// 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 - initialize default value
// no value
if (!$scope.model.value)
return;
// Backwards compatibility, the color used to be stored as a hex value only
if (typeof $scope.model.value === "string") {
$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;
@@ -156,8 +182,8 @@ function ColorPickerController($scope, angularHelper) {
// If a match was found, set it as the active color.
if (foundItem) {
$scope.model.activeColor.value = foundItem.value;
$scope.model.activeColor.label = foundItem.label;
$scope.model.value.value = foundItem.value;
$scope.model.value.label = foundItem.label;
}
}
@@ -6,10 +6,9 @@
</div>
<umb-color-swatches colors="model.config.items"
selected-color="model.activeColor.value"
selected-color="model.value.value"
size="m"
use-label="model.useLabel"
on-select="onSelect(color)">
use-label="model.useLabel">
</umb-color-swatches>
<input type="hidden" name="modelValue" ng-model="model.value" val-property-validator="validateMandatory" />
@@ -35,6 +35,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
return $scope.model.config.idType === "udi" ? i.udi : i.id;
});
$scope.model.value = trim(currIds.join(), ",");
angularHelper.getCurrentForm($scope).$setDirty();
//Validate!
if ($scope.model.config && $scope.model.config.minNumber && parseInt($scope.model.config.minNumber) > $scope.renderModel.length) {
@@ -83,10 +84,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
opacity: 0.7,
tolerance: "pointer",
scroll: true,
zIndex: 6000,
update: function (e, ui) {
angularHelper.getCurrentForm($scope).$setDirty();
}
zIndex: 6000
};
if ($scope.model.config) {
@@ -52,7 +52,6 @@ angular.module('umbraco')
});
editedCrop.coordinates = $scope.currentCrop.coordinates;
$scope.close();
angularHelper.getCurrentForm($scope).$setDirty();
};
//reset the current crop
@@ -99,10 +98,6 @@ 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,8 +40,7 @@
<umb-image-gravity
src="imageSrc"
center="model.value.focalPoint"
on-image-loaded="imageLoaded(isCroppable, hasDimensions)"
on-gravity-changed="focalPointChanged()">
on-image-loaded="imageLoaded(isCroppable, hasDimensions)">
</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, mediaHelper) {
function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService, navigationService, treeService) {
//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,12 +269,10 @@ 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);
// create the folders collection (only for media list views)
if (section === "media" && !mediaHelper.hasFilePropertyType(e)) {
if (e.contentTypeAlias === 'Folder') {
$scope.folders.push(e);
}
});
@@ -12,10 +12,6 @@ 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;
@@ -25,9 +21,6 @@ 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,18 +1,11 @@
<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>&nbsp;<strong>{{currentNode.name}}</strong> ?
</p>
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
</umb-confirm>
</div>
+3
View File
@@ -0,0 +1,3 @@
/Umbraco/**
/Umbraco_Client/**
+3 -2
View File
@@ -520,6 +520,7 @@
</Content>
<Content Include="Umbraco\Install\Views\Web.config" />
<Content Include="App_Plugins\ModelsBuilder\package.manifest" />
<Content Include=".eslintignore" />
<None Include="Config\404handlers.Release.config">
<DependentUpon>404handlers.config</DependentUpon>
</None>
@@ -1038,9 +1039,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7132</DevelopmentServerPort>
<DevelopmentServerPort>7130</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7132</IISUrl>
<IISUrl>http://localhost:7130</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
+2 -14
View File
@@ -32,11 +32,8 @@
<key alias="rename" version="7.3.0">Omdøb</key>
<key alias="restore" version="7.3.0">Gendan</key>
<key alias="SetPermissionsForThePage">Sæt rettigheder for siden %0%</key>
<key alias="chooseWhereToCopy">Vælg hvor du vil kopiere</key>
<key alias="chooseWhereToMove">Vælg hvortil du vil flytte</key>
<key alias="toInTheTreeStructureBelow">til i træstrukturen nedenfor</key>
<key alias="wasMovedTo">blev flyttet til</key>
<key alias="wasCopiedTo">blev kopieret til</key>
<key alias="toInTheTreeStructureBelow">I træstrukturen nedenfor</key>
<key alias="rights">Rettigheder</key>
<key alias="rollback">Fortryd ændringer</key>
<key alias="sendtopublish">Send til udgivelse</key>
@@ -182,11 +179,6 @@
<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>
@@ -287,7 +279,6 @@
<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>
@@ -839,8 +830,7 @@
<key alias="relateToOriginal">Relater det kopierede element til originalen</key>
</area>
<area alias="notifications">
<key alias="editNotifications"><![CDATA[Vælg dine notificeringer for <strong>%0%</strong>]]></key>
<key alias="notificationsSavedFor">Notificeringer er gemt for</key>
<key alias="editNotifications">Rediger dine notificeringer for %0%</key>
<key alias="mailBody">
<![CDATA[
Hej %0%
@@ -1014,7 +1004,6 @@ Mange hilsner fra Umbraco robotten
<area alias="rollback">
<key alias="headline">Vælg en version at sammenligne med den nuværende version</key>
<key alias="currentVersion">Nuværende version</key>
<key alias="diffHelp"><![CDATA[Her vises forskellene mellem den nuværende version og den valgte version<br /><del>Rød</del> tekst vil ikke blive vist i den valgte version. <ins>Grøn betyder tilføjet</ins>]]></key>
<key alias="documentRolledBack">Dokument tilbagerullet</key>
@@ -1164,7 +1153,6 @@ 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>
+2 -14
View File
@@ -33,11 +33,8 @@
<key alias="rename" version="7.3.0">Rename</key>
<key alias="restore" version="7.3.0">Restore</key>
<key alias="SetPermissionsForThePage">Set permissions for the page %0%</key>
<key alias="chooseWhereToCopy">Choose where to copy</key>
<key alias="chooseWhereToMove">Choose where to move</key>
<key alias="toInTheTreeStructureBelow">to in the tree structure below</key>
<key alias="wasMovedTo">was moved to</key>
<key alias="wasCopiedTo">was copied to</key>
<key alias="toInTheTreeStructureBelow">In the tree structure below</key>
<key alias="rights">Permissions</key>
<key alias="rollback">Rollback</key>
<key alias="sendtopublish">Send To Publish</key>
@@ -188,11 +185,6 @@
<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>
@@ -295,7 +287,6 @@
<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>
@@ -1047,8 +1038,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="relateToOriginal">Relate copied items to original</key>
</area>
<area alias="notifications">
<key alias="editNotifications"><![CDATA[Select your notification for <strong>%0%</strong>]]></key>
<key alias="notificationsSavedFor">Notification settings saved for</key>
<key alias="editNotifications">Edit your notification for %0%</key>
<key alias="mailBody">
<![CDATA[
Hi %0%
@@ -1320,7 +1310,6 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="undoEditCrop">Undo edits</key>
</area>
<area alias="rollback">
<key alias="headline">Select a version to compare with the current version</key>
<key alias="currentVersion">Current version</key>
<key alias="diffHelp"><![CDATA[This shows the differences between the current version and the selected version<br /><del>Red</del> text will not be shown in the selected version. , <ins>green means added</ins>]]></key>
<key alias="documentRolledBack">Document has been rolled back</key>
@@ -1489,7 +1478,6 @@ 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>
@@ -33,11 +33,8 @@
<key alias="rename" version="7.3.0">Rename</key>
<key alias="restore" version="7.3.0">Restore</key>
<key alias="SetPermissionsForThePage">Set permissions for the page %0%</key>
<key alias="chooseWhereToCopy">Choose where to copy</key>
<key alias="chooseWhereToMove">Choose where to move</key>
<key alias="toInTheTreeStructureBelow">to in the tree structure below</key>
<key alias="wasMovedTo">was moved to</key>
<key alias="wasCopiedTo">was copied to</key>
<key alias="toInTheTreeStructureBelow">In the tree structure below</key>
<key alias="rights">Permissions</key>
<key alias="rollback">Rollback</key>
<key alias="sendtopublish">Send To Publish</key>
@@ -189,11 +186,6 @@
<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>
@@ -297,7 +289,6 @@
<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>
@@ -1046,8 +1037,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="relateToOriginal">Relate copied items to original</key>
</area>
<area alias="notifications">
<key alias="editNotifications"><![CDATA[Select your notification for <strong>%0%</strong>]]></key>
<key alias="notificationsSavedFor">Notification settings saved for</key>
<key alias="editNotifications">Edit your notification for %0%</key>
<key alias="mailBody">
<![CDATA[
Hi %0%
@@ -1319,7 +1309,6 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="undoEditCrop">Undo edits</key>
</area>
<area alias="rollback">
<key alias="headline">Select a version to compare with the current version</key>
<key alias="currentVersion">Current version</key>
<key alias="diffHelp"><![CDATA[This shows the differences between the current version and the selected version<br /><del>Red</del> text will not be shown in the selected version. , <ins>green means added</ins>]]></key>
<key alias="documentRolledBack">Document has been rolled back</key>
@@ -1487,7 +1476,6 @@ 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>
@@ -2232,4 +2220,8 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="itemCannotBeRestoredHelpText">There is no location where this item can be automatically restored. You can move the item manually using the tree below.</key>
<key alias="wasRestored">was restored under</key>
</area>
<area alias="notify">
<key alias="notifySet">Select your notifications for</key>
<key alias="notificationsSavedFor">Notification settings saved for </key>
</area>
</language>
@@ -55,7 +55,7 @@
</div>
<div runat="server" id="pl_buttons" class="umb-dialog-footer btn-toolbar umb-btn-toolbar">
<a href="#" class="btn btn-link" onclick="UmbClientMgr.closeModalWindow()"><%=umbraco.ui.Text("general", "close")%></a>
<a href="#" class="btn btn-link" onclick="UmbClientMgr.closeModalWindow()"><%=umbraco.ui.Text("general", "cancel")%></a>
<asp:Button ID="Button1" runat="server" visible="false" CssClass="btn btn-primary" OnClick="doRollback_Click"></asp:Button>
</div>
</asp:Content>
+1 -3
View File
@@ -349,9 +349,7 @@ namespace Umbraco.Web.Editors
var mapped = AutoMapperExtensions.MapWithUmbracoContext<IContent, ContentItemDisplay>(emptyContent, UmbracoContext);
// translate the content type name if applicable
mapped.ContentTypeName = Services.TextService.UmbracoDictionaryTranslate(mapped.ContentTypeName);
// if your user type doesn't have access to the Settings section it would not get this property mapped
if(mapped.DocumentType != null)
mapped.DocumentType.Name = Services.TextService.UmbracoDictionaryTranslate(mapped.DocumentType.Name);
mapped.DocumentType.Name = Services.TextService.UmbracoDictionaryTranslate(mapped.DocumentType.Name);
//remove this tab if it exists: umbContainerView
var containerTab = mapped.Tabs.FirstOrDefault(x => x.Alias == Constants.Conventions.PropertyGroups.ListViewGroupName);
+4 -5
View File
@@ -27,7 +27,7 @@ namespace Umbraco.Web.Editors
long totalRecords;
var dateQuery = sinceDate.HasValue ? Query<IAuditItem>.Builder.Where(x => x.CreateDate >= sinceDate) : null;
var result = Services.AuditService.GetPagedItemsByEntity(id, pageNumber - 1, pageSize, out totalRecords, orderDirection, customFilter: dateQuery);
var mapped = result.Select(item => Mapper.Map<AuditLog>(item));
var mapped = Mapper.Map<IEnumerable<AuditLog>>(result);
var page = new PagedResult<AuditLog>(totalRecords, pageNumber, pageSize)
{
@@ -85,17 +85,16 @@ namespace Umbraco.Web.Editors
private IEnumerable<AuditLog> MapAvatarsAndNames(IEnumerable<AuditLog> items)
{
var mappedItems = items.ToList();
var userIds = mappedItems.Select(x => x.UserId).ToArray();
var userIds = items.Select(x => x.UserId).ToArray();
var users = Services.UserService.GetUsersById(userIds)
.ToDictionary(x => x.Id, x => x.GetUserAvatarUrls(ApplicationContext.ApplicationCache.RuntimeCache));
var userNames = Services.UserService.GetUsersById(userIds).ToDictionary(x => x.Id, x => x.Name);
foreach (var item in mappedItems)
foreach (var item in items)
{
item.UserAvatars = users[item.UserId];
item.UserName = userNames[item.UserId];
}
return mappedItems;
return items;
}
}
}
+14 -23
View File
@@ -100,7 +100,7 @@ namespace Umbraco.Web.Editors
{
var errors = string.Join(". ", resetResult.Errors);
_logger.Warn<PasswordChanger>(string.Format("Could not reset user password {0}", errors));
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult(errors, new[] { "resetPassword" }) });
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not reset password, errors: " + errors, new[] { "resetPassword" }) });
}
return Attempt.Succeed(new PasswordChangedModel());
@@ -120,30 +120,21 @@ namespace Umbraco.Web.Editors
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "oldPassword" }) });
}
//get the user
var backOfficeIdentityUser = await userMgr.FindByIdAsync(savingUser.Id);
if (backOfficeIdentityUser == null)
if (passwordModel.OldPassword.IsNullOrWhiteSpace() == false)
{
//this really shouldn't ever happen... but just in case
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password could not be verified", new[] { "oldPassword" }) });
//if an old password is suplied try to change it
var changeResult = await userMgr.ChangePasswordAsync(savingUser.Id, passwordModel.OldPassword, passwordModel.NewPassword);
if (changeResult.Succeeded == false)
{
var errors = string.Join(". ", changeResult.Errors);
_logger.Warn<PasswordChanger>(string.Format("Could not change user password {0}", errors));
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, errors: " + errors, new[] { "oldPassword" }) });
}
return Attempt.Succeed(new PasswordChangedModel());
}
//is the old password correct?
var validateResult = await userMgr.CheckPasswordAsync(backOfficeIdentityUser, passwordModel.OldPassword);
if(validateResult == false)
{
//no, fail with an error message for "oldPassword"
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Incorrect password", new[] { "oldPassword" }) });
}
//can we change to the new password?
var changeResult = await userMgr.ChangePasswordAsync(savingUser.Id, passwordModel.OldPassword, passwordModel.NewPassword);
if (changeResult.Succeeded == false)
{
//no, fail with error messages for "password"
var errors = string.Join(". ", changeResult.Errors);
_logger.Warn<PasswordChanger>(string.Format("Could not change user password {0}", errors));
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult(errors, new[] { "password" }) });
}
return Attempt.Succeed(new PasswordChangedModel());
//We shouldn't really get here
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid information supplied", new[] { "value" }) });
}
/// <summary>
@@ -53,16 +53,6 @@ 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
@@ -129,4 +119,4 @@ namespace Umbraco.Web.Editors
return Attempt<string>.Succeed();
}
}
}
}
@@ -30,7 +30,6 @@ 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));
@@ -51,14 +50,6 @@ 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());
@@ -157,4 +148,4 @@ namespace Umbraco.Web.Editors
Services.TextService.Localize("speechBubbles/deleteUserGroupSuccess", new[] {userGroups[0].Name}));
}
}
}
}
@@ -965,37 +965,5 @@ namespace Umbraco.Web
#endregion
#region RelatedLink
/// <summary>
/// Renders an anchor element for a RelatedLink instance.
/// Format: &lt;a href=&quot;relatedLink.Link&quot; target=&quot;_blank/_self&quot;&gt;relatedLink.Caption&lt;/a&gt;
/// </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: &lt;a href=&quot;relatedLink.Link&quot; target=&quot;_blank/_self&quot; htmlAttributes&gt;relatedLink.Caption&lt;/a&gt;
/// </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", PropertyEditorValueTypes.Text, "membergrouppicker", Group="People", Icon="icon-users")]
[PropertyEditor(Constants.PropertyEditors.MemberGroupPickerAlias, "Member Group Picker", "membergrouppicker", Group="People", Icon="icon-users")]
public class MemberGroupPickerPropertyEditor : PropertyEditor
{
}
File diff suppressed because it is too large Load Diff
+4 -5
View File
@@ -63,11 +63,10 @@ namespace Umbraco.Web.Scheduling
private async Task<bool> GetTaskByHttpAync(string url, CancellationToken token)
{
if (_httpClient == null)
{
_httpClient = Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri)
? new HttpClient { BaseAddress = baseUri }
: new HttpClient();
}
_httpClient = new HttpClient();
if (Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri))
_httpClient.BaseAddress = baseUri;
var request = new HttpRequestMessage(HttpMethod.Get, url);
@@ -238,10 +238,7 @@ 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");
if (EmailSender.CanSendRequiredEmail)
{
menu.Items.Add<ActionNotify>(ui.Text("actions", ActionNotify.Instance.Alias), true);
}
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);
+1 -1
View File
@@ -207,7 +207,7 @@ namespace Umbraco.Web.UI
typeInstance.TypeID = typeId;
typeInstance.ParentID = nodeId;
typeInstance.Alias = text.CleanForXss();
typeInstance.Alias = text;
// 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.CleanForXss());
filename = CleanFilename(filename);
oldName = CleanFilename(oldName);
if (filename != oldName)
@@ -116,11 +116,6 @@ namespace umbraco.presentation.dialogs
currentVersionTitle.Text = currentDoc.Text;
currentVersionMeta.Text = ui.Text("content", "createDate") + ": " + currentDoc.VersionDate.ToShortDateString() + " " + currentDoc.VersionDate.ToShortTimeString();
pp_selectVersion.Text = ui.Text("rollback", "headline");
pp_currentVersion.Text = ui.Text("rollback", "currentVersion");
pp_view.Text = ui.Text("rollback", "view");
pp_rollBackTo.Text = ui.Text("rollback", "rollbackTo");
if (!IsPostBack) {
allVersions.Items.Add(new ListItem(ui.Text("rollback", "selectVersion")+ "...", ""));
@@ -84,19 +84,14 @@ 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;
var property = page.getProperty(pt.Alias);
if (property != null && property.Value != null)
{
pageRow[ui.Text("value")] = property.Value;
}
pageRow[ui.Text("value")] = page.getProperty(pt.Alias).Value;
pageTable.Rows.Add(pageRow);
}
dg_fields.DataSource = pageTable;
dg_fields.DataBind();
}