Implementing inline audit trail on content editor view.

This commit is contained in:
sfmskywalker
2014-05-26 01:36:05 +02:00
parent 5f63454cee
commit 780d1248d3
8 changed files with 150 additions and 13 deletions

View File

@@ -1,20 +1,72 @@
using Orchard.AuditTrail.Models;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Orchard.AuditTrail.Models;
using Orchard.AuditTrail.Services;
using Orchard.AuditTrail.Settings;
using Orchard.AuditTrail.ViewModels;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.UI.Navigation;
namespace Orchard.AuditTrail.Drivers {
public class AuditTrailPartDriver : ContentPartDriver<AuditTrailPart> {
private readonly IOrchardServices _services;
private readonly IAuditTrailManager _auditTrailManager;
private readonly IAuditTrailEventDisplayBuilder _displayBuilder;
public AuditTrailPartDriver(IOrchardServices services, IAuditTrailManager auditTrailManager, IAuditTrailEventDisplayBuilder displayBuilder) {
_services = services;
_auditTrailManager = auditTrailManager;
_displayBuilder = displayBuilder;
}
protected override DriverResult Editor(AuditTrailPart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(AuditTrailPart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape("Parts_AuditTrail_Edit", () => {
if (updater != null) {
updater.TryUpdateModel(part, Prefix, null, null);
}
return shapeHelper.EditorTemplate(Model: part, TemplateName: "Parts.AuditTrail", Prefix: Prefix);
});
var settings = part.Settings.GetModel<AuditTrailPartSettings>();
var results = new List<DriverResult>();
if (settings.ShowAuditTrailCommentInput) {
results.Add(ContentShape("Parts_AuditTrail_Comment", () => {
if (updater != null) {
updater.TryUpdateModel(part, Prefix, null, null);
}
return shapeHelper.EditorTemplate(Model: part, TemplateName: "Parts.AuditTrail.Comment", Prefix: Prefix);
}));
}
if (settings.ShowAuditTrailLink) {
results.Add(ContentShape("Parts_AuditTrail_Link", () => shapeHelper.Parts_AuditTrail_Link()));
}
if (settings.ShowAuditTrail) {
results.Add(ContentShape("Parts_AuditTrail", () => {
var pager = new Pager(_services.WorkContext.CurrentSite, null, null);
var pageOfData = _auditTrailManager.GetRecords(pager.Page, pager.PageSize, new AuditTrailFilterParameters {
FilterKey = "content",
FilterValue = part.Id.ToString(CultureInfo.InvariantCulture)
});
var pagerShape = shapeHelper.Pager(pager).TotalItemCount(pageOfData.TotalItemCount);
var eventDescriptors = from c in _auditTrailManager.Describe()
from e in c.Events
select e;
var recordViewModels = from record in pageOfData
let descriptor = eventDescriptors.FirstOrDefault(x => x.Event == record.Event)
where descriptor != null
select new AuditTrailEventSummaryViewModel {
Record = record,
EventDescriptor = descriptor,
CategoryDescriptor = descriptor.CategoryDescriptor,
SummaryShape = _displayBuilder.BuildDisplay(record, "SummaryAdmin")
};
return shapeHelper.Parts_AuditTrail(Records: recordViewModels, Pager: pagerShape);
}));
}
return Combined(results.ToArray());
}
}
}

View File

@@ -83,6 +83,8 @@
<Content Include="Module.txt" />
<Content Include="Views\Parts.Contents.AuditTrail.SummaryAdmin.cshtml" />
<Content Include="Views\DefinitionTemplates\AuditTrailPartSettings.cshtml" />
<Content Include="Views\Parts.AuditTrail.Link.cshtml" />
<Content Include="Views\Parts.AuditTrail.cshtml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
@@ -151,7 +153,7 @@
<Content Include="Views\AuditTrailEvent-Content.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\EditorTemplates\Parts.AuditTrail.cshtml" />
<Content Include="Views\EditorTemplates\Parts.AuditTrail.Comment.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>

View File

@@ -1,5 +1,8 @@
<Placement>
<Place Parts_AuditTrail_Edit="Content:after" />
<Place Parts_AuditTrail_Comment="Content:after.1"
Parts_AuditTrail_Link="Content:after.2"
Parts_AuditTrail="Content:after.3"/>
<Match DisplayType="SummaryAdmin">
<Place Parts_Contents_AuditTrail_SummaryAdmin="Actions:7"/>
</Match>

View File

@@ -0,0 +1,10 @@
(function($) {
// Initialize Expando control
$(".expando-wrapper legend").expandoControl(
function (controller) {
return controller.nextAll(".expando");
}, {
collapse: true,
remember: true
});
})(jQuery);

View File

@@ -9,6 +9,8 @@
new SelectListItem {Text = T("Date (desc)").Text, Value = AuditTrailOrderBy.DateDescending.ToString(), Selected = Model.Filter.OrderBy == AuditTrailOrderBy.DateDescending},
new SelectListItem {Text = T("Event (asc)").Text, Value = AuditTrailOrderBy.EventAscending.ToString(), Selected = Model.Filter.OrderBy == AuditTrailOrderBy.EventAscending},
};
Layout.Title = T("Audit Trail");
}
<section class="audit-trail-filter">
@using (Html.BeginForm("Index", "Admin", new { area = "Orchard.AuditTrail" }, FormMethod.Get)) {
@@ -17,9 +19,9 @@
@Html.Hidden("filtervalue", Model.Filter.FilterValue)
@Html.Label("username", T("User:").Text)
@Html.TextBox("username", Model.Filter.UserName, new { @class = "text" })
@Html.LabelFor(m => from, T("Between:"))
@Html.LabelFor(m => from, T("From:"))
@Html.EditorFor(m => from)
@Html.LabelFor(m => to, T("And:"))
@Html.LabelFor(m => to, T("To:"))
@Html.EditorFor(m => to)
@Html.LabelFor(m => orderBy, T("Ordered by:"))
@Html.DropDownListFor(m => orderBy, orderByItems)

View File

@@ -1,8 +1,7 @@
@model Orchard.AuditTrail.Models.AuditTrailPart
<fieldset>
<legend>@T("Audit Trail")</legend>
<div>
@Html.LabelFor(m => m.Comment)
@Html.LabelFor(m => m.Comment, T("Audit Trail Comment"))
@Html.TextBoxFor(m => m.Comment, new { @class = "text large" })
<span class="hint">@T("Optionally provide a comment about this change. This comment will be stored as part of an audit trail event.")</span>
</div>

View File

@@ -0,0 +1,8 @@
@{
var contentId = (int)Model.ContentPart.Id;
}
@if (contentId > 0) {
<fieldset>
@Html.ActionLink(T("View Audit Trail").Text, "Index", "Admin", new { filterkey = "content", filtervalue = contentId, area = "Orchard.AuditTrail" }, null)
</fieldset>
}

View File

@@ -0,0 +1,61 @@
@using Orchard.AuditTrail.Models
@using Orchard.AuditTrail.ViewModels
@{
Script.Require("ShapesBase");
Script.Include("~/Themes/TheAdmin/scripts/admin.js").AtFoot();
Script.Include("audit-trail-admin.js").AtFoot();
}
@{
var records = (IEnumerable<AuditTrailEventSummaryViewModel>)Model.Records;
var auditTrailPart = (AuditTrailPart)Model.ContentPart;
}
@if (auditTrailPart.Id > 0) {
<fieldset class="expando-wrapper">
<legend>@T("Audit Trail")</legend>
<div class="expando">
<section class="audit-trail-list">
@if (!records.Any()) {
<p class="info">@T("There are no audit trail events to display.")</p>
}
else {
<table class="items">
<thead>
<tr>
<th>@T("Event")</th>
<th>@T("Category")</th>
<th>@T("User")</th>
<th>@T("Timestamp")</th>
<th>@T("Comment")</th>
<th>@T("Event Data")</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var record in records) {
<tr>
<td>@record.EventDescriptor.Name</td>
<td>@record.CategoryDescriptor.Name</td>
<td>@record.Record.UserName</td>
<td>@Display.DateTime(DateTimeUtc: record.Record.CreatedUtc, CustomFormat: T("g"))</td>
<td>@record.Record.Comment</td>
<td>@Display(record.SummaryShape)</td>
<td>@Html.ActionLink(T("Details").Text, "Detail", "Admin", new { id = record.Record.Id, area = "Orchard.AuditTrail" }, null)</td>
</tr>
}
</tbody>
@if (Model.Pager.TotalItemCount > Model.Pager.PageSize) {
<tfoot>
<tr>
<td colspan="6">
@Html.ActionLink(T("Show more events").Text, "Index", "Admin", new { filterKey = "content", filterValue = auditTrailPart.Id, page = 2, area = "Orchard.AuditTrail" }, null)
</td>
</tr>
</tfoot>
}
</table>
}
</section>
</div>
</fieldset>
}