Merge remote-tracking branch 'origin/v8/feature/media-tracking' into v8/feature/AB3466-paged-relations
# Conflicts: # src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs
This commit is contained in:
@@ -9,6 +9,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
IEnumerable<IRelation> GetPagedRelationsByQuery(IQuery<IRelation> query, long pageIndex, int pageSize, out long totalRecords, Ordering ordering);
|
||||
|
||||
/// <summary>
|
||||
/// Persist multiple <see cref="IRelation"/> at once
|
||||
/// </summary>
|
||||
/// <param name="relations"></param>
|
||||
void Save(IEnumerable<IRelation> relations);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all relations for a parent for any specified relation type alias
|
||||
/// </summary>
|
||||
|
||||
@@ -853,21 +853,22 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
var allRelationTypes = RelationTypeRepository.GetMany(Array.Empty<int>())
|
||||
.ToDictionary(x => x.Alias, x => x);
|
||||
|
||||
foreach(var rel in trackedRelations)
|
||||
{
|
||||
if (!allRelationTypes.TryGetValue(rel.RelationTypeAlias, out var relationType))
|
||||
throw new InvalidOperationException($"The relation type {rel.RelationTypeAlias} does not exist");
|
||||
var toSave = trackedRelations.Select(rel =>
|
||||
{
|
||||
if (!allRelationTypes.TryGetValue(rel.RelationTypeAlias, out var relationType))
|
||||
throw new InvalidOperationException($"The relation type {rel.RelationTypeAlias} does not exist");
|
||||
|
||||
if (!udiToGuids.TryGetValue(rel.Udi, out var guid))
|
||||
continue; // This shouldn't happen!
|
||||
if (!udiToGuids.TryGetValue(rel.Udi, out var guid))
|
||||
return null; // This shouldn't happen!
|
||||
|
||||
if (!keyToIds.TryGetValue(guid, out var id))
|
||||
continue; // This shouldn't happen!
|
||||
if (!keyToIds.TryGetValue(guid, out var id))
|
||||
return null; // This shouldn't happen!
|
||||
|
||||
//Create new relation
|
||||
//TODO: This is N+1, we could do this all in one operation, just need a new method on the relations repo
|
||||
RelationRepository.Save(new Relation(entity.Id, id, relationType));
|
||||
}
|
||||
return new Relation(entity.Id, id, relationType);
|
||||
}).WhereNotNull();
|
||||
|
||||
// Save bulk relations
|
||||
RelationRepository.Save(toSave);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,50 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
#endregion
|
||||
|
||||
public void Save(IEnumerable<IRelation> relations)
|
||||
{
|
||||
foreach (var hasIdentityGroup in relations.GroupBy(r => r.HasIdentity))
|
||||
{
|
||||
if (hasIdentityGroup.Key)
|
||||
{
|
||||
// Do updates, we can't really do a bulk update so this is still a 1 by 1 operation
|
||||
// however we can bulk populate the object types. It might be possible to bulk update
|
||||
// with SQL but would be pretty ugly and we're not really too worried about that for perf,
|
||||
// it's the bulk inserts we care about.
|
||||
var asArray = hasIdentityGroup.ToArray();
|
||||
foreach (var relation in hasIdentityGroup)
|
||||
{
|
||||
relation.UpdatingEntity();
|
||||
var dto = RelationFactory.BuildDto(relation);
|
||||
Database.Update(dto);
|
||||
}
|
||||
PopulateObjectTypes(asArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do bulk inserts
|
||||
var entitiesAndDtos = hasIdentityGroup.ToDictionary(
|
||||
r => // key = entity
|
||||
{
|
||||
r.AddingEntity();
|
||||
return r;
|
||||
},
|
||||
RelationFactory.BuildDto); // value = DTO
|
||||
|
||||
Database.InsertBulk(entitiesAndDtos.Values);
|
||||
|
||||
// All dtos now have IDs assigned
|
||||
foreach (var de in entitiesAndDtos)
|
||||
{
|
||||
// re-assign ID to the entity
|
||||
de.Key.Id = de.Value.Id;
|
||||
}
|
||||
|
||||
PopulateObjectTypes(entitiesAndDtos.Keys.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IRelation> GetPagedRelationsByQuery(IQuery<IRelation> query, long pageIndex, int pageSize, out long totalRecords, Ordering ordering)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
@@ -189,6 +233,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public void DeleteByParent(int parentId, params string[] relationTypeAliases)
|
||||
{
|
||||
var subQuery = Sql().Select<RelationDto>(x => x.Id)
|
||||
@@ -204,19 +249,28 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
Database.Execute(Sql().Delete<RelationDto>().WhereIn<RelationDto>(x => x.Id, subQuery));
|
||||
}
|
||||
|
||||
private void PopulateObjectTypes(IRelation entity)
|
||||
/// <summary>
|
||||
/// Used to populate the object types after insert/update
|
||||
/// </summary>
|
||||
/// <param name="entities"></param>
|
||||
private void PopulateObjectTypes(params IRelation[] entities)
|
||||
{
|
||||
var nodes = Database.Fetch<NodeDto>(Sql().Select<NodeDto>().From<NodeDto>().Where<NodeDto>(x => x.NodeId == entity.ChildId || x.NodeId == entity.ParentId))
|
||||
var entityIds = entities.Select(x => x.ParentId).Concat(entities.Select(y => y.ChildId)).Distinct();
|
||||
|
||||
var nodes = Database.Fetch<NodeDto>(Sql().Select<NodeDto>().From<NodeDto>()
|
||||
.WhereIn<NodeDto>(x => x.NodeId, entityIds))
|
||||
.ToDictionary(x => x.NodeId, x => x.NodeObjectType);
|
||||
|
||||
if(nodes.TryGetValue(entity.ParentId, out var parentObjectType))
|
||||
foreach (var e in entities)
|
||||
{
|
||||
entity.ParentObjectType = parentObjectType.GetValueOrDefault();
|
||||
}
|
||||
|
||||
if(nodes.TryGetValue(entity.ChildId, out var childObjectType))
|
||||
{
|
||||
entity.ChildObjectType = childObjectType.GetValueOrDefault();
|
||||
if (nodes.TryGetValue(e.ParentId, out var parentObjectType))
|
||||
{
|
||||
e.ParentObjectType = parentObjectType.GetValueOrDefault();
|
||||
}
|
||||
if (nodes.TryGetValue(e.ChildId, out var childObjectType))
|
||||
{
|
||||
e.ChildObjectType = childObjectType.GetValueOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -296,6 +296,8 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="relation">Relation to save</param>
|
||||
void Save(IRelation relation);
|
||||
|
||||
void Save(IEnumerable<IRelation> relations);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a <see cref="IRelationType"/>
|
||||
/// </summary>
|
||||
|
||||
@@ -427,6 +427,24 @@ namespace Umbraco.Core.Services.Implement
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(IEnumerable<IRelation> relations)
|
||||
{
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
var saveEventArgs = new SaveEventArgs<IRelation>(relations);
|
||||
if (scope.Events.DispatchCancelable(SavingRelation, this, saveEventArgs))
|
||||
{
|
||||
scope.Complete();
|
||||
return;
|
||||
}
|
||||
|
||||
_relationRepository.Save(relations);
|
||||
scope.Complete();
|
||||
saveEventArgs.CanCancel = false;
|
||||
scope.Events.Dispatch(SavedRelation, this, saveEventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Save(IRelationType relationType)
|
||||
{
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Umbraco.Tests.Services
|
||||
ServiceContext.ContentService.Save(content);
|
||||
}
|
||||
|
||||
for (var i = 0; i < 6; i++)
|
||||
for (var i = 0; i < 6; i++)
|
||||
createContentWithMediaRefs(); //create 6 content items referencing the same media
|
||||
|
||||
var relations = ServiceContext.RelationService.GetByChildId(m1.Id, Constants.Conventions.RelationTypes.RelatedMediaAlias).ToList();
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Tests.Services
|
||||
[Test]
|
||||
public void Relation_Returns_Parent_Child_Object_Types_When_Creating()
|
||||
{
|
||||
var r = CreateNewRelation("Test", "test");
|
||||
var r = CreateAndSaveRelation("Test", "test");
|
||||
|
||||
Assert.AreEqual(Constants.ObjectTypes.Document, r.ParentObjectType);
|
||||
Assert.AreEqual(Constants.ObjectTypes.Media, r.ChildObjectType);
|
||||
@@ -141,7 +141,7 @@ namespace Umbraco.Tests.Services
|
||||
[Test]
|
||||
public void Relation_Returns_Parent_Child_Object_Types_When_Getting()
|
||||
{
|
||||
var r = CreateNewRelation("Test", "test");
|
||||
var r = CreateAndSaveRelation("Test", "test");
|
||||
|
||||
// re-get
|
||||
r = ServiceContext.RelationService.GetById(r.Id);
|
||||
@@ -150,7 +150,47 @@ namespace Umbraco.Tests.Services
|
||||
Assert.AreEqual(Constants.ObjectTypes.Media, r.ChildObjectType);
|
||||
}
|
||||
|
||||
private IRelation CreateNewRelation(string name, string alias)
|
||||
[Test]
|
||||
public void Insert_Bulk_Relations()
|
||||
{
|
||||
var rs = ServiceContext.RelationService;
|
||||
|
||||
var newRelations = CreateRelations(10);
|
||||
|
||||
Assert.IsTrue(newRelations.All(x => !x.HasIdentity));
|
||||
|
||||
ServiceContext.RelationService.Save(newRelations);
|
||||
|
||||
Assert.IsTrue(newRelations.All(x => x.HasIdentity));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Update_Bulk_Relations()
|
||||
{
|
||||
var rs = ServiceContext.RelationService;
|
||||
|
||||
var date = DateTime.Now.AddDays(-10);
|
||||
var newRelations = CreateRelations(10);
|
||||
foreach (var r in newRelations)
|
||||
{
|
||||
r.CreateDate = date;
|
||||
r.UpdateDate = date;
|
||||
}
|
||||
|
||||
//insert
|
||||
ServiceContext.RelationService.Save(newRelations);
|
||||
Assert.IsTrue(newRelations.All(x => x.UpdateDate == date));
|
||||
|
||||
var newDate = DateTime.Now.AddDays(-5);
|
||||
foreach (var r in newRelations)
|
||||
r.UpdateDate = newDate;
|
||||
|
||||
//update
|
||||
ServiceContext.RelationService.Save(newRelations);
|
||||
Assert.IsTrue(newRelations.All(x => x.UpdateDate == newDate));
|
||||
}
|
||||
|
||||
private IRelation CreateAndSaveRelation(string name, string alias)
|
||||
{
|
||||
var rs = ServiceContext.RelationService;
|
||||
var rt = new RelationType(name, alias, false, null, null);
|
||||
@@ -173,6 +213,35 @@ namespace Umbraco.Tests.Services
|
||||
return r;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a bunch of content/media items return relation objects for them (unsaved)
|
||||
/// </summary>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<IRelation> CreateRelations(int count)
|
||||
{
|
||||
var rs = ServiceContext.RelationService;
|
||||
var rtName = Guid.NewGuid().ToString();
|
||||
var rt = new RelationType(rtName, rtName, false, null, null);
|
||||
rs.Save(rt);
|
||||
|
||||
var ct = MockedContentTypes.CreateBasicContentType();
|
||||
ServiceContext.ContentTypeService.Save(ct);
|
||||
|
||||
var mt = MockedContentTypes.CreateImageMediaType("img");
|
||||
ServiceContext.MediaTypeService.Save(mt);
|
||||
|
||||
return Enumerable.Range(1, count).Select(index =>
|
||||
{
|
||||
var c1 = MockedContent.CreateBasicContent(ct);
|
||||
var c2 = MockedMedia.CreateMediaImage(mt, -1);
|
||||
ServiceContext.ContentService.Save(c1);
|
||||
ServiceContext.MediaService.Save(c2);
|
||||
|
||||
return new Relation(c1.Id, c2.Id, rt);
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
//TODO: Create a relation for entities of the wrong Entity Type (GUID) based on the Relation Type's defined parent/child object types
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, editorService, mediaHelper) {
|
||||
function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, editorService, mediaHelper, mediaResource, $routeParams) {
|
||||
|
||||
function link(scope, element, attrs, ctrl) {
|
||||
|
||||
var evts = [];
|
||||
var referencesLoaded = false;
|
||||
|
||||
scope.allowChangeMediaType = false;
|
||||
scope.loading = true;
|
||||
|
||||
function onInit() {
|
||||
|
||||
@@ -94,6 +96,19 @@
|
||||
setMediaExtension();
|
||||
});
|
||||
|
||||
/** Loads in the media references one time */
|
||||
function loadRelations() {
|
||||
if (!referencesLoaded) {
|
||||
referencesLoaded = true;
|
||||
mediaResource.getReferences($routeParams.id)
|
||||
.then(function (data) {
|
||||
scope.loading = false;
|
||||
scope.references = data;
|
||||
scope.hasReferences = data.content.length > 0 || data.members.length > 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//ensure to unregister from all events!
|
||||
scope.$on('$destroy', function () {
|
||||
for (var e in evts) {
|
||||
@@ -102,6 +117,15 @@
|
||||
});
|
||||
|
||||
onInit();
|
||||
|
||||
// load media type references when the 'info' tab is first activated/switched to
|
||||
evts.push(eventsService.on("app.tabChange", function (event, args) {
|
||||
$timeout(function () {
|
||||
if (args.alias === "umbInfo") {
|
||||
loadRelations();
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
var directive = {
|
||||
|
||||
@@ -552,8 +552,31 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
"Search",
|
||||
args)),
|
||||
'Failed to retrieve media items for search: ' + query);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaResource#getReferences
|
||||
* @methodOf umbraco.resources.mediaResource
|
||||
*
|
||||
* @description
|
||||
* Retrieves references of a given media item.
|
||||
*
|
||||
* @param {Int} id id of media node to retrieve references for
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getReferences: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaApiBaseUrl",
|
||||
"GetReferences",
|
||||
{ id: id })),
|
||||
"Failed to retrieve usages for media of id " + id);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
<div class="umb-package-details">
|
||||
<div class="umb-package-details__main-content">
|
||||
|
||||
<umb-load-indicator ng-if="loading === true"></umb-load-indicator>
|
||||
|
||||
<!-- Main Column -->
|
||||
<div class="umb-package-details__main-content" ng-if="loading === false">
|
||||
|
||||
<!-- Links -->
|
||||
<umb-box data-element="node-info-urls">
|
||||
<umb-box-header title-key="general_links"></umb-box-header>
|
||||
<umb-box-content class="block-form">
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="!nodeUrl"
|
||||
size="small">
|
||||
<umb-empty-state ng-if="!nodeUrl"
|
||||
size="small">
|
||||
<localize key="content_noMediaLink"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
<ul ng-if="nodeUrl" class="nav nav-stacked" style="margin-bottom: 0;">
|
||||
<li>
|
||||
<a ng-attr-href="{{node.extension !== 'svg' ? nodeUrl : undefined}}" ng-click="node.extension === 'svg' && openSVG()" target="_blank">
|
||||
<i class="icon icon-out"></i>
|
||||
<span>{{nodeFileName}}</span>
|
||||
<i class="icon icon-out"></i>
|
||||
<span>{{nodeFileName}}</span>
|
||||
|
||||
</a>
|
||||
</li>
|
||||
@@ -23,9 +28,106 @@
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<!-- Media Tracking (NO Items) -->
|
||||
<umb-box ng-if="loading === false && hasReferences === false">
|
||||
<umb-box-header title-key="references_tabName"></umb-box-header>
|
||||
<umb-box-content>
|
||||
<umb-empty-state size="small">
|
||||
This Media item has no references.
|
||||
</umb-empty-state>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<!-- Media Tracking (With Items) -->
|
||||
<div ng-if="loading === false && hasReferences === true">
|
||||
|
||||
<!-- Content -->
|
||||
<div ng-if="references.content.length > 0">
|
||||
|
||||
<h5 class="mt4" style="margin-bottom: 20px;">
|
||||
<localize key="references_labelUsedByDocuments">Used in Documents</localize>
|
||||
</h5>
|
||||
|
||||
<div class="umb-table">
|
||||
<div class="umb-table-head">
|
||||
<div class="umb-table-row">
|
||||
<div class="umb-table-cell"></div>
|
||||
<div class="umb-table-cell umb-table__name not-fixed"><localize key="general_name">Name</localize></div>
|
||||
<div class="umb-table-cell"><localize key="content_alias">Alias</localize></div>
|
||||
<div class="umb-table-cell umb-table-cell--nano"><localize key="general_open" style="visibility:hidden;">Open</localize></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-table-body">
|
||||
<div class="umb-table-row" ng-repeat="reference in references.content">
|
||||
<div class="umb-table-cell"><i class="umb-table-body__icon {{reference.icon}}"></i></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 umb-table-cell--nano"><a ng-href="#/content/content/edit/{{::reference.id}}"><localize key="general_open">Open</localize></a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Members -->
|
||||
<div ng-if="references.members.length > 0">
|
||||
|
||||
<h5 class="mt4" style="margin-bottom: 20px;">
|
||||
<localize key="references_labelUsedByMembers">Used in Members</localize>
|
||||
</h5>
|
||||
|
||||
<div class="umb-table">
|
||||
<div class="umb-table-head">
|
||||
<div class="umb-table-row">
|
||||
<div class="umb-table-cell"></div>
|
||||
<div class="umb-table-cell umb-table__name not-fixed"><localize key="general_name">Name</localize></div>
|
||||
<div class="umb-table-cell"><localize key="content_alias">Alias</localize></div>
|
||||
<div class="umb-table-cell umb-table-cell--nano"><localize key="general_open" style="visibility:hidden;">Open</localize></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-table-body">
|
||||
<div class="umb-table-row" ng-repeat="reference in references.members">
|
||||
<div class="umb-table-cell"><i class="umb-table-body__icon {{reference.icon}}"></i></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 umb-table-cell--nano"><a href="#/member/member/edit/{{::reference.key}}"><localize key="general_open">Open</localize></a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Media -->
|
||||
<div ng-if="references.media.length > 0">
|
||||
|
||||
<h5 class="mt4" style="margin-bottom: 20px;">
|
||||
<localize key="references_labelUsedByMedia">Used in Media</localize>
|
||||
</h5>
|
||||
|
||||
<div class="umb-table">
|
||||
<div class="umb-table-head">
|
||||
<div class="umb-table-row">
|
||||
<div class="umb-table-cell"></div>
|
||||
<div class="umb-table-cell umb-table__name not-fixed"><localize key="general_name">Name</localize></div>
|
||||
<div class="umb-table-cell"><localize key="content_alias">Alias</localize></div>
|
||||
<div class="umb-table-cell umb-table-cell--nano"><localize key="general_open" style="visibility:hidden;">Open</localize></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-table-body">
|
||||
<div class="umb-table-row" ng-repeat="reference in references.media">
|
||||
<div class="umb-table-cell"><i class="umb-table-body__icon {{reference.icon}}"></i></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 umb-table-cell--nano"><a href="#/media/media/edit/{{::reference.id}}"><localize key="general_open">Open</localize></a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__sidebar">
|
||||
<!-- Sidebar -->
|
||||
<div class="umb-package-details__sidebar" ng-if="loading === false">
|
||||
<!-- General Info -->
|
||||
<umb-box data-element="node-info-general">
|
||||
<umb-box-header title-key="general_general"></umb-box-header>
|
||||
<umb-box-content class="block-form">
|
||||
@@ -39,12 +141,11 @@
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group data-element="node-info-media-type" label="@content_mediatype">
|
||||
<umb-node-preview
|
||||
style="max-width: 100%; margin-bottom: 0px;"
|
||||
icon="node.icon"
|
||||
name="node.contentTypeName"
|
||||
allow-open="allowChangeMediaType"
|
||||
on-open="openMediaType(mediaType)">
|
||||
<umb-node-preview style="max-width: 100%; margin-bottom: 0px;"
|
||||
icon="node.icon"
|
||||
name="node.contentTypeName"
|
||||
allow-open="allowChangeMediaType"
|
||||
on-open="openMediaType(mediaType)">
|
||||
</umb-node-preview>
|
||||
</umb-control-group>
|
||||
|
||||
|
||||
@@ -2181,6 +2181,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="labelUsedByMemberTypes">Used in Member Types</key>
|
||||
<key alias="noMemberTypes">No references to Member Types.</key>
|
||||
<key alias="usedByProperties">Used by</key>
|
||||
<key alias="labelUsedByDocuments">Used in Documents</key>
|
||||
<key alias="labelUsedByMembers">Used in Members</key>
|
||||
<key alias="labelUsedByMedia">Used in Media</key>
|
||||
</area>
|
||||
<area alias="logViewer">
|
||||
<key alias="logLevels">Log Levels</key>
|
||||
|
||||
@@ -2197,6 +2197,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="labelUsedByMemberTypes">Used in Member Types</key>
|
||||
<key alias="noMemberTypes">No references to Member Types.</key>
|
||||
<key alias="usedByProperties">Used by</key>
|
||||
<key alias="labelUsedByDocuments">Used in Documents</key>
|
||||
<key alias="labelUsedByMembers">Used in Members</key>
|
||||
<key alias="labelUsedByMedia">Used in Media</key>
|
||||
</area>
|
||||
<area alias="logViewer">
|
||||
<key alias="logLevels">Log Levels</key>
|
||||
|
||||
@@ -36,6 +36,7 @@ using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Web.ContentApps;
|
||||
using Umbraco.Web.Editors.Binders;
|
||||
using Umbraco.Web.Editors.Filters;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -943,5 +944,71 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
return hasPathAccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the references (usages) for the media item
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public MediaReferences GetReferences(int id)
|
||||
{
|
||||
var result = new MediaReferences();
|
||||
|
||||
var relations = Services.RelationService.GetByChildId(id, Constants.Conventions.RelationTypes.RelatedMediaAlias).ToList();
|
||||
var relationEntities = Services.RelationService.GetParentEntitiesFromRelations(relations).ToList();
|
||||
|
||||
var documents = new List<MediaReferences.EntityTypeReferences>();
|
||||
var members = new List<MediaReferences.EntityTypeReferences>();
|
||||
var media = new List<MediaReferences.EntityTypeReferences>();
|
||||
|
||||
foreach (var item in relationEntities)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case DocumentEntitySlim doc:
|
||||
documents.Add(new MediaReferences.EntityTypeReferences {
|
||||
Id = doc.Id,
|
||||
Key = doc.Key,
|
||||
Udi = Udi.Create(Constants.UdiEntityType.Document, doc.Key),
|
||||
Icon = doc.ContentTypeIcon,
|
||||
Name = doc.Name,
|
||||
Alias = doc.ContentTypeAlias
|
||||
});
|
||||
break;
|
||||
|
||||
case MemberEntitySlim memb:
|
||||
members.Add(new MediaReferences.EntityTypeReferences
|
||||
{
|
||||
Id = memb.Id,
|
||||
Key = memb.Key,
|
||||
Udi = Udi.Create(Constants.UdiEntityType.Member, memb.Key),
|
||||
Icon = memb.ContentTypeIcon,
|
||||
Name = memb.Name,
|
||||
Alias = memb.ContentTypeAlias
|
||||
});
|
||||
break;
|
||||
|
||||
case MediaEntitySlim med:
|
||||
media.Add(new MediaReferences.EntityTypeReferences
|
||||
{
|
||||
Id = med.Id,
|
||||
Key = med.Key,
|
||||
Udi = Udi.Create(Constants.UdiEntityType.Media, med.Key),
|
||||
Icon = med.ContentTypeIcon,
|
||||
Name = med.Name,
|
||||
Alias = med.ContentTypeAlias
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.Content = documents;
|
||||
result.Members = members;
|
||||
result.Media = media;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
src/Umbraco.Web/Models/ContentEditing/MediaReferences.cs
Normal file
24
src/Umbraco.Web/Models/ContentEditing/MediaReferences.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "mediaReferences", Namespace = "")]
|
||||
public class MediaReferences
|
||||
{
|
||||
[DataMember(Name = "content")]
|
||||
public IEnumerable<EntityTypeReferences> Content { get; set; } = Enumerable.Empty<EntityTypeReferences>();
|
||||
|
||||
[DataMember(Name = "members")]
|
||||
public IEnumerable<EntityTypeReferences> Members { get; set; } = Enumerable.Empty<EntityTypeReferences>();
|
||||
|
||||
[DataMember(Name = "media")]
|
||||
public IEnumerable<EntityTypeReferences> Media { get; set; } = Enumerable.Empty<EntityTypeReferences>();
|
||||
|
||||
[DataContract(Name = "entityType", Namespace = "")]
|
||||
public class EntityTypeReferences : EntityBasic
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,6 +222,7 @@
|
||||
<Compile Include="Models\ContentEditing\LinkDisplay.cs" />
|
||||
<Compile Include="Models\ContentEditing\MacroDisplay.cs" />
|
||||
<Compile Include="Models\ContentEditing\MacroParameterDisplay.cs" />
|
||||
<Compile Include="Models\ContentEditing\MediaReferences.cs" />
|
||||
<Compile Include="Models\ContentEditing\UrlAndAnchors.cs" />
|
||||
<Compile Include="Models\Mapping\CommonMapper.cs" />
|
||||
<Compile Include="Models\Mapping\MapperContextExtensions.cs" />
|
||||
@@ -1283,4 +1284,4 @@
|
||||
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
|
||||
</SGen>
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user