Merge branch 'v8/dev' into v8/contrib

This commit is contained in:
Sebastiaan Janssen
2021-08-20 16:54:50 +02:00
12 changed files with 184 additions and 73 deletions

View File

@@ -26,8 +26,8 @@
not want this to happen as the alpha of the next major is, really, the next major already. not want this to happen as the alpha of the next major is, really, the next major already.
--> -->
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.4.0, 2.999999)" /> <dependency id="Microsoft.AspNet.SignalR.Core" version="[2.4.0, 2.999999)" />
<dependency id="ImageProcessor.Web" version="[4.12.1.100,4.999999)" /> <dependency id="ImageProcessor.Web" version="[4.12.1,4.999999)" />
<dependency id="ImageProcessor.Web.Config" version="[2.6.0.100,2.999999)" /> <dependency id="ImageProcessor.Web.Config" version="[2.6.0,2.999999)" />
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.1,2.999999)" /> <dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.1,2.999999)" />
</group> </group>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<runtime xdt:Transform="InsertIfMissing" />
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" xdt:Transform="InsertIfMissing" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Collections.Immutable')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Buffers')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Memory')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Numerics.Vectors')" xdt:Transform="Remove" />
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.5.0" newVersion="1.2.5.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" />
<bindingRedirect oldVersion="4.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" />
<bindingRedirect oldVersion="4.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" />
<bindingRedirect oldVersion="4.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -91,6 +91,7 @@
{ {
$src = "$($this.SolutionRoot)\src" $src = "$($this.SolutionRoot)\src"
$log = "$($this.BuildTemp)\belle.log" $log = "$($this.BuildTemp)\belle.log"
Write-Host "Compile Belle" Write-Host "Compile Belle"
Write-Host "Logging to $log" Write-Host "Logging to $log"
@@ -352,6 +353,14 @@
"-x!dotless.Core.*" "-x!Content_Types.xml" "-x!*.pdb" ` "-x!dotless.Core.*" "-x!Content_Types.xml" "-x!*.pdb" `
> $null > $null
if (-not $?) { throw "Failed to zip UmbracoCms." } if (-not $?) { throw "Failed to zip UmbracoCms." }
Write-Host "Zip cms cloud"
$this.CopyFile("$($this.SolutionRoot)\build\NuSpecs\tools\Web.config.cloud.xdt", "$tmp\WebApp\Web.config.install.xdt")
&$this.BuildEnv.Zip a -r "$out\UmbracoCms.$($this.Version.Semver).Cloud.zip" `
"$tmp\WebApp\*" `
"-x!dotless.Core.*" "-x!Content_Types.xml" "-x!*.pdb" `
> $null
if (-not $?) { throw "Failed to zip UmbracoCms." }
}) })
$ubuild.DefineMethod("PrepareBuild", $ubuild.DefineMethod("PrepareBuild",
@@ -553,7 +562,6 @@
# run # run
if (-not $get) if (-not $get)
{ {
cd
if ($command.Length -eq 0) if ($command.Length -eq 0)
{ {
$command = @( "Build" ) $command = @( "Build" )

View File

@@ -18,5 +18,5 @@ using System.Resources;
[assembly: AssemblyVersion("8.0.0")] [assembly: AssemblyVersion("8.0.0")]
// these are FYI and changed automatically // these are FYI and changed automatically
[assembly: AssemblyFileVersion("8.15.1")] [assembly: AssemblyFileVersion("8.16.0")]
[assembly: AssemblyInformationalVersion("8.15.1")] [assembly: AssemblyInformationalVersion("8.16.0-rc")]

View File

@@ -642,6 +642,24 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
return $q.when(umbDataFormatter.formatContentGetData(result)); return $q.when(umbDataFormatter.formatContentGetData(result));
}); });
}, },
getScaffolds: function(parentId, aliases){
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetEmptyByAliases"),
{ parentId: parentId, contentTypeAliases: aliases }
),
'Failed to retrieve data for empty content item aliases ' + aliases.join(", ")
).then(function(result) {
Object.keys(result).map(function(key){
result[key] = umbDataFormatter.formatContentGetData(result[key]);
});
return $q.when(result);
});
},
/** /**
* @ngdoc method * @ngdoc method
* @name umbraco.resources.contentResource#getScaffoldByKey * @name umbraco.resources.contentResource#getScaffoldByKey

View File

@@ -522,10 +522,14 @@
]; ];
// Initialize // Initialize
var scaffoldsLoaded = 0;
vm.scaffolds = []; vm.scaffolds = [];
_.each(model.config.contentTypes, function (contentType) {
contentResource.getScaffold(-20, contentType.ncAlias).then(function (scaffold) { contentResource.getScaffolds(-20, contentTypeAliases).then(function (scaffolds){
// Loop through all the content types
_.each(model.config.contentTypes, function (contentType){
// Get the scaffold from the result
var scaffold = scaffolds[contentType.ncAlias];
// make sure it's an element type before allowing the user to create new ones // make sure it's an element type before allowing the user to create new ones
if (scaffold.isElement) { if (scaffold.isElement) {
// remove all tabs except the specified tab // remove all tabs except the specified tab
@@ -554,13 +558,10 @@
// Store the scaffold object // Store the scaffold object
vm.scaffolds.push(scaffold); vm.scaffolds.push(scaffold);
} }
scaffoldsLoaded++;
initIfAllScaffoldsHaveLoaded();
}, function (error) {
scaffoldsLoaded++;
initIfAllScaffoldsHaveLoaded();
}); });
// Initialize once all scaffolds have been loaded
initNestedContent();
}); });
/** /**
@@ -586,57 +587,50 @@
}); });
} }
var initIfAllScaffoldsHaveLoaded = function () { var initNestedContent = function () {
// Initialize when all scaffolds have loaded // Initialize when all scaffolds have loaded
if (model.config.contentTypes.length === scaffoldsLoaded) { // Sort the scaffold explicitly according to the sort order defined by the data type.
// Because we're loading the scaffolds async one at a time, we need to vm.scaffolds = $filter("orderBy")(vm.scaffolds, function (s) {
// sort them explicitly according to the sort order defined by the data type. return contentTypeAliases.indexOf(s.contentTypeAlias);
contentTypeAliases = []; });
_.each(model.config.contentTypes, function (contentType) {
contentTypeAliases.push(contentType.ncAlias);
});
vm.scaffolds = $filter("orderBy")(vm.scaffolds, function (s) {
return contentTypeAliases.indexOf(s.contentTypeAlias);
});
// Convert stored nodes // Convert stored nodes
if (model.value) { if (model.value) {
for (var i = 0; i < model.value.length; i++) { for (var i = 0; i < model.value.length; i++) {
var item = model.value[i]; var item = model.value[i];
var scaffold = getScaffold(item.ncContentTypeAlias); var scaffold = getScaffold(item.ncContentTypeAlias);
if (scaffold == null) { if (scaffold == null) {
// No such scaffold - the content type might have been deleted. We need to skip it. // No such scaffold - the content type might have been deleted. We need to skip it.
continue; continue;
}
createNode(scaffold, item);
} }
createNode(scaffold, item);
} }
// Enforce min items if we only have one scaffold type
var modelWasChanged = false;
if (vm.nodes.length < vm.minItems && vm.scaffolds.length === 1) {
for (var i = vm.nodes.length; i < model.config.minItems; i++) {
addNode(vm.scaffolds[0].contentTypeAlias);
}
modelWasChanged = true;
}
// If there is only one item, set it as current node
if (vm.singleMode || (vm.nodes.length === 1 && vm.maxItems === 1)) {
setCurrentNode(vm.nodes[0], false);
}
validate();
vm.inited = true;
if (modelWasChanged) {
updateModel();
}
updatePropertyActionStates();
checkAbilityToPasteContent();
} }
// Enforce min items if we only have one scaffold type
var modelWasChanged = false;
if (vm.nodes.length < vm.minItems && vm.scaffolds.length === 1) {
for (var i = vm.nodes.length; i < model.config.minItems; i++) {
addNode(vm.scaffolds[0].contentTypeAlias);
}
modelWasChanged = true;
}
// If there is only one item, set it as current node
if (vm.singleMode || (vm.nodes.length === 1 && vm.maxItems === 1)) {
setCurrentNode(vm.nodes[0], false);
}
validate();
vm.inited = true;
if (modelWasChanged) {
updateModel();
}
updatePropertyActionStates();
checkAbilityToPasteContent();
} }
function extendPropertyWithNCData(prop) { function extendPropertyWithNCData(prop) {

View File

@@ -348,9 +348,9 @@
<WebProjectProperties> <WebProjectProperties>
<UseIIS>False</UseIIS> <UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort> <AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>8151</DevelopmentServerPort> <DevelopmentServerPort>8160</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath> <DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:8151</IISUrl> <IISUrl>http://localhost:8160</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication> <NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer> <UseCustomServer>False</UseCustomServer>
<CustomServerUrl> <CustomServerUrl>

View File

@@ -272,9 +272,9 @@
"view": "nodename" "view": "nodename"
}, },
{ {
"element": "[data-element='editor-content'] [data-element='property-welcomeText']", "element": "[data-element='editor-content'] [data-element='property-welcomeText'] > div",
"title": "Add a welcome text", "title": "Add a welcome text",
"content": "<p>Add content to the <b>Welcome Text</b> field.</p><p>If you don't have any ideas here is a start:<br/> <pre>I am learning Umbraco. High Five I Rock #H5IR</pre>.</p>" "content": "<p>Add content to the <b>Welcome Text</b> field.</p><p>If you don't have any ideas here is a start:<br/> <pre>I am learning Umbraco. High Five I Rock #H5IR</pre></p>"
}, },
{ {
"element": "[data-element='editor-content'] [data-element='button-saveAndPublish']", "element": "[data-element='editor-content'] [data-element='button-saveAndPublish']",

View File

@@ -364,6 +364,24 @@ namespace Umbraco.Web.Editors
return GetEmpty(contentType, parentId); return GetEmpty(contentType, parentId);
} }
/// <summary>
/// Gets a dictionary containing empty content items for every alias specified in the contentTypeAliases array in the body of the request.
/// </summary>
/// <remarks>
/// This is a post request in order to support a large amount of aliases without hitting the URL length limit.
/// </remarks>
/// <param name="contentTypesByAliases"></param>
/// <returns></returns>
[OutgoingEditorModelEvent]
[HttpPost]
public IDictionary<string, ContentItemDisplay> GetEmptyByAliases(ContentTypesByAliases contentTypesByAliases)
{
// It's important to do this operation within a scope to reduce the amount of readlock queries.
using var scope = _scopeProvider.CreateScope(autoComplete: true);
var contentTypes = contentTypesByAliases.ContentTypeAliases.Select(alias => Services.ContentTypeService.Get(alias));
return GetEmpties(contentTypes, contentTypesByAliases.ParentId).ToDictionary(x => x.ContentTypeAlias);
}
/// <summary> /// <summary>
/// Gets an empty content item for the document type. /// Gets an empty content item for the document type.

View File

@@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// A model for retrieving multiple content types based on their aliases.
/// </summary>
[DataContract(Name = "contentTypes", Namespace = "")]
public class ContentTypesByAliases
{
/// <summary>
/// Id of the parent of the content type.
/// </summary>
[DataMember(Name = "parentId")]
[Required]
public int ParentId { get; set; }
/// <summary>
/// The alias of every content type to get.
/// </summary>
[DataMember(Name = "contentTypeAliases")]
[Required]
public string[] ContentTypeAliases { get; set; }
}
}

View File

@@ -253,6 +253,7 @@
<Compile Include="Media\UploadAutoFillProperties.cs" /> <Compile Include="Media\UploadAutoFillProperties.cs" />
<Compile Include="Migrations\PostMigrations\PublishedSnapshotRebuilder.cs" /> <Compile Include="Migrations\PostMigrations\PublishedSnapshotRebuilder.cs" />
<Compile Include="Models\AnchorsModel.cs" /> <Compile Include="Models\AnchorsModel.cs" />
<Compile Include="Models\ContentEditing\ContentTypesByAliases.cs" />
<Compile Include="Models\ContentEditing\ContentTypesByKeys.cs" /> <Compile Include="Models\ContentEditing\ContentTypesByKeys.cs" />
<Compile Include="Models\ContentEditing\DataTypeReferences.cs" /> <Compile Include="Models\ContentEditing\DataTypeReferences.cs" />
<Compile Include="Models\ContentEditing\LinkDisplay.cs" /> <Compile Include="Models\ContentEditing\LinkDisplay.cs" />

View File

@@ -1,10 +1,8 @@
using System; using System.Collections;
using System.Net.Http; using System.Net.Http;
using System.Web.Http.Filters; using System.Web.Http.Filters;
using Umbraco.Core;
using Umbraco.Web.Composing; using Umbraco.Web.Composing;
using Umbraco.Web.Editors; using Umbraco.Web.Editors;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.WebApi.Filters namespace Umbraco.Web.WebApi.Filters
{ {
@@ -23,18 +21,37 @@ namespace Umbraco.Web.WebApi.Filters
if (actionExecutedContext.Response.Content is ObjectContent objectContent) if (actionExecutedContext.Response.Content is ObjectContent objectContent)
{ {
var model = objectContent.Value; var model = objectContent.Value;
if (model != null) if (model != null)
{ {
var args = new EditorModelEventArgs( if (model is IDictionary modelDict)
model, {
Current.UmbracoContext); foreach (var entity in modelDict)
EditorModelEventManager.EmitEvent(actionExecutedContext, args); {
objectContent.Value = args.Model; if (entity is DictionaryEntry entry)
{
var args = CreateArgs(entry.Value);
EditorModelEventManager.EmitEvent(actionExecutedContext, args);
entry.Value = args.Model;
}
}
}
else
{
var args = CreateArgs(model);
EditorModelEventManager.EmitEvent(actionExecutedContext, args);
objectContent.Value = args.Model;
}
} }
} }
base.OnActionExecuted(actionExecutedContext); base.OnActionExecuted(actionExecutedContext);
} }
private EditorModelEventArgs CreateArgs(object model)
{
return new EditorModelEventArgs(
model,
Current.UmbracoContext);
}
} }
} }