Merge remote-tracking branch 'origin/v8/dev' into v9/dev
# Conflicts: # src/Umbraco.Core/Composing/CompositionExtensions/Services.cs # src/Umbraco.Core/Constants-AppSettings.cs # src/Umbraco.Core/Dashboards/ContentDashboardSettings.cs # src/Umbraco.Core/Dashboards/IContentDashboardSettings.cs # src/Umbraco.Core/Manifest/ManifestParser.cs # src/Umbraco.Core/Manifest/PackageManifest.cs # src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs # src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs # src/Umbraco.Core/Models/PropertyTagsExtensions.cs # src/Umbraco.Core/PropertyEditors/ComplexPropertyEditorContentEventHandler.cs # src/Umbraco.Core/PropertyEditors/ConfigurationEditor.cs # src/Umbraco.Core/PropertyEditors/DataValueEditor.cs # src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValue.cs # src/Umbraco.Core/Serialization/JsonToStringConverter.cs # src/Umbraco.Core/Sync/ApplicationUrlHelper.cs # src/Umbraco.Core/Telemetry/ITelemetryService.cs # src/Umbraco.Core/Telemetry/Models/PackageTelemetry.cs # src/Umbraco.Core/Telemetry/Models/TelemetryReportData.cs # src/Umbraco.Core/Telemetry/TelemetryService.cs # src/Umbraco.Tests/Manifest/ManifestParserTests.cs # src/Umbraco.Tests/PropertyEditors/BlockEditorComponentTests.cs # src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs # src/Umbraco.Tests/PropertyEditors/NestedContentPropertyComponentTests.cs # src/Umbraco.Tests/Web/Controllers/AuthenticationControllerTests.cs # src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs # src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js # src/Umbraco.Web.UI/Umbraco/config/lang/da.xml # src/Umbraco.Web.UI/Umbraco/config/lang/en.xml # src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml # src/Umbraco.Web.UI/web.Template.config # src/Umbraco.Web/BatchedDatabaseServerMessenger.cs # src/Umbraco.Web/Cache/DistributedCacheBinder.cs # src/Umbraco.Web/Compose/BlockEditorComponent.cs # src/Umbraco.Web/Compose/NestedContentPropertyComponent.cs # src/Umbraco.Web/Editors/AuthenticationController.cs # src/Umbraco.Web/Editors/ContentTypeController.cs # src/Umbraco.Web/Editors/DashboardController.cs # src/Umbraco.Web/Editors/EntityController.cs # src/Umbraco.Web/Editors/UsersController.cs # src/Umbraco.Web/PropertyEditors/BlockEditorPropertyEditor.cs # src/Umbraco.Web/PropertyEditors/ColorPickerConfigurationEditor.cs # src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs # src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs # src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs # src/Umbraco.Web/PropertyEditors/MediaPicker3PropertyEditor.cs # src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs # src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs # src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs # src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs # src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs # src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs # src/Umbraco.Web/Telemetry/ReportSiteTask.cs # src/Umbraco.Web/Telemetry/TelemetryComponent.cs # src/Umbraco.Web/Trees/ContentTreeController.cs # src/Umbraco.Web/Umbraco.Web.csproj # src/Umbraco.Web/WebApi/EnableDetailedErrorsAttribute.cs
This commit is contained in:
@@ -68,12 +68,15 @@ namespace Umbraco.Extensions
|
||||
switch (storageType)
|
||||
{
|
||||
case TagsStorageType.Csv:
|
||||
property.SetValue(string.Join(delimiter.ToString(), currentTags.Union(trimmedTags)), culture); // csv string
|
||||
property.SetValue(string.Join(delimiter.ToString(), currentTags.Union(trimmedTags)).NullOrWhiteSpaceAsNull(), culture); // csv string
|
||||
break;
|
||||
|
||||
case TagsStorageType.Json:
|
||||
var updatedTags = currentTags.Union(trimmedTags).ToArray();
|
||||
var updatedValue = updatedTags.Length == 0 ? null : serializer.Serialize(updatedTags);
|
||||
property.SetValue(updatedValue, culture); // json array
|
||||
break;
|
||||
property.SetValue(serializer.Serialize(currentTags.Union(trimmedTags).ToArray()), culture); // json array
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -81,7 +84,7 @@ namespace Umbraco.Extensions
|
||||
switch (storageType)
|
||||
{
|
||||
case TagsStorageType.Csv:
|
||||
property.SetValue(string.Join(delimiter.ToString(), trimmedTags), culture); // csv string
|
||||
property.SetValue(string.Join(delimiter.ToString(), trimmedTags).NullOrWhiteSpaceAsNull(), culture); // csv string
|
||||
break;
|
||||
|
||||
case TagsStorageType.Json:
|
||||
@@ -124,11 +127,13 @@ namespace Umbraco.Extensions
|
||||
switch (storageType)
|
||||
{
|
||||
case TagsStorageType.Csv:
|
||||
property.SetValue(string.Join(delimiter.ToString(), currentTags.Except(trimmedTags)), culture); // csv string
|
||||
property.SetValue(string.Join(delimiter.ToString(), currentTags.Except(trimmedTags)).NullOrWhiteSpaceAsNull(), culture); // csv string
|
||||
break;
|
||||
|
||||
case TagsStorageType.Json:
|
||||
property.SetValue(serializer.Serialize(currentTags.Except(trimmedTags).ToArray()), culture); // json array
|
||||
var updatedTags = currentTags.Except(trimmedTags).ToArray();
|
||||
var updatedValue = updatedTags.Length == 0 ? null : serializer.Serialize(updatedTags);
|
||||
property.SetValue(updatedValue, culture); // json array
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +165,7 @@ namespace Umbraco.Extensions
|
||||
case TagsStorageType.Json:
|
||||
try
|
||||
{
|
||||
return serializer.Deserialize<string[]>(value).Select(x => x.ToString().Trim());
|
||||
return serializer.Deserialize<string[]>(value).Select(x => x.Trim());
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -197,6 +197,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
return value.TryConvertTo(valueType);
|
||||
}
|
||||
|
||||
@@ -232,6 +233,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
StaticApplicationLogging.Logger.LogWarning("The value {EditorValue} cannot be converted to the type {StorageTypeValue}", editorValue.Value, ValueTypes.ToStorageType(ValueType));
|
||||
return null;
|
||||
}
|
||||
|
||||
return result.Result;
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
MapBlockItemData(blockEditorData.BlockValue.SettingsData);
|
||||
|
||||
// return json
|
||||
return JsonConvert.SerializeObject(blockEditorData.BlockValue);
|
||||
return JsonConvert.SerializeObject(blockEditorData.BlockValue, Formatting.None);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
|
||||
UpdateBlockListRecursively(blockListValue, createGuid);
|
||||
|
||||
return JsonConvert.SerializeObject(blockListValue.BlockValue);
|
||||
return JsonConvert.SerializeObject(blockListValue.BlockValue, Formatting.None);
|
||||
}
|
||||
|
||||
private void UpdateBlockListRecursively(BlockEditorData blockListData, Func<Guid> createGuid)
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Notifications;
|
||||
@@ -41,11 +43,13 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
foreach (var cultureVal in propVals)
|
||||
{
|
||||
// Remove keys from published value & any nested properties
|
||||
var updatedPublishedVal = FormatPropertyValue(cultureVal.PublishedValue?.ToString(), onlyMissingKeys);
|
||||
var publishedValue = cultureVal.PublishedValue is JToken jsonPublishedValue ? jsonPublishedValue.ToString(Formatting.None) : cultureVal.PublishedValue?.ToString();
|
||||
var updatedPublishedVal = FormatPropertyValue(publishedValue, onlyMissingKeys).NullOrWhiteSpaceAsNull();
|
||||
cultureVal.PublishedValue = updatedPublishedVal;
|
||||
|
||||
// Remove keys from edited/draft value & any nested properties
|
||||
var updatedEditedVal = FormatPropertyValue(cultureVal.EditedValue?.ToString(), onlyMissingKeys);
|
||||
var editedValue = cultureVal.EditedValue is JToken jsonEditedValue ? jsonEditedValue.ToString(Formatting.None) : cultureVal.EditedValue?.ToString();
|
||||
var updatedEditedVal = FormatPropertyValue(editedValue, onlyMissingKeys).NullOrWhiteSpaceAsNull();
|
||||
cultureVal.EditedValue = updatedEditedVal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
}
|
||||
|
||||
// Convert back to raw JSON for persisting
|
||||
return JsonConvert.SerializeObject(grid);
|
||||
return JsonConvert.SerializeObject(grid, Formatting.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
var sourcePath = _mediaFileManager.FileSystem.GetRelativePath(src);
|
||||
var copyPath = _mediaFileManager.CopyFile(notification.Copy, property.PropertyType, sourcePath);
|
||||
jo["src"] = _mediaFileManager.FileSystem.GetUrl(copyPath);
|
||||
notification.Copy.SetValue(property.Alias, jo.ToString(), propertyValue.Culture, propertyValue.Segment);
|
||||
notification.Copy.SetValue(property.Alias, jo.ToString(Formatting.None), propertyValue.Culture, propertyValue.Segment);
|
||||
isUpdated = true;
|
||||
}
|
||||
}
|
||||
@@ -272,17 +272,11 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
// it can happen when an image is uploaded via the folder browser, in which case
|
||||
// the property value will be the file source eg '/media/23454/hello.jpg' and we
|
||||
// are fixing that anomaly here - does not make any sense at all but... bah...
|
||||
|
||||
var dt = _dataTypeService.GetDataType(property.PropertyType.DataTypeId);
|
||||
var config = dt?.ConfigurationAs<ImageCropperConfiguration>();
|
||||
src = svalue;
|
||||
var json = new
|
||||
property.SetValue(JsonConvert.SerializeObject(new
|
||||
{
|
||||
src = svalue,
|
||||
crops = config == null ? Array.Empty<ImageCropperConfiguration.Crop>() : config.Crops
|
||||
};
|
||||
|
||||
property.SetValue(JsonConvert.SerializeObject(json), pvalue.Culture, pvalue.Segment);
|
||||
src = svalue
|
||||
}, Formatting.None), pvalue.Culture, pvalue.Segment);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -205,6 +205,10 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
{
|
||||
src = val,
|
||||
crops = crops
|
||||
},new JsonSerializerSettings()
|
||||
{
|
||||
Formatting = Formatting.None,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.PropertyEditors
|
||||
@@ -53,23 +54,55 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
internal class MediaPicker3PropertyValueEditor : DataValueEditor, IDataValueReference
|
||||
{
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
|
||||
public MediaPicker3PropertyValueEditor(
|
||||
ILocalizedTextService localizedTextService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IIOHelper ioHelper,
|
||||
DataEditorAttribute attribute)
|
||||
DataEditorAttribute attribute,
|
||||
IDataTypeService dataTypeService)
|
||||
: base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute)
|
||||
{
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_dataTypeService = dataTypeService;
|
||||
}
|
||||
|
||||
public override object ToEditor(IProperty property, string culture = null, string segment = null)
|
||||
{
|
||||
var value = property.GetValue(culture, segment);
|
||||
|
||||
return Deserialize(_jsonSerializer, value);
|
||||
var dtos = Deserialize(_jsonSerializer, value).ToList();
|
||||
|
||||
var dataType = _dataTypeService.GetDataType(property.PropertyType.DataTypeId);
|
||||
if (dataType?.Configuration != null)
|
||||
{
|
||||
var configuration = dataType.ConfigurationAs<MediaPicker3Configuration>();
|
||||
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
dto.ApplyConfiguration(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public override object FromEditor(ContentPropertyData editorValue, object currentValue)
|
||||
{
|
||||
if (editorValue.Value is JArray dtos)
|
||||
{
|
||||
// Clean up redundant/default data
|
||||
foreach (var dto in dtos.Values<JObject>())
|
||||
{
|
||||
MediaWithCropsDto.Prune(dto);
|
||||
}
|
||||
|
||||
return dtos.ToString(Formatting.None);
|
||||
}
|
||||
|
||||
return base.FromEditor(editorValue, currentValue);
|
||||
}
|
||||
|
||||
///<remarks>
|
||||
@@ -142,6 +175,52 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
|
||||
[DataMember(Name = "focalPoint")]
|
||||
public ImageCropperValue.ImageCropperFocalPoint FocalPoint { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Applies the configuration to ensure only valid crops are kept and have the correct width/height.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration.</param>
|
||||
public void ApplyConfiguration(MediaPicker3Configuration configuration)
|
||||
{
|
||||
var crops = new List<ImageCropperValue.ImageCropperCrop>();
|
||||
|
||||
var configuredCrops = configuration?.Crops;
|
||||
if (configuredCrops != null)
|
||||
{
|
||||
foreach (var configuredCrop in configuredCrops)
|
||||
{
|
||||
var crop = Crops?.FirstOrDefault(x => x.Alias == configuredCrop.Alias);
|
||||
|
||||
crops.Add(new ImageCropperValue.ImageCropperCrop
|
||||
{
|
||||
Alias = configuredCrop.Alias,
|
||||
Width = configuredCrop.Width,
|
||||
Height = configuredCrop.Height,
|
||||
Coordinates = crop?.Coordinates
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Crops = crops;
|
||||
|
||||
if (configuration?.EnableLocalFocalPoint == false)
|
||||
{
|
||||
FocalPoint = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes redundant crop data/default focal point.
|
||||
/// </summary>
|
||||
/// <param name="value">The media with crops DTO.</param>
|
||||
/// <returns>
|
||||
/// The cleaned up value.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Because the DTO uses the same JSON keys as the image cropper value for crops and focal point, we can re-use the prune method.
|
||||
/// </remarks>
|
||||
public static void Prune(JObject value) => ImageCropperValue.Prune(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
|
||||
private static readonly JsonSerializerSettings LinkDisplayJsonSerializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.None,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
};
|
||||
|
||||
@@ -150,13 +151,17 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return string.Empty;
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var links = JsonConvert.DeserializeObject<List<LinkDisplay>>(value);
|
||||
if (links.Count == 0)
|
||||
return null;
|
||||
|
||||
return JsonConvert.SerializeObject(
|
||||
from link in JsonConvert.DeserializeObject<List<LinkDisplay>>(value)
|
||||
from link in links
|
||||
select new MultiUrlPickerValueEditor.LinkDto
|
||||
{
|
||||
Name = link.Name,
|
||||
@@ -164,8 +169,8 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
Target = link.Target,
|
||||
Udi = link.Udi,
|
||||
Url = link.Udi == null ? link.Url : null, // only save the URL for external links
|
||||
}, LinkDisplayJsonSerializerSettings
|
||||
);
|
||||
},
|
||||
LinkDisplayJsonSerializerSettings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
public override object FromEditor(ContentPropertyData editorValue, object currentValue)
|
||||
{
|
||||
var asArray = editorValue.Value as JArray;
|
||||
if (asArray == null)
|
||||
if (asArray == null || asArray.HasValues == false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -59,14 +59,19 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
public override object FromEditor(ContentPropertyData editorValue, object currentValue)
|
||||
{
|
||||
var json = editorValue.Value as JArray;
|
||||
if (json == null)
|
||||
if (json == null || json.HasValues == false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var values = json.Select(item => item.Value<string>()).ToArray();
|
||||
|
||||
return JsonConvert.SerializeObject(values);
|
||||
if (values.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(values, Formatting.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
var rows = _nestedContentValues.GetPropertyValues(propertyValue);
|
||||
|
||||
if (rows.Count == 0)
|
||||
return string.Empty;
|
||||
return null;
|
||||
|
||||
foreach (var row in rows.ToList())
|
||||
{
|
||||
@@ -136,7 +136,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
}
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(rows).ToXmlString<string>();
|
||||
return JsonConvert.SerializeObject(rows, Formatting.None).ToXmlString<string>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -231,7 +231,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
var rows = _nestedContentValues.GetPropertyValues(editorValue.Value);
|
||||
|
||||
if (rows.Count == 0)
|
||||
return string.Empty;
|
||||
return null;
|
||||
|
||||
foreach (var row in rows.ToList())
|
||||
{
|
||||
@@ -256,7 +256,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
}
|
||||
|
||||
// return json
|
||||
return JsonConvert.SerializeObject(rows);
|
||||
return JsonConvert.SerializeObject(rows, Formatting.None);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
@@ -32,7 +33,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
|
||||
UpdateNestedContentKeysRecursively(complexEditorValue, onlyMissingKeys, createGuid);
|
||||
|
||||
return complexEditorValue.ToString();
|
||||
return complexEditorValue.ToString(Formatting.None);
|
||||
}
|
||||
|
||||
private void UpdateNestedContentKeysRecursively(JToken json, bool onlyMissingKeys, Func<Guid> createGuid)
|
||||
@@ -65,7 +66,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
var parsed = JToken.Parse(propVal);
|
||||
UpdateNestedContentKeysRecursively(parsed, onlyMissingKeys, createGuid);
|
||||
// set the value to the updated one
|
||||
prop.Value = parsed.ToString();
|
||||
prop.Value = parsed.ToString(Formatting.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
var editorValueWithMediaUrlsRemoved = _imageSourceParser.RemoveImageSources(parseAndSavedTempImages);
|
||||
var parsed = MacroTagParser.FormatRichTextContentForPersistence(editorValueWithMediaUrlsRemoved);
|
||||
|
||||
return parsed;
|
||||
return parsed.NullOrWhiteSpaceAsNull();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
|
||||
if (editorValue.Value is JArray json)
|
||||
{
|
||||
return json.Select(x => x.Value<string>());
|
||||
return json.HasValues ? json.Select(x => x.Value<string>()) : null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value) == false)
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Cms.Core.Media;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Strings;
|
||||
@@ -122,13 +123,19 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool HasFocalPoint()
|
||||
=> FocalPoint != null && (FocalPoint.Left != 0.5m || FocalPoint.Top != 0.5m);
|
||||
=> FocalPoint is ImageCropperFocalPoint focalPoint && (focalPoint.Left != 0.5m || focalPoint.Top != 0.5m);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the value has crops.
|
||||
/// </summary>
|
||||
public bool HasCrops()
|
||||
=> Crops is IEnumerable<ImageCropperCrop> crops && crops.Any();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the value has a specified crop.
|
||||
/// </summary>
|
||||
public bool HasCrop(string alias)
|
||||
=> Crops != null && Crops.Any(x => x.Alias == alias);
|
||||
=> Crops is IEnumerable<ImageCropperCrop> crops && crops.Any(x => x.Alias == alias);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the value has a source image.
|
||||
@@ -167,6 +174,51 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes redundant crop data/default focal point.
|
||||
/// </summary>
|
||||
/// <param name="value">The image cropper value.</param>
|
||||
/// <returns>
|
||||
/// The cleaned up value.
|
||||
/// </returns>
|
||||
public static void Prune(JObject value)
|
||||
{
|
||||
if (value is null) throw new ArgumentNullException(nameof(value));
|
||||
|
||||
if (value.TryGetValue("crops", out var crops))
|
||||
{
|
||||
if (crops.HasValues)
|
||||
{
|
||||
foreach (var crop in crops.Values<JObject>().ToList())
|
||||
{
|
||||
if (crop.TryGetValue("coordinates", out var coordinates) == false || coordinates.HasValues == false)
|
||||
{
|
||||
// Remove crop without coordinates
|
||||
crop.Remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Width/height are already stored in the crop configuration
|
||||
crop.Remove("width");
|
||||
crop.Remove("height");
|
||||
}
|
||||
}
|
||||
|
||||
if (crops.HasValues == false)
|
||||
{
|
||||
// Remove empty crops
|
||||
value.Remove("crops");
|
||||
}
|
||||
}
|
||||
|
||||
if (value.TryGetValue("focalPoint", out var focalPoint) &&
|
||||
(focalPoint.HasValues == false || (focalPoint.Value<decimal>("top") == 0.5m && focalPoint.Value<decimal>("left") == 0.5m)))
|
||||
{
|
||||
// Remove empty/default focal point
|
||||
value.Remove("focalPoint");
|
||||
}
|
||||
}
|
||||
|
||||
#region IEquatable
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace Umbraco.Cms.Infrastructure.Serialization
|
||||
{
|
||||
JsonSerializerSettings.Converters.Add(new FuzzyBooleanConverter());
|
||||
JsonSerializerSettings.ContractResolver = new ConfigurationCustomContractResolver();
|
||||
JsonSerializerSettings.Formatting = Formatting.None;
|
||||
JsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
||||
}
|
||||
|
||||
private class ConfigurationCustomContractResolver : DefaultContractResolver
|
||||
|
||||
@@ -14,7 +14,8 @@ namespace Umbraco.Cms.Infrastructure.Serialization
|
||||
Converters = new List<JsonConverter>()
|
||||
{
|
||||
new StringEnumConverter()
|
||||
}
|
||||
},
|
||||
Formatting = Formatting.None
|
||||
};
|
||||
public string Serialize(object input)
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Cms.Infrastructure.Serialization
|
||||
}
|
||||
// Load JObject from stream
|
||||
JObject jObject = JObject.Load(reader);
|
||||
return jObject.ToString();
|
||||
return jObject.ToString(Formatting.None);
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
|
||||
@@ -678,7 +678,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
r = code
|
||||
});
|
||||
|
||||
// Construct full URL using configured application URL (which will fall back to request)
|
||||
// Construct full URL using configured application URL (which will fall back to current request)
|
||||
Uri applicationUri = _httpContextAccessor.GetRequiredHttpContext().Request.GetApplicationUri(_webRoutingSettings);
|
||||
var callbackUri = new Uri(applicationUri, action);
|
||||
return callbackUri.ToString();
|
||||
|
||||
@@ -282,7 +282,12 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
|
||||
|
||||
if (_emailSender.CanSendRequiredEmail())
|
||||
{
|
||||
AddActionNode<ActionNotify>(item, menu, true, opensDialog: true);
|
||||
menu.Items.Add(new MenuItem("notify", LocalizedTextService)
|
||||
{
|
||||
Icon = "megaphone",
|
||||
SeparatorBefore = true,
|
||||
OpensDialog = true
|
||||
});
|
||||
}
|
||||
|
||||
if((item is DocumentEntitySlim documentEntity && documentEntity.IsContainer) == false)
|
||||
|
||||
@@ -152,12 +152,12 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetUrlsByUdis",
|
||||
"GetUrlsByIds",
|
||||
query),
|
||||
{
|
||||
udis: udis
|
||||
ids: ids
|
||||
}),
|
||||
'Failed to retrieve url map for udis ' + udis);
|
||||
'Failed to retrieve url map for ids ' + ids);
|
||||
},
|
||||
|
||||
getUrlByUdi: function (udi, culture) {
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.HealthCheck.Checks.Config;
|
||||
|
||||
namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
{
|
||||
[HealthCheck(
|
||||
"6708CA45-E96E-40B8-A40A-0607C1CA7F28",
|
||||
"Application URL Configuration",
|
||||
Description = "Checks if the Umbraco application URL is configured for your site.",
|
||||
Group = "Security")]
|
||||
public class UmbracoApplicationUrlCheck : HealthCheck
|
||||
{
|
||||
private readonly ILocalizedTextService _textService;
|
||||
private readonly IRuntimeState _runtime;
|
||||
private readonly IUmbracoSettingsSection _settings;
|
||||
|
||||
private const string SetApplicationUrlAction = "setApplicationUrl";
|
||||
|
||||
public UmbracoApplicationUrlCheck(ILocalizedTextService textService, IRuntimeState runtime, IUmbracoSettingsSection settings)
|
||||
{
|
||||
_textService = textService;
|
||||
_runtime = runtime;
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the action and returns its status
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public override HealthCheckStatus ExecuteAction(HealthCheckAction action)
|
||||
{
|
||||
switch (action.Alias)
|
||||
{
|
||||
case SetApplicationUrlAction:
|
||||
return SetUmbracoApplicationUrl();
|
||||
default:
|
||||
throw new InvalidOperationException("UmbracoApplicationUrlCheck action requested is either not executable or does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<HealthCheckStatus> GetStatus()
|
||||
{
|
||||
//return the statuses
|
||||
return new[] { CheckUmbracoApplicationUrl() };
|
||||
}
|
||||
|
||||
private HealthCheckStatus CheckUmbracoApplicationUrl()
|
||||
{
|
||||
var url = _settings.WebRouting.UmbracoApplicationUrl;
|
||||
|
||||
string resultMessage;
|
||||
StatusResultType resultType;
|
||||
var actions = new List<HealthCheckAction>();
|
||||
|
||||
if (url.IsNullOrWhiteSpace())
|
||||
{
|
||||
resultMessage = _textService.Localize("healthcheck", "umbracoApplicationUrlCheckResultFalse");
|
||||
resultType = StatusResultType.Warning;
|
||||
|
||||
actions.Add(new HealthCheckAction(SetApplicationUrlAction, Id)
|
||||
{
|
||||
Name = _textService.Localize("healthcheck", "umbracoApplicationUrlConfigureButton"),
|
||||
Description = _textService.Localize("healthcheck", "umbracoApplicationUrlConfigureDescription")
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
resultMessage = _textService.Localize("healthcheck", "umbracoApplicationUrlCheckResultTrue", new[] { url });
|
||||
resultType = StatusResultType.Success;
|
||||
}
|
||||
|
||||
return new HealthCheckStatus(resultMessage)
|
||||
{
|
||||
ResultType = resultType,
|
||||
Actions = actions
|
||||
};
|
||||
}
|
||||
|
||||
private HealthCheckStatus SetUmbracoApplicationUrl()
|
||||
{
|
||||
var configFilePath = IOHelper.MapPath("~/config/umbracoSettings.config");
|
||||
const string xPath = "/settings/web.routing/@umbracoApplicationUrl";
|
||||
var configurationService = new ConfigurationService(configFilePath, xPath, _textService);
|
||||
var urlValue = _runtime.ApplicationUrl.ToString();
|
||||
var updateConfigFile = configurationService.UpdateConfigFile(urlValue);
|
||||
|
||||
if (updateConfigFile.Success)
|
||||
{
|
||||
return
|
||||
new HealthCheckStatus(_textService.Localize("healthcheck", "umbracoApplicationUrlConfigureSuccess", new[] { urlValue }))
|
||||
{
|
||||
ResultType = StatusResultType.Success
|
||||
};
|
||||
}
|
||||
|
||||
return
|
||||
new HealthCheckStatus(_textService.Localize("healthcheck", "umbracoApplicationUrlConfigureError", new[] { updateConfigFile.Result }))
|
||||
{
|
||||
ResultType = StatusResultType.Error
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
|
||||
@@ -11,6 +12,11 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
[TestFixture]
|
||||
public class NestedContentPropertyComponentTests
|
||||
{
|
||||
private static void AreEqualJson(string expected, string actual)
|
||||
{
|
||||
Assert.AreEqual(JToken.Parse(expected), JToken.Parse(actual));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Invalid_Json()
|
||||
{
|
||||
@@ -27,17 +33,17 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
Guid GuidFactory() => guids[guidCounter++];
|
||||
|
||||
var json = @"[
|
||||
{""key"":""04a6dba8-813c-4144-8aca-86a3f24ebf08"",""name"":""Item 1"",""ncContentTypeAlias"":""nested"",""text"":""woot""},
|
||||
{""key"":""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",""name"":""Item 2"",""ncContentTypeAlias"":""nested"",""text"":""zoot""}
|
||||
]";
|
||||
{""key"":""04a6dba8-813c-4144-8aca-86a3f24ebf08"",""name"":""Item 1"",""ncContentTypeAlias"":""nested"",""text"":""woot""},
|
||||
{""key"":""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",""name"":""Item 2"",""ncContentTypeAlias"":""nested"",""text"":""zoot""}
|
||||
]";
|
||||
var expected = json
|
||||
.Replace("04a6dba8-813c-4144-8aca-86a3f24ebf08", guids[0].ToString())
|
||||
.Replace("d8e214d8-c5a5-4b45-9b51-4050dd47f5fa", guids[1].ToString());
|
||||
|
||||
var component = new NestedContentPropertyHandler();
|
||||
var result = component.CreateNestedContentKeys(json, false, GuidFactory);
|
||||
var actual = component.CreateNestedContentKeys(json, false, GuidFactory);
|
||||
|
||||
Assert.AreEqual(JsonConvert.DeserializeObject(expected).ToString(), JsonConvert.DeserializeObject(result).ToString());
|
||||
AreEqualJson(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -48,29 +54,27 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
Guid GuidFactory() => guids[guidCounter++];
|
||||
|
||||
var json = @"[{
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"": [{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""fbde4288-8382-4e13-8933-ed9c160de050"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]
|
||||
}
|
||||
]";
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"": [{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""fbde4288-8382-4e13-8933-ed9c160de050"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}]
|
||||
}]";
|
||||
|
||||
var expected = json
|
||||
.Replace("04a6dba8-813c-4144-8aca-86a3f24ebf08", guids[0].ToString())
|
||||
@@ -79,9 +83,9 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
.Replace("fbde4288-8382-4e13-8933-ed9c160de050", guids[3].ToString());
|
||||
|
||||
var component = new NestedContentPropertyHandler();
|
||||
var result = component.CreateNestedContentKeys(json, false, GuidFactory);
|
||||
var actual = component.CreateNestedContentKeys(json, false, GuidFactory);
|
||||
|
||||
Assert.AreEqual(JsonConvert.DeserializeObject(expected).ToString(), JsonConvert.DeserializeObject(result).ToString());
|
||||
AreEqualJson(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -93,7 +97,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
|
||||
// we need to ensure the escaped json is consistent with how it will be re-escaped after parsing
|
||||
// and this is how to do that, the result will also include quotes around it.
|
||||
var subJsonEscaped = JsonConvert.ToString(JsonConvert.DeserializeObject(@"[{
|
||||
var subJsonEscaped = JsonConvert.ToString(JToken.Parse(@"
|
||||
[{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
@@ -104,21 +109,21 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]").ToString());
|
||||
]").ToString(Formatting.None));
|
||||
|
||||
var json = @"[{
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + subJsonEscaped + @"
|
||||
}
|
||||
]";
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + subJsonEscaped + @"
|
||||
}
|
||||
]";
|
||||
|
||||
var expected = json
|
||||
.Replace("04a6dba8-813c-4144-8aca-86a3f24ebf08", guids[0].ToString())
|
||||
@@ -127,9 +132,9 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
.Replace("fbde4288-8382-4e13-8933-ed9c160de050", guids[3].ToString());
|
||||
|
||||
var component = new NestedContentPropertyHandler();
|
||||
var result = component.CreateNestedContentKeys(json, false, GuidFactory);
|
||||
var actual = component.CreateNestedContentKeys(json, false, GuidFactory);
|
||||
|
||||
Assert.AreEqual(JsonConvert.DeserializeObject(expected).ToString(), JsonConvert.DeserializeObject(result).ToString());
|
||||
AreEqualJson(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -141,7 +146,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
|
||||
// we need to ensure the escaped json is consistent with how it will be re-escaped after parsing
|
||||
// and this is how to do that, the result will also include quotes around it.
|
||||
var subJsonEscaped = JsonConvert.ToString(JsonConvert.DeserializeObject(@"[{
|
||||
var subJsonEscaped = JsonConvert.ToString(JToken.Parse(@"[{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
@@ -152,7 +157,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]").ToString());
|
||||
]").ToString(Formatting.None));
|
||||
|
||||
// Complex editor such as the grid
|
||||
var complexEditorJsonEscaped = @"{
|
||||
@@ -231,9 +236,9 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
.Replace("fbde4288-8382-4e13-8933-ed9c160de050", guids[3].ToString());
|
||||
|
||||
var component = new NestedContentPropertyHandler();
|
||||
var result = component.CreateNestedContentKeys(json, false, GuidFactory);
|
||||
var actual = component.CreateNestedContentKeys(json, false, GuidFactory);
|
||||
|
||||
Assert.AreEqual(JsonConvert.DeserializeObject(expected).ToString(), JsonConvert.DeserializeObject(result).ToString());
|
||||
AreEqualJson(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -252,10 +257,10 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
var result = component.CreateNestedContentKeys(json, true, GuidFactory);
|
||||
|
||||
// Ensure the new GUID is put in a key into the JSON
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[0].ToString()));
|
||||
|
||||
// Ensure that the original key is NOT changed/modified & still exists
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains("04a6dba8-813c-4144-8aca-86a3f24ebf08"));
|
||||
Assert.IsTrue(result.Contains("04a6dba8-813c-4144-8aca-86a3f24ebf08"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -267,7 +272,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
|
||||
// we need to ensure the escaped json is consistent with how it will be re-escaped after parsing
|
||||
// and this is how to do that, the result will also include quotes around it.
|
||||
var subJsonEscaped = JsonConvert.ToString(JsonConvert.DeserializeObject(@"[{
|
||||
var subJsonEscaped = JsonConvert.ToString(JToken.Parse(@"[{
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
@@ -276,7 +281,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]").ToString());
|
||||
]").ToString(Formatting.None));
|
||||
|
||||
var json = @"[{
|
||||
""name"": ""Item 1 was copied and has no key"",
|
||||
@@ -295,9 +300,9 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
var result = component.CreateNestedContentKeys(json, true, GuidFactory);
|
||||
|
||||
// Ensure the new GUID is put in a key into the JSON for each item
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[1].ToString()));
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[2].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[1].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[2].ToString()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -309,7 +314,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
|
||||
// we need to ensure the escaped json is consistent with how it will be re-escaped after parsing
|
||||
// and this is how to do that, the result will also include quotes around it.
|
||||
var subJsonEscaped = JsonConvert.ToString(JsonConvert.DeserializeObject(@"[{
|
||||
var subJsonEscaped = JsonConvert.ToString(JToken.Parse(@"[{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
@@ -319,7 +324,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]").ToString());
|
||||
]").ToString(Formatting.None));
|
||||
|
||||
// Complex editor such as the grid
|
||||
var complexEditorJsonEscaped = @"{
|
||||
@@ -394,8 +399,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors
|
||||
var result = component.CreateNestedContentKeys(json, true, GuidFactory);
|
||||
|
||||
// Ensure the new GUID is put in a key into the JSON for each item
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[1].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[1].ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common
|
||||
{
|
||||
private const string CropperJson1 = "{\"focalPoint\": {\"left\": 0.96,\"top\": 0.80827067669172936},\"src\": \"/media/1005/img_0671.jpg\",\"crops\": [{\"alias\":\"thumb\",\"width\": 100,\"height\": 100,\"coordinates\": {\"x1\": 0.58729977382575338,\"y1\": 0.055768992440203169,\"x2\": 0,\"y2\": 0.32457553600198386}}]}";
|
||||
private const string CropperJson2 = "{\"focalPoint\": {\"left\": 0.98,\"top\": 0.80827067669172936},\"src\": \"/media/1005/img_0672.jpg\",\"crops\": [{\"alias\":\"thumb\",\"width\": 100,\"height\": 100,\"coordinates\": {\"x1\": 0.58729977382575338,\"y1\": 0.055768992440203169,\"x2\": 0,\"y2\": 0.32457553600198386}}]}";
|
||||
private const string CropperJson3 = "{\"focalPoint\": {\"left\": 0.98,\"top\": 0.80827067669172936},\"src\": \"/media/1005/img_0672.jpg\",\"crops\": []}";
|
||||
private const string CropperJson3 = "{\"focalPoint\": {\"left\": 0.5,\"top\": 0.5},\"src\": \"/media/1005/img_0672.jpg\",\"crops\": []}";
|
||||
private const string MediaPath = "/media/1005/img_0671.jpg";
|
||||
|
||||
[Test]
|
||||
public void CanConvertImageCropperDataSetSrcToString()
|
||||
{
|
||||
// cropperJson3 - has not crops
|
||||
// cropperJson3 - has no crops
|
||||
ImageCropperValue cropperValue = CropperJson3.DeserializeImageCropperValue();
|
||||
Attempt<string> serialized = cropperValue.TryConvertTo<string>();
|
||||
Assert.IsTrue(serialized.Success);
|
||||
@@ -38,7 +38,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common
|
||||
[Test]
|
||||
public void CanConvertImageCropperDataSetJObject()
|
||||
{
|
||||
// cropperJson3 - has not crops
|
||||
// cropperJson3 - has no crops
|
||||
ImageCropperValue cropperValue = CropperJson3.DeserializeImageCropperValue();
|
||||
Attempt<JObject> serialized = cropperValue.TryConvertTo<JObject>();
|
||||
Assert.IsTrue(serialized.Success);
|
||||
|
||||
Reference in New Issue
Block a user