Merge remote-tracking branch 'origin/v8/dev' into v9/feature/merge_v8_14-12-2021

# Conflicts:
#	src/Umbraco.Core/Constants-Conventions.cs
#	src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs
#	src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs
#	src/Umbraco.Core/Models/IContentType.cs
#	src/Umbraco.Core/Packaging/PackageDataInstallation.cs
#	src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs
#	src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepository.cs
#	src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs
#	src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs
#	src/Umbraco.Core/Services/Implement/MemberService.cs
#	src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs
#	src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs
#	src/Umbraco.Tests/Services/Importing/ImportResources.Designer.cs
#	src/Umbraco.Tests/Services/Importing/ImportResources.resx
#	src/Umbraco.Tests/Umbraco.Tests.csproj
#	src/Umbraco.Web.UI.Client/src/common/directives/components/localization/localize.directive.js
#	src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js
#	src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js
#	src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html
#	src/Umbraco.Web.UI.Client/src/views/member/apps/content/content.html
#	src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml
#	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/Umbraco/config/lang/fr.xml
#	src/Umbraco.Web.UI/Umbraco/config/lang/nl.xml
#	src/Umbraco.Web.UI/Umbraco/config/lang/zh.xml
#	src/Umbraco.Web.UI/config/BackOfficeTours/getting-started.json
#	src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs
#	src/Umbraco.Web/Models/ContentEditing/MemberDisplay.cs
#	src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs
#	src/Umbraco.Web/Models/Mapping/MemberMapDefinition.cs
#	src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesMapper.cs
#	src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs
#	src/Umbraco.Web/PropertyEditors/BlockEditorPropertyEditor.cs
#	src/Umbraco.Web/Runtime/WebInitialComposer.cs
#	src/Umbraco.Web/Trees/ContentTreeController.cs
#	src/Umbraco.Web/Umbraco.Web.csproj
#	tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/Services/Importing/SingleDocType-WithCleanupPolicy.xml
This commit is contained in:
Bjarke Berg
2021-12-14 20:13:42 +01:00
81 changed files with 1064 additions and 857 deletions

View File

@@ -37,5 +37,9 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
[DataMember(Name = "apps")]
public IEnumerable<ContentApp> ContentApps { get; set; }
[DataMember(Name = "membershipProperties")]
public IEnumerable<ContentPropertyDisplay> MembershipProperties { get; set; }
}
}

View File

@@ -75,84 +75,14 @@ namespace Umbraco.Cms.Core.Models.Mapping
isLockedOutProperty.Value = _localizedTextService.Localize("general", "no");
}
if (_backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null
&& _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)))
{
var memberTypeLink = $"#/member/memberTypes/edit/{source.ContentTypeId}";
// Replace the doctype property
var docTypeProperty = resolved.SelectMany(x => x.Properties)
.First(x => x.Alias == $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}doctype");
docTypeProperty.Value = new List<object>
{
new
{
linkText = source.ContentType.Name,
url = memberTypeLink,
target = "_self",
icon = Constants.Icons.ContentType
}
};
docTypeProperty.View = "urllist";
}
return resolved;
}
[Obsolete("Use MapMembershipProperties. Will be removed in Umbraco 10.")]
protected override IEnumerable<ContentPropertyDisplay> GetCustomGenericProperties(IContentBase content)
{
var member = (IMember)content;
var genericProperties = new List<ContentPropertyDisplay>
{
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}id",
Label = _localizedTextService.Localize("general","id"),
Value = new List<string> {member.Id.ToString(), member.Key.ToString()},
View = "idwithguid"
},
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}doctype",
Label = _localizedTextService.Localize("content","membertype"),
Value = _localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, member.ContentType.Name),
View = _propertyEditorCollection[Constants.PropertyEditors.Aliases.Label].GetValueEditor().View
},
GetLoginProperty(member, _localizedTextService),
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}email",
Label = _localizedTextService.Localize("general","email"),
Value = member.Email,
View = "email",
Validation = {Mandatory = true}
},
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}password",
Label = _localizedTextService.Localize(null,"password"),
Value = new Dictionary<string, object>
{
// TODO: why ignoreCase, what are we doing here?!
{"newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null)},
},
// TODO: Hard coding this because the changepassword doesn't necessarily need to be a resolvable (real) property editor
View = "changepassword",
// initialize the dictionary with the configuration from the default membership provider
Config = GetPasswordConfig(member)
},
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}membergroup",
Label = _localizedTextService.Localize("content","membergroup"),
Value = GetMemberGroupValue(member.Username),
View = "membergroups",
Config = new Dictionary<string, object> {{"IsRequired", true}}
}
};
return genericProperties;
return MapMembershipProperties(member, null);
}
private Dictionary<string, object> GetPasswordConfig(IMember member)
@@ -256,5 +186,59 @@ namespace Umbraco.Cms.Core.Models.Mapping
return result;
}
public IEnumerable<ContentPropertyDisplay> MapMembershipProperties(IMember member, MapperContext context)
{
var properties = new List<ContentPropertyDisplay>
{
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}id",
Label = _localizedTextService.Localize("general","id"),
Value = new List<string> {member.Id.ToString(), member.Key.ToString()},
View = "idwithguid"
},
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}doctype",
Label = _localizedTextService.Localize("content","membertype"),
Value = _localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, member.ContentType.Name),
View = _propertyEditorCollection[Constants.PropertyEditors.Aliases.Label].GetValueEditor().View
},
GetLoginProperty(member, _localizedTextService),
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}email",
Label = _localizedTextService.Localize("general","email"),
Value = member.Email,
View = "email",
Validation = {Mandatory = true}
},
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}password",
Label = _localizedTextService.Localize(null,"password"),
Value = new Dictionary<string, object>
{
// TODO: why ignoreCase, what are we doing here?!
{"newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null)},
},
// TODO: Hard coding this because the changepassword doesn't necessarily need to be a resolvable (real) property editor
View = "changepassword",
// Initialize the dictionary with the configuration from the default membership provider
Config = GetPasswordConfig(member)
},
new ContentPropertyDisplay
{
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}membergroup",
Label = _localizedTextService.Localize("content","membergroup"),
Value = GetMemberGroupValue(member.Username),
View = "membergroups",
Config = new Dictionary<string, object> {{"IsRequired", true}}
}
};
return properties;
}
}
}

View File

@@ -52,47 +52,25 @@ namespace Umbraco.Cms.Core.Models.Mapping
var noGroupProperties = content.GetNonGroupedProperties()
.Where(x => IgnoreProperties.Contains(x.Alias) == false) // skip ignored
.ToList();
var genericproperties = MapProperties(content, noGroupProperties, context);
var genericProperties = MapProperties(content, noGroupProperties, context);
tabs.Add(new Tab<ContentPropertyDisplay>
{
Id = 0,
Label = LocalizedTextService.Localize("general", "properties"),
Alias = "Generic properties",
Properties = genericproperties,
Type = PropertyGroupType.Group.ToString()
});
var genericProps = tabs.Single(x => x.Id == 0);
//store the current props to append to the newly inserted ones
var currProps = genericProps.Properties.ToArray();
var contentProps = new List<ContentPropertyDisplay>();
var customProperties = GetCustomGenericProperties(content);
if (customProperties != null)
{
//add the custom ones
contentProps.AddRange(customProperties);
genericProperties.AddRange(customProperties);
}
//now add the user props
contentProps.AddRange(currProps);
//re-assign
genericProps.Properties = contentProps;
//Show or hide properties tab based on whether it has or not any properties
if (genericProps.Properties.Any() == false)
if (genericProperties.Count > 0)
{
//loop through the tabs, remove the one with the id of zero and exit the loop
for (var i = 0; i < tabs.Count; i++)
tabs.Add(new Tab<ContentPropertyDisplay>
{
if (tabs[i].Id != 0) continue;
tabs.RemoveAt(i);
break;
}
Id = 0,
Label = LocalizedTextService.Localize("general", "properties"),
Alias = "Generic properties",
Properties = genericProperties
});
}
}