-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
ContainedPartDisplayDriver.cs
173 lines (149 loc) · 7.51 KB
/
ContainedPartDisplayDriver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using OrchardCore.ContentManagement;
using OrchardCore.ContentManagement.Display.ContentDisplay;
using OrchardCore.ContentManagement.Metadata;
using OrchardCore.ContentManagement.Metadata.Models;
using OrchardCore.DisplayManagement.ModelBinding;
using OrchardCore.DisplayManagement.Views;
using OrchardCore.Lists.Models;
using OrchardCore.Lists.Services;
using OrchardCore.Lists.ViewModels;
namespace OrchardCore.Lists.Drivers
{
public class ContainedPartDisplayDriver : ContentDisplayDriver
{
private readonly IContentManager _contentManager;
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly IContainerService _containerService;
public ContainedPartDisplayDriver(
IContentManager contentManager,
IContentDefinitionManager contentDefinitionManager,
IContainerService containerService
)
{
_contentManager = contentManager;
_contentDefinitionManager = contentDefinitionManager;
_containerService = containerService;
}
public override async Task<IDisplayResult> EditAsync(ContentItem model, IUpdateModel updater)
{
// This method can get called when a new content item is created, at that point
// the query string contains a ListPart.ContainerId value, or when an
// existing content item has ContainedPart value. In both cases the hidden field
// needs to be rendered in the edit form to maintain the relationship with the parent.
var containedPart = model.As<ContainedPart>();
if (containedPart != null)
{
return BuildViewModel(containedPart.ListContentItemId, containedPart.ListContentType, model.ContentType);
}
var viewModel = new EditContainedPartViewModel();
if (await updater.TryUpdateModelAsync(viewModel, nameof(ListPart))
&& viewModel.ContainerId != null
&& viewModel.ContentType == model.ContentType)
{
// We are creating a content item that needs to be added to a container.
// Render the container id as part of the form. The content type, and the enable ordering setting.
// The content type must be included to prevent any contained items,
// such as widgets, from also having a ContainedPart shape built for them.
// Attach ContainedPart to the contentitem during edit to provide handlers container info.
await model.AlterAsync<ContainedPart>(async part =>
{
part.ListContentItemId = viewModel.ContainerId;
part.ListContentType = viewModel.ContainerContentType;
if (viewModel.EnableOrdering)
{
part.Order = await _containerService.GetNextOrderNumberAsync(viewModel.ContainerId);
}
});
return BuildViewModel(viewModel.ContainerId, viewModel.ContainerContentType, model.ContentType, viewModel.EnableOrdering);
}
return null;
}
public override async Task<IDisplayResult> UpdateAsync(ContentItem model, IUpdateModel updater)
{
var viewModel = new EditContainedPartViewModel();
// The content type must match the value provided in the query string
// in order for the ContainedPart to be included on the Content Item.
if (await updater.TryUpdateModelAsync(viewModel, nameof(ListPart))
&& viewModel.ContainerId != null
&& viewModel.ContentType == model.ContentType)
{
await model.AlterAsync<ContainedPart>(async part =>
{
part.ListContentItemId = viewModel.ContainerId;
part.ListContentType = viewModel.ContainerContentType;
// If creating get next order number so item is added to the end of the list.
if (viewModel.EnableOrdering)
{
part.Order = await _containerService.GetNextOrderNumberAsync(viewModel.ContainerId);
}
});
}
return await EditAsync(model, updater);
}
private IDisplayResult BuildViewModel(string containerId, string containerContentType, string contentType, bool enableOrdering = false)
{
var results = new List<IDisplayResult>()
{
Initialize<EditContainedPartViewModel>("ListPart_ContainerId", m =>
{
m.ContainerId = containerId;
m.ContainerContentType = containerContentType;
m.EnableOrdering = enableOrdering;
m.ContentType = contentType;
})
.Location("Content")
};
if (!String.IsNullOrEmpty(containerContentType))
{
var definition = _contentDefinitionManager.GetTypeDefinition(containerContentType);
if (definition != null)
{
var listPart = definition.Parts.FirstOrDefault(x => x.PartDefinition.Name == nameof(ListPart));
var settings = listPart?.GetSettings<ListPartSettings>();
if (settings != null)
{
// Add list part navigation
results.Add(Initialize<ListPartNavigationAdminViewModel>("ListPartNavigationAdmin", async model =>
{
model.ContainedContentTypeDefinitions = GetContainedContentTypes(settings).ToArray();
model.Container = await _contentManager.GetAsync(containerId, VersionOptions.Latest);
model.EnableOrdering = settings.EnableOrdering;
model.ContainerContentTypeDefinition = definition;
}).Location("Content:1.5"));
if (settings.ShowHeader)
{
results.Add(GetListPartHeader(containerId, settings));
}
}
}
}
return Combine(results);
}
private IDisplayResult GetListPartHeader(string containerId, ListPartSettings listPartSettings)
{
return Initialize<ListPartHeaderAdminViewModel>("ListPartHeaderAdmin", async model =>
{
var container = await _contentManager.GetAsync(containerId);
if (container == null)
{
return;
}
model.ContainerContentItem = container;
if (listPartSettings != null)
{
model.ContainedContentTypeDefinitions = GetContainedContentTypes(listPartSettings).ToArray();
model.EnableOrdering = listPartSettings.EnableOrdering;
}
}).Location("Content:1");
}
private IEnumerable<ContentTypeDefinition> GetContainedContentTypes(ListPartSettings settings) =>
settings.ContainedContentTypes
?.Select(contentType => _contentDefinitionManager.GetTypeDefinition(contentType))
.Where(definition => definition is not null)
?? Enumerable.Empty<ContentTypeDefinition>();
}
}