* Add missing list view usages to data type references (#14485) * Added default implementation #14617
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.Serialization;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.ContentEditing;
|
||||
|
||||
@@ -20,6 +21,9 @@ public class DataTypeReferences
|
||||
[DataMember(Name = "properties")]
|
||||
public object? Properties { get; set; }
|
||||
|
||||
[DataMember(Name = "listViews")]
|
||||
public object? ListViews { get; set; }
|
||||
|
||||
[DataContract(Name = "property", Namespace = "")]
|
||||
public class PropertyTypeReferences
|
||||
{
|
||||
@@ -29,5 +33,12 @@ public class DataTypeReferences
|
||||
[DataMember(Name = "alias")]
|
||||
public string? Alias { get; set; }
|
||||
}
|
||||
|
||||
[DataContract(Name = "listView", Namespace = "")]
|
||||
public class ListViewReferences
|
||||
{
|
||||
[DataMember(Name = "name")]
|
||||
public string? Name { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,4 +14,13 @@ public interface IDataTypeRepository : IReadWriteQueryRepository<int, IDataType>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
IReadOnlyDictionary<Udi, IEnumerable<string>> FindUsages(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a dictionary of content type <see cref="Udi" />s and the data type (List view) aliases that use a
|
||||
/// <see cref="IDataType" />
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
IReadOnlyDictionary<Udi, IEnumerable<string>> FindListViewUsages(int id) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -612,6 +612,12 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
return _dataTypeRepository.FindUsages(id);
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<Udi, IEnumerable<string>> GetListViewReferences(int id)
|
||||
{
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
|
||||
return _dataTypeRepository.FindListViewUsages(id);
|
||||
}
|
||||
|
||||
private void Audit(AuditType type, int userId, int objectId)
|
||||
{
|
||||
_auditRepository.Save(new AuditItem(objectId, type, userId, ObjectTypes.GetName(UmbracoObjectTypes.DataType)));
|
||||
|
||||
@@ -14,6 +14,7 @@ public interface IDataTypeService : IService
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
IReadOnlyDictionary<Udi, IEnumerable<string>> GetReferences(int id);
|
||||
IReadOnlyDictionary<Udi, IEnumerable<string>> GetListViewReferences(int id) => throw new NotImplementedException();
|
||||
|
||||
Attempt<OperationResult<OperationResultType, EntityContainer>?> CreateContainer(int parentId, Guid key, string name, int userId = Constants.Security.SuperUserId);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core;
|
||||
@@ -10,6 +11,7 @@ using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
@@ -17,6 +19,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Factories;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Querying;
|
||||
using Umbraco.Cms.Infrastructure.Scoping;
|
||||
using Umbraco.Extensions;
|
||||
using static Umbraco.Cms.Core.Constants.SqlTemplates;
|
||||
using static Umbraco.Cms.Core.Persistence.SqlExtensionsStatics;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
||||
@@ -124,6 +127,84 @@ internal class DataTypeRepository : EntityRepositoryBase<int, IDataType>, IDataT
|
||||
x => (IEnumerable<string>)x.PropertyTypes.Select(p => p.Alias).ToList());
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<Udi, IEnumerable<string>> FindListViewUsages(int id)
|
||||
{
|
||||
var usages = new Dictionary<Udi, IEnumerable<string>>();
|
||||
|
||||
if (id == default)
|
||||
{
|
||||
return usages;
|
||||
}
|
||||
|
||||
IDataType? dataType = Get(id);
|
||||
|
||||
if (dataType != null && dataType.EditorAlias.Equals(Constants.PropertyEditors.Aliases.ListView))
|
||||
{
|
||||
// Get All contentTypes where isContainer (list view enabled) is set to true
|
||||
Sql<ISqlContext> sql = Sql()
|
||||
.Select<ContentTypeDto>(ct => ct.Select(node => node.NodeDto))
|
||||
.From<ContentTypeDto>()
|
||||
.InnerJoin<NodeDto>().On<NodeDto, ContentTypeDto>(n => n.NodeId, ct => ct.NodeId)
|
||||
.Where<ContentTypeDto>(ct => ct.IsContainer == true);
|
||||
|
||||
List<ContentTypeDto> ctds = Database.Fetch<ContentTypeDto>(sql);
|
||||
|
||||
// If there are not any ContentTypes with a ListView return.
|
||||
if (!ctds.Any())
|
||||
{
|
||||
return usages;
|
||||
}
|
||||
|
||||
// First check if it is a custom list view
|
||||
ContentTypeDto? customListView = ctds.Where(x => (Constants.Conventions.DataTypes.ListViewPrefix + x.Alias).Equals(dataType.Name)).FirstOrDefault();
|
||||
|
||||
if (customListView != null)
|
||||
{
|
||||
// Add usages as customListView
|
||||
usages.Add(
|
||||
new GuidUdi(ObjectTypes.GetUdiType(customListView.NodeDto.NodeObjectType!.Value), customListView.NodeDto.UniqueId),
|
||||
new List<string> { dataType.Name! });
|
||||
}
|
||||
else
|
||||
{
|
||||
// It is not a custom ListView, so check the default ones.
|
||||
foreach (ContentTypeDto contentWithListView in ctds)
|
||||
{
|
||||
var customListViewName = Constants.Conventions.DataTypes.ListViewPrefix + contentWithListView.Alias;
|
||||
IDataType? clv = Get(Query<IDataType>().Where(x => x.Name == customListViewName))?.FirstOrDefault();
|
||||
|
||||
// Check if the content type has a custom listview (extra check to prevent duplicates)
|
||||
if (clv == null)
|
||||
{
|
||||
// ContentType has no custom listview so it uses the default one
|
||||
var udi = new GuidUdi(ObjectTypes.GetUdiType(contentWithListView.NodeDto.NodeObjectType!.Value), contentWithListView.NodeDto.UniqueId);
|
||||
var listViewType = new List<string>();
|
||||
|
||||
if (dataType.Id.Equals(Constants.DataTypes.DefaultContentListView) && udi.EntityType == ObjectTypes.GetUdiType(UmbracoObjectTypes.DocumentType))
|
||||
listViewType.Add(Constants.Conventions.DataTypes.ListViewPrefix + "Content");
|
||||
else if (dataType.Id.Equals(Constants.DataTypes.DefaultMediaListView) && udi.EntityType == ObjectTypes.GetUdiType(UmbracoObjectTypes.MediaType))
|
||||
listViewType.Add(Constants.Conventions.DataTypes.ListViewPrefix + "Media");
|
||||
else if (dataType.Id.Equals(Constants.DataTypes.DefaultMembersListView) && udi.EntityType == ObjectTypes.GetUdiType(UmbracoObjectTypes.MemberType))
|
||||
listViewType.Add(Constants.Conventions.DataTypes.ListViewPrefix + "Members");
|
||||
|
||||
if (listViewType.Any())
|
||||
{
|
||||
var added = usages.TryAdd(udi, listViewType);
|
||||
if (!added)
|
||||
{
|
||||
usages[udi] = usages[udi].Append(dataType.Name!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return usages;
|
||||
}
|
||||
|
||||
|
||||
#region Overrides of RepositoryBase<int,DataTypeDefinition>
|
||||
|
||||
protected override IDataType? PerformGet(int id) => GetMany(id).FirstOrDefault();
|
||||
|
||||
@@ -430,7 +430,8 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
var result = new DataTypeReferences();
|
||||
var usages = _dataTypeService.GetReferences(id);
|
||||
|
||||
foreach(var groupOfEntityType in usages.GroupBy(x => x.Key.EntityType))
|
||||
// properties
|
||||
foreach (var groupOfEntityType in usages.GroupBy(x => x.Key.EntityType))
|
||||
{
|
||||
//get all the GUIDs for the content types to find
|
||||
var guidsAndPropertyAliases = groupOfEntityType.ToDictionary(i => ((GuidUdi)i.Key).Guid, i => i.Value);
|
||||
@@ -443,6 +444,21 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
result.MemberTypes = GetContentTypeUsages(_memberTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases);
|
||||
}
|
||||
|
||||
// ListView
|
||||
var listViewUsages = _dataTypeService.GetListViewReferences(id);
|
||||
foreach (var groupOfEntityType in listViewUsages.GroupBy(x => x.Key.EntityType))
|
||||
{
|
||||
//get all the GUIDs for the content types to find
|
||||
var guidsAndPropertyAliases = groupOfEntityType.ToDictionary(i => ((GuidUdi)i.Key).Guid, i => i.Value);
|
||||
|
||||
if (groupOfEntityType.Key == ObjectTypes.GetUdiType(UmbracoObjectTypes.DocumentType))
|
||||
result.DocumentTypes = result.DocumentTypes.Concat(GetListViewContentTypeUsages(_contentTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases));
|
||||
else if (groupOfEntityType.Key == ObjectTypes.GetUdiType(UmbracoObjectTypes.MediaType))
|
||||
result.MediaTypes = result.MediaTypes.Concat(GetListViewContentTypeUsages(_mediaTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases));
|
||||
else if (groupOfEntityType.Key == ObjectTypes.GetUdiType(UmbracoObjectTypes.MemberType))
|
||||
result.MemberTypes = result.MemberTypes.Concat(GetListViewContentTypeUsages(_memberTypeService.GetAll(guidsAndPropertyAliases.Keys), guidsAndPropertyAliases));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -481,6 +497,22 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
});
|
||||
}
|
||||
|
||||
private IEnumerable<DataTypeReferences.ContentTypeReferences> GetListViewContentTypeUsages(
|
||||
IEnumerable<IContentTypeBase> cts,
|
||||
IReadOnlyDictionary<Guid, IEnumerable<string>> usages) => cts.Select(x => new DataTypeReferences.ContentTypeReferences
|
||||
{
|
||||
Id = x.Id,
|
||||
Key = x.Key,
|
||||
Alias = x.Alias,
|
||||
Icon = x.Icon,
|
||||
Name = x.Name,
|
||||
Udi = new GuidUdi(ObjectTypes.GetUdiType(UmbracoObjectTypes.DocumentType), x.Key),
|
||||
ListViews = usages.GetValueOrDefault(x.Key)?.Select(lv => new DataTypeReferences.ContentTypeReferences.ListViewReferences
|
||||
{
|
||||
Name = lv
|
||||
})
|
||||
});
|
||||
|
||||
#region ReadOnly actions to return basic data - allow access for: content ,media, members, settings, developer
|
||||
/// <summary>
|
||||
/// Gets the content json for all data types
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<div class="umb-table-cell"><umb-icon icon="{{reference.icon}}" class="umb-table-body__icon"></umb-icon></div>
|
||||
<div class="umb-table-cell umb-table__name"><span>{{::reference.name}}</span></div>
|
||||
<div class="umb-table-cell"><span title="{{::reference.alias}}">{{::reference.alias}}</span></div>
|
||||
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}}</span></div>
|
||||
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}} {{::reference.listViews | umbCmsJoinArray:', ':'name'}}</span></div>
|
||||
<div class="umb-table-cell umb-table-cell--nano"><a href="#/settings/documentTypes/edit/{{::reference.id}}" ng-click="vm.openDocumentType(reference.id, $event)"><localize key="general_open">Open</localize></a></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
<!-- Media Types -->
|
||||
<div ng-if="vm.references.mediaTypes.length > 0" class="mb4">
|
||||
|
||||
|
||||
<h5 class="mt0" style="margin-bottom: 20px;">
|
||||
<localize key="references_labelUsedByMediaTypes">Used in Media Types</localize>
|
||||
</h5>
|
||||
@@ -72,7 +72,7 @@
|
||||
<div class="umb-table-cell"><umb-icon icon="{{reference.icon}}" class="umb-table-body__icon"></umb-icon></div>
|
||||
<div class="umb-table-cell umb-table__name"><span>{{::reference.name}}</span></div>
|
||||
<div class="umb-table-cell"><span title="{{::reference.alias}}">{{::reference.alias}}</span></div>
|
||||
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}}</span></div>
|
||||
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}} {{::reference.listViews | umbCmsJoinArray:', ':'name'}} </span></div>
|
||||
<div class="umb-table-cell umb-table-cell--nano"><a href="#/settings/mediaTypes/edit/{{::reference.id}}" ng-click="vm.openMediaType(reference.id, $event)"><localize key="general_open">Open</localize></a></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -103,7 +103,7 @@
|
||||
<div class="umb-table-cell"><umb-icon icon="{{reference.icon}}" class="umb-table-body__icon"></umb-icon></div>
|
||||
<div class="umb-table-cell umb-table__name"><span>{{::reference.name}}</span></div>
|
||||
<div class="umb-table-cell"><span title="{{::reference.alias}}">{{::reference.alias}}</span></div>
|
||||
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}}</span></div>
|
||||
<div class="umb-table-cell --noOverflow"><span>{{::reference.properties | umbCmsJoinArray:', ':'name'}} {{::reference.listViews | umbCmsJoinArray:', ':'name'}}</span></div>
|
||||
<div class="umb-table-cell umb-table-cell--nano"><a href="#/settings/memberTypes/edit/{{::reference.id}}" ng-click="vm.openMemberType(reference.id, $event)"><localize key="general_open">Open</localize></a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user