mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
151: Implemented pluggable filter UI.
153: Added Order By Category.
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.AuditTrail.ViewModels;
|
||||
using Orchard.Localization.Services;
|
||||
using Orchard.Security;
|
||||
@@ -27,20 +28,16 @@ namespace Orchard.AuditTrail.Controllers {
|
||||
|
||||
public dynamic New { get; private set; }
|
||||
|
||||
public ActionResult Index(PagerParameters pagerParameters, AuditTrailFilterViewModel filterParameters) {
|
||||
public ActionResult Index(PagerParameters pagerParameters, AuditTrailOrderBy? orderBy = null) {
|
||||
|
||||
if(!_authorizer.Authorize(Permissions.ViewAuditTrail))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var pager = new Pager(_services.WorkContext.CurrentSite, pagerParameters);
|
||||
var pageOfData = _auditTrailManager.GetRecords(pager.Page, pager.PageSize, new AuditTrailFilterParameters {
|
||||
UserName = filterParameters.UserName,
|
||||
FilterKey = filterParameters.FilterKey,
|
||||
FilterValue = filterParameters.FilterValue,
|
||||
From = _dateServices.ConvertFromLocalString(filterParameters.From.Date, filterParameters.From.Time),
|
||||
To = _dateServices.ConvertFromLocalString(filterParameters.To.Date, filterParameters.To.Time),
|
||||
}, filterParameters.OrderBy);
|
||||
var filters = Filters.From(Request.QueryString);
|
||||
var pageOfData = _auditTrailManager.GetRecords(pager.Page, pager.PageSize, filters, orderBy ?? AuditTrailOrderBy.DateDescending);
|
||||
var pagerShape = New.Pager(pager).TotalItemCount(pageOfData.TotalItemCount);
|
||||
var filterLayout = _auditTrailManager.BuildFilterDisplays(filters);
|
||||
var eventDescriptorsQuery =
|
||||
from c in _auditTrailManager.DescribeCategories()
|
||||
from e in c.Events
|
||||
@@ -60,7 +57,8 @@ namespace Orchard.AuditTrail.Controllers {
|
||||
var viewModel = new AuditTrailViewModel {
|
||||
Records = recordViewModelsQuery.ToArray(),
|
||||
Pager = pagerShape,
|
||||
Filter = filterParameters
|
||||
OrderBy = orderBy ?? AuditTrailOrderBy.DateDescending,
|
||||
FilterLayout = filterLayout
|
||||
};
|
||||
|
||||
return View(viewModel);
|
||||
|
@@ -2,7 +2,9 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Providers.Content;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.AuditTrail.Settings;
|
||||
using Orchard.AuditTrail.ViewModels;
|
||||
using Orchard.ContentManagement;
|
||||
@@ -45,10 +47,7 @@ namespace Orchard.AuditTrail.Drivers {
|
||||
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 pageOfData = _auditTrailManager.GetRecords(pager.Page, pager.PageSize, ContentAuditTrailEventProvider.CreateFilters(part.Id));
|
||||
var pagerShape = shapeHelper.Pager(pager).TotalItemCount(pageOfData.TotalItemCount);
|
||||
var eventDescriptors = from c in _auditTrailManager.DescribeCategories()
|
||||
from e in c.Events
|
||||
|
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace Orchard.AuditTrail.Helpers {
|
||||
public static class DateTimeHelper {
|
||||
public static DateTime? Earliest(this DateTime? value) {
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
var v = value.Value;
|
||||
return new DateTime(v.Year, v.Month, v.Day, 0, 0, 0, 0, v.Kind);
|
||||
}
|
||||
|
||||
public static DateTime? Latest(this DateTime? value) {
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
var v = value.Value;
|
||||
return new DateTime(v.Year, v.Month, v.Day, 23, 59, 59, 999, v.Kind);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.Helpers {
|
||||
public static class FiltersHelper {
|
||||
public static string Get(this Filters filters, string key) {
|
||||
if (!filters.ContainsKey(key))
|
||||
return null;
|
||||
|
||||
return filters[key];
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace Orchard.AuditTrail.Helpers {
|
||||
public static class StringConversionHelper {
|
||||
public static int? ToInt32(this string value) {
|
||||
if (String.IsNullOrWhiteSpace(value))
|
||||
return null;
|
||||
|
||||
int i;
|
||||
if(!Int32.TryParse(value, out i))
|
||||
return null;
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
public class DescribeContext {
|
||||
private readonly Dictionary<string, DescribeFor> _describes = new Dictionary<string, DescribeFor>();
|
||||
|
||||
public IEnumerable<AuditTrailCategoryDescriptor> Describe() {
|
||||
var query =
|
||||
from d in _describes.Values
|
||||
select new AuditTrailCategoryDescriptor {
|
||||
Category = d.Category,
|
||||
Name = d.Name,
|
||||
Events = d.Events
|
||||
};
|
||||
|
||||
return query.ToArray();
|
||||
}
|
||||
|
||||
public DescribeFor For(string category, LocalizedString name) {
|
||||
DescribeFor describeFor;
|
||||
if (!_describes.TryGetValue(category, out describeFor)) {
|
||||
describeFor = new DescribeFor(category, name);
|
||||
_describes[category] = describeFor;
|
||||
}
|
||||
return describeFor;
|
||||
}
|
||||
}
|
||||
}
|
@@ -80,6 +80,7 @@
|
||||
<Content Include="Recipes\audit-trail.recipe.xml" />
|
||||
<Content Include="Scripts\audit-trail-admin.js" />
|
||||
<Content Include="Styles\admin.css" />
|
||||
<Content Include="Styles\custom-grid.css" />
|
||||
<Content Include="Styles\menu.audit-trail-admin.css" />
|
||||
<Content Include="Styles\menu.audit-trail.png" />
|
||||
<Content Include="Web.config" />
|
||||
@@ -128,6 +129,10 @@
|
||||
<Content Include="Views\AuditTrailEvent-User.cshtml" />
|
||||
<Content Include="Views\EditorTemplates\Parts.AuditTrailSettings.cshtml" />
|
||||
<Content Include="Views\AuditTrailEvent-User-LoginFailed..cshtml" />
|
||||
<Content Include="Views\AuditTrailFilter-Common-User.cshtml" />
|
||||
<Content Include="Views\AuditTrailFilter-ContentType.cshtml" />
|
||||
<Content Include="Views\AuditTrailFilter-Common-Date.cshtml" />
|
||||
<Content Include="Views\AuditTrailFilter-ContentItem.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
|
||||
@@ -149,17 +154,26 @@
|
||||
<Compile Include="Drivers\AuditTrailTrimmingSettingsPartDriver.cs" />
|
||||
<Compile Include="Drivers\AuditTrailSettingsPartDriver.cs" />
|
||||
<Compile Include="Handlers\AuditTrailTrimmingSettingsPartHandler.cs" />
|
||||
<Compile Include="Helpers\FiltersHelper.cs" />
|
||||
<Compile Include="Helpers\DateTimeHelper.cs" />
|
||||
<Compile Include="Helpers\StringConversionHelper.cs" />
|
||||
<Compile Include="ImportExport\AuditTrailExportStep.cs" />
|
||||
<Compile Include="ImportExport\AuditTrailExportHandler.cs" />
|
||||
<Compile Include="ImportExport\AuditTrailImportHandler.cs" />
|
||||
<Compile Include="Models\AuditTrailEventRecordResult.cs" />
|
||||
<Compile Include="Models\AuditTrailTrimmingSettingsPart.cs" />
|
||||
<Compile Include="Services\CommonAuditTrailEventHandler.cs" />
|
||||
<Compile Include="Services\AuditTrailEventHandlerBase.cs" />
|
||||
<Compile Include="Services\Models\DisplayFilterContext.cs" />
|
||||
<Compile Include="Services\Models\QueryFilterContext.cs" />
|
||||
<Compile Include="Providers\Content\ContentAuditTrailEventShapes.cs" />
|
||||
<Compile Include="Providers\Content\DiffGramAnalyzer.cs" />
|
||||
<Compile Include="Providers\Content\DiffNode.cs" />
|
||||
<Compile Include="Providers\Content\DiffType.cs" />
|
||||
<Compile Include="Services\Models\Filters.cs" />
|
||||
<Compile Include="Providers\Content\IDiffGramAnalyzer.cs" />
|
||||
<Compile Include="Services\AuditTrailTrimmingBackgroundTask.cs" />
|
||||
<Compile Include="Shapes\AuditTrailShapes.cs" />
|
||||
<Compile Include="ViewModels\AuditTrailCategorySettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\AuditTrailEventSettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\AuditTrailTrimmingSettingsViewModel.cs" />
|
||||
@@ -175,7 +189,7 @@
|
||||
<Compile Include="Providers\ContentDefinition\IContentDefinitionEventHandler.cs" />
|
||||
<Compile Include="Providers\Content\AuditTrailEventHandler.cs" />
|
||||
<Compile Include="Helpers\EventDataHelper.cs" />
|
||||
<Compile Include="Models\AuditTrailFilterParameters.cs" />
|
||||
<Compile Include="Services\Models\AuditTrailFilterParameters.cs" />
|
||||
<Compile Include="Providers\Role\IRoleEventHandler.cs" />
|
||||
<Compile Include="Providers\Role\RoleEventHandler.cs" />
|
||||
<Compile Include="Providers\Role\RoleAuditTrailEventProvider.cs" />
|
||||
@@ -194,18 +208,18 @@
|
||||
<Compile Include="Services\IEventDataSerializer.cs" />
|
||||
<Compile Include="ViewModels\AuditTrailDetailsViewModel.cs" />
|
||||
<Compile Include="Providers\Content\GlobalContentHandler.cs" />
|
||||
<Compile Include="Models\AuditTrailEventDescriptor.cs" />
|
||||
<Compile Include="Services\Models\AuditTrailEventDescriptor.cs" />
|
||||
<Compile Include="Services\Models\AuditTrailCategoryDescriptor.cs" />
|
||||
<Compile Include="Models\DescribeContext.cs" />
|
||||
<Compile Include="Models\DescribeFor.cs" />
|
||||
<Compile Include="Models\AuditTrailContext.cs" />
|
||||
<Compile Include="Models\AuditTrailCreateContext.cs" />
|
||||
<Compile Include="Services\Models\DescribeContext.cs" />
|
||||
<Compile Include="Services\Models\DescribeFor.cs" />
|
||||
<Compile Include="Services\Models\AuditTrailContext.cs" />
|
||||
<Compile Include="Services\Models\AuditTrailCreateContext.cs" />
|
||||
<Compile Include="Services\AuditTrailEventProviderBase.cs" />
|
||||
<Compile Include="Providers\Content\ContentAuditTrailEventProvider.cs" />
|
||||
<Compile Include="Services\IAuditTrailEventHandler.cs" />
|
||||
<Compile Include="Services\IAuditTrailEventProvider.cs" />
|
||||
<Compile Include="ViewModels\AuditTrailFilterViewModel.cs" />
|
||||
<Compile Include="Models\AuditTrailOrderBy.cs" />
|
||||
<Compile Include="ViewModels\CommonAuditTrailFilterViewModel.cs" />
|
||||
<Compile Include="Services\Models\AuditTrailOrderBy.cs" />
|
||||
<Compile Include="ViewModels\AuditTrailViewModel.cs" />
|
||||
<Compile Include="Migrations.cs" />
|
||||
<Compile Include="Models\AuditTrailEventRecord.cs" />
|
||||
|
@@ -1,10 +1,11 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.AuditTrail.Providers.Content {
|
||||
public class AuditTrailEventHandler : IAuditTrailEventHandler {
|
||||
public void Create(AuditTrailCreateContext context) {
|
||||
public class ContentAuditTrailEventHandler : AuditTrailEventHandlerBase {
|
||||
public override void Create(AuditTrailCreateContext context) {
|
||||
var content = context.Properties.ContainsKey("Content") ? (IContent)context.Properties["Content"] : default(IContent);
|
||||
var auditTrailPart = content != null ? content.As<AuditTrailPart>() : default(AuditTrailPart);
|
||||
|
||||
|
@@ -1,14 +1,29 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Orchard.AuditTrail.Helpers;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.AuditTrail.Providers.Content {
|
||||
public class ContentAuditTrailEventProvider : AuditTrailEventProviderBase {
|
||||
private readonly IContentManager _contentManager;
|
||||
public ContentAuditTrailEventProvider(IContentManager contentManager) {
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
public const string Created = "Created";
|
||||
public const string Saved = "Saved";
|
||||
public const string Published = "Published";
|
||||
public const string Unpublished = "Unpublished";
|
||||
public const string Removed = "Removed";
|
||||
|
||||
public static Filters CreateFilters(int contentId) {
|
||||
return new Filters {
|
||||
{"content", contentId.ToString(CultureInfo.InvariantCulture)}
|
||||
};
|
||||
}
|
||||
|
||||
public override void Describe(DescribeContext context) {
|
||||
context.For("Content", T("Content"))
|
||||
.Event(this, Created, T("Created"), T("Content was created."), enableByDefault: true)
|
||||
@@ -16,6 +31,25 @@ namespace Orchard.AuditTrail.Providers.Content {
|
||||
.Event(this, Published, T("Published"), T("Content was published."), enableByDefault: true)
|
||||
.Event(this, Unpublished, T("Unpublished"), T("Content was unpublished."), enableByDefault: true)
|
||||
.Event(this, Removed, T("Removed"), T("Content was deleted."), enableByDefault: true);
|
||||
|
||||
context.QueryFilter(QueryFilter);
|
||||
context.DisplayFilter(DisplayFilter);
|
||||
}
|
||||
|
||||
private void QueryFilter(QueryFilterContext context) {
|
||||
if (!context.Filters.ContainsKey("content"))
|
||||
return;
|
||||
|
||||
var contentId = context.Filters["content"].ToInt32();
|
||||
context.Query = context.Query.Where(x => x.EventFilterKey == "content" && x.EventFilterData == contentId.ToString());
|
||||
}
|
||||
|
||||
private void DisplayFilter(DisplayFilterContext context) {
|
||||
var contentItemId = context.Filters.Get("content").ToInt32();
|
||||
var contentItem = contentItemId != null ? _contentManager.Get(contentItemId.Value, VersionOptions.Latest) : default(ContentItem);
|
||||
var filterDisplay = context.ShapeFactory.AuditTrailFilter__ContentItem(ContentItem: contentItem);
|
||||
|
||||
context.FilterLayout.TripleSecond.Add(filterDisplay);
|
||||
}
|
||||
}
|
||||
}
|
@@ -56,7 +56,13 @@ namespace Orchard.AuditTrail.Providers.Content {
|
||||
eventData["PreviousContentItemVersionId"] = previousContentItemVersion.Id;
|
||||
}
|
||||
|
||||
_auditTrailManager.CreateRecord<ContentAuditTrailEventProvider>(eventName, _wca.GetContext().CurrentUser, properties, eventData, eventFilterKey: "content", eventFilterData: content.Id.ToString(CultureInfo.InvariantCulture));
|
||||
_auditTrailManager.CreateRecord<ContentAuditTrailEventProvider>(
|
||||
eventName,
|
||||
_wca.GetContext().CurrentUser,
|
||||
properties,
|
||||
eventData,
|
||||
eventFilterKey: "content",
|
||||
eventFilterData: content.Id.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.Providers.ContentDefinition {
|
||||
public class ContentPartAuditTrailEventProvider : AuditTrailEventProviderBase {
|
||||
|
@@ -1,8 +1,18 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Orchard.AuditTrail.Helpers;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
|
||||
namespace Orchard.AuditTrail.Providers.ContentDefinition {
|
||||
public class ContentTypeAuditTrailEventProvider : AuditTrailEventProviderBase {
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
|
||||
public ContentTypeAuditTrailEventProvider(IContentDefinitionManager contentDefinitionManager) {
|
||||
_contentDefinitionManager = contentDefinitionManager;
|
||||
}
|
||||
|
||||
public const string Created = "Created";
|
||||
public const string Removed = "Removed";
|
||||
public const string PartAdded = "PartAdded";
|
||||
@@ -18,6 +28,26 @@ namespace Orchard.AuditTrail.Providers.ContentDefinition {
|
||||
.Event(this, PartRemoved, T("Part removed"), T("Content Part was removed."), enableByDefault: true)
|
||||
.Event(this, TypeSettingsUpdated, T("Type Settings updated"), T("Content Type settings were updated."), enableByDefault: true)
|
||||
.Event(this, PartSettingsUpdated, T("Part Settings updated"), T("Content Part settings were updated."), enableByDefault: true);
|
||||
|
||||
context.QueryFilter(QueryFilter);
|
||||
context.DisplayFilter(DisplayFilter);
|
||||
}
|
||||
|
||||
private void QueryFilter(QueryFilterContext context) {
|
||||
var contentType = context.Filters.Get("contenttype");
|
||||
|
||||
if(String.IsNullOrWhiteSpace(contentType))
|
||||
return;
|
||||
|
||||
context.Query = context.Query.Where(x => x.EventFilterKey == "contenttype" && x.EventFilterData == contentType);
|
||||
}
|
||||
|
||||
private void DisplayFilter(DisplayFilterContext context) {
|
||||
var filterDisplay = context.ShapeFactory.AuditTrailFilter__ContentType(
|
||||
ContentType: context.Filters.Get("contenttype"),
|
||||
ContentTypes: _contentDefinitionManager.ListTypeDefinitions().OrderBy(x => x.DisplayName).ToArray());
|
||||
|
||||
context.FilterLayout.TripleFirst.Add(filterDisplay);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.Providers.Role {
|
||||
public class RoleAuditTrailEventProvider : AuditTrailEventProviderBase {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.Providers.User {
|
||||
public class UserAuditTrailEventProvider : AuditTrailEventProviderBase {
|
||||
|
@@ -0,0 +1,9 @@
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.Services {
|
||||
public class AuditTrailEventHandlerBase : Component, IAuditTrailEventHandler {
|
||||
public virtual void Create(AuditTrailCreateContext context) {}
|
||||
public virtual void Filter(QueryFilterContext context) {}
|
||||
public virtual void DisplayFilter(DisplayFilterContext context) { }
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.Services {
|
||||
public abstract class AuditTrailEventProviderBase : Component, IAuditTrailEventProvider {
|
||||
|
@@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using Orchard.AuditTrail.Helpers;
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Collections;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Data;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.Security;
|
||||
using Orchard.Services;
|
||||
using Orchard.Settings;
|
||||
@@ -22,6 +23,7 @@ namespace Orchard.AuditTrail.Services {
|
||||
private readonly ICacheManager _cacheManager;
|
||||
private readonly ISiteService _siteService;
|
||||
private readonly ISignals _signals;
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
|
||||
public AuditTrailManager(
|
||||
IRepository<AuditTrailEventRecord> auditTrailRepository,
|
||||
@@ -31,7 +33,8 @@ namespace Orchard.AuditTrail.Services {
|
||||
IEventDataSerializer serializer,
|
||||
ICacheManager cacheManager,
|
||||
ISiteService siteService,
|
||||
ISignals signals) {
|
||||
ISignals signals,
|
||||
IShapeFactory shapeFactory) {
|
||||
|
||||
_auditTrailRepository = auditTrailRepository;
|
||||
_providers = providers;
|
||||
@@ -41,24 +44,40 @@ namespace Orchard.AuditTrail.Services {
|
||||
_cacheManager = cacheManager;
|
||||
_siteService = siteService;
|
||||
_signals = signals;
|
||||
_shapeFactory = shapeFactory;
|
||||
}
|
||||
|
||||
public IPageOfItems<AuditTrailEventRecord> GetRecords(int page, int pageSize, AuditTrailFilterParameters filter = null, AuditTrailOrderBy orderBy = AuditTrailOrderBy.DateDescending) {
|
||||
public IPageOfItems<AuditTrailEventRecord> GetRecords(
|
||||
int page,
|
||||
int pageSize,
|
||||
Filters filters = null,
|
||||
AuditTrailOrderBy orderBy = AuditTrailOrderBy.DateDescending) {
|
||||
|
||||
var query = _auditTrailRepository.Table;
|
||||
|
||||
|
||||
if (filter != null) {
|
||||
if (!String.IsNullOrWhiteSpace(filter.FilterKey)) query = query.Where(x => x.EventFilterKey == filter.FilterKey);
|
||||
if (!String.IsNullOrWhiteSpace(filter.FilterValue)) query = query.Where(x => x.EventFilterData == filter.FilterValue);
|
||||
if (!String.IsNullOrWhiteSpace(filter.UserName)) query = query.Where(x => x.UserName == filter.UserName);
|
||||
if (filter.From != null) query = query.Where(x => x.CreatedUtc >= filter.From);
|
||||
if (filter.To != null) query = query.Where(x => x.CreatedUtc <= filter.To);
|
||||
if (filters != null) {
|
||||
var filterContext = new QueryFilterContext(query, filters);
|
||||
|
||||
// Invoke event handlers.
|
||||
_auditTrailEventHandlers.Filter(filterContext);
|
||||
|
||||
// Give each provider a chance to modify the query.
|
||||
var providersContext = DescribeProviders();
|
||||
foreach (var queryFilter in providersContext.QueryFilters) {
|
||||
queryFilter(filterContext);
|
||||
}
|
||||
|
||||
query = filterContext.Query;
|
||||
}
|
||||
|
||||
switch (orderBy) {
|
||||
case AuditTrailOrderBy.EventAscending:
|
||||
query = query.OrderBy(x => x.Event).ThenByDescending(x => x.Id);
|
||||
break;
|
||||
case AuditTrailOrderBy.CategoryAscending:
|
||||
query = query.OrderBy(x => x.Category).ThenByDescending(x => x.Id);
|
||||
break;
|
||||
default:
|
||||
query = query.OrderByDescending(x => x.CreatedUtc).ThenByDescending(x => x.Id);
|
||||
break;
|
||||
@@ -79,6 +98,27 @@ namespace Orchard.AuditTrail.Services {
|
||||
return _auditTrailRepository.Get(id);
|
||||
}
|
||||
|
||||
public dynamic BuildFilterDisplays(Filters filters) {
|
||||
var layout = (dynamic)_shapeFactory.Create("AuditTrailFilters", Arguments.From(new {
|
||||
TripleFirst = _shapeFactory.Create("AuditTrailFilters_TripleFirst"),
|
||||
TripleSecond = _shapeFactory.Create("AuditTrailFilters_TripleSecond"),
|
||||
TripleThird = _shapeFactory.Create("AuditTrailFilters_TripleThird")
|
||||
}));
|
||||
var displayContext = new DisplayFilterContext(_shapeFactory, filters, layout);
|
||||
|
||||
// Invoke event handlers.
|
||||
_auditTrailEventHandlers.DisplayFilter(displayContext);
|
||||
|
||||
// Give each provider a chance to provide a filter display.
|
||||
var providersContext = DescribeProviders();
|
||||
|
||||
foreach (var action in providersContext.FilterDisplays) {
|
||||
action(displayContext);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
public AuditTrailEventRecordResult CreateRecord<T>(string eventName, IUser user, IDictionary<string, object> properties = null, IDictionary<string, object> eventData = null, string eventFilterKey = null, string eventFilterData = null) where T:IAuditTrailEventProvider {
|
||||
var eventDescriptor = DescribeEvent<T>(eventName);
|
||||
if(!IsEventEnabled(eventDescriptor))
|
||||
@@ -129,9 +169,14 @@ namespace Orchard.AuditTrail.Services {
|
||||
}
|
||||
|
||||
public IEnumerable<AuditTrailCategoryDescriptor> DescribeCategories() {
|
||||
var context = DescribeProviders();
|
||||
return context.Describe();
|
||||
}
|
||||
|
||||
public DescribeContext DescribeProviders() {
|
||||
var context = new DescribeContext();
|
||||
_providers.Describe(context);
|
||||
return context.Describe();
|
||||
return context;
|
||||
}
|
||||
|
||||
public AuditTrailEventDescriptor DescribeEvent<T>(string eventName) where T:IAuditTrailEventProvider {
|
||||
|
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Orchard.AuditTrail.Helpers;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
using Orchard.Localization.Services;
|
||||
|
||||
namespace Orchard.AuditTrail.Services {
|
||||
public class CommonAuditTrailEventHandler : AuditTrailEventHandlerBase {
|
||||
private readonly Lazy<IAuditTrailManager> _auditTrailManager;
|
||||
private readonly IDateServices _dateServices;
|
||||
|
||||
public CommonAuditTrailEventHandler(Lazy<IAuditTrailManager> auditTrailManager, IDateServices dateServices) {
|
||||
_auditTrailManager = auditTrailManager;
|
||||
_dateServices = dateServices;
|
||||
}
|
||||
|
||||
public override void Filter(QueryFilterContext context) {
|
||||
// Common filters (username, from and to).
|
||||
var userName = context.Filters.Get("username");
|
||||
var fromDate = context.Filters.Get("from.Date");
|
||||
var fromTime = context.Filters.Get("from.Time");
|
||||
var toDate = context.Filters.Get("to.Date");
|
||||
var toTime = context.Filters.Get("to.Time");
|
||||
var from = _dateServices.ConvertFromLocalString(fromDate, fromTime).Earliest();
|
||||
var to = _dateServices.ConvertFromLocalString(toDate, toTime).Latest();
|
||||
var query = context.Query;
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(userName)) query = query.Where(x => x.UserName == userName);
|
||||
if (from != null) query = query.Where(x => x.CreatedUtc >= from);
|
||||
if (to != null) query = query.Where(x => x.CreatedUtc <= to);
|
||||
|
||||
context.Query = query;
|
||||
}
|
||||
|
||||
public override void DisplayFilter(DisplayFilterContext context) {
|
||||
// Common filters (username, from and to).
|
||||
var userName = context.Filters.Get("username");
|
||||
var fromDate = context.Filters.Get("from.Date");
|
||||
var toDate = context.Filters.Get("to.Date");
|
||||
var userNameFilterDisplay = context.ShapeFactory.AuditTrailFilter__Common__User(UserName: userName);
|
||||
var dateFilterDisplay = context.ShapeFactory.AuditTrailFilter__Common__Date(
|
||||
From: new DateTimeEditor {Date = fromDate, ShowDate = true},
|
||||
To: new DateTimeEditor {Date = toDate, ShowDate = true});
|
||||
|
||||
context.FilterLayout.TripleFirst.Add(dateFilterDisplay);
|
||||
context.FilterLayout.TripleSecond.Add(userNameFilterDisplay);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,8 +1,10 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.Events;
|
||||
|
||||
namespace Orchard.AuditTrail.Services {
|
||||
public interface IAuditTrailEventHandler : IEventHandler {
|
||||
void Create(AuditTrailCreateContext context);
|
||||
void Filter(QueryFilterContext context);
|
||||
void DisplayFilter(DisplayFilterContext context);
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.Events;
|
||||
|
||||
namespace Orchard.AuditTrail.Services {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
using Orchard.Collections;
|
||||
using Orchard.Security;
|
||||
|
||||
@@ -12,9 +13,9 @@ namespace Orchard.AuditTrail.Services {
|
||||
/// <param name="page">The page number to get records from.</param>
|
||||
/// <param name="pageSize">The number of records to get.</param>
|
||||
/// <param name="orderBy">The value to order by.</param>
|
||||
/// <param name="filter">Optional. An object to filter the records on.</param>
|
||||
/// <param name="filters">Optional. An object to filter the records on.</param>
|
||||
/// <returns>Returns a page of event records.</returns>
|
||||
IPageOfItems<AuditTrailEventRecord> GetRecords(int page, int pageSize, AuditTrailFilterParameters filter = null, AuditTrailOrderBy orderBy = AuditTrailOrderBy.DateDescending);
|
||||
IPageOfItems<AuditTrailEventRecord> GetRecords(int page, int pageSize, Filters filters = null, AuditTrailOrderBy orderBy = AuditTrailOrderBy.DateDescending);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a single event record by ID.
|
||||
@@ -22,6 +23,13 @@ namespace Orchard.AuditTrail.Services {
|
||||
/// <param name="id">The event record ID.</param>
|
||||
/// <returns>Returns a single event record by ID.</returns>
|
||||
AuditTrailEventRecord GetRecord(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a shape tree of filter displays.
|
||||
/// </summary>
|
||||
/// <param name="filters">Input for each filter builder.</param>
|
||||
/// <returns>Returns a tree of shapes.</returns>
|
||||
dynamic BuildFilterDisplays(Filters filters);
|
||||
|
||||
/// <summary>
|
||||
/// Records an audit trail event.
|
||||
@@ -42,6 +50,11 @@ namespace Orchard.AuditTrail.Services {
|
||||
/// <returns>Returns a list of audit trail category descriptors.</returns>
|
||||
IEnumerable<AuditTrailCategoryDescriptor> DescribeCategories();
|
||||
|
||||
/// <summary>
|
||||
/// Describes all audit trail event providers.
|
||||
/// </summary>
|
||||
DescribeContext DescribeProviders();
|
||||
|
||||
/// <summary>
|
||||
/// Describes a single audit trail event.
|
||||
/// </summary>
|
||||
@@ -62,5 +75,6 @@ namespace Orchard.AuditTrail.Services {
|
||||
/// </summary>
|
||||
/// <returns>Returns the deleted records.</returns>
|
||||
IEnumerable<AuditTrailEventRecord> Trim(TimeSpan threshold);
|
||||
|
||||
}
|
||||
}
|
@@ -1,7 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class AuditTrailCategoryDescriptor {
|
||||
public string Category { get; set; }
|
||||
public LocalizedString Name { get; set; }
|
||||
|
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class AuditTrailContext {
|
||||
public AuditTrailContext() {
|
||||
EventData = new Dictionary<string, object>();
|
@@ -1,4 +1,4 @@
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class AuditTrailCreateContext : AuditTrailContext {
|
||||
public string Comment { get; set; }
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class AuditTrailEventDescriptor {
|
||||
public AuditTrailCategoryDescriptor CategoryDescriptor { get; set; }
|
||||
public string Event { get; set; }
|
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using Orchard.AuditTrail.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class AuditTrailFilterParameters {
|
||||
public string FilterKey { get; set; }
|
||||
public string FilterValue { get; set; }
|
||||
public Filters Filters { get; set; }
|
||||
public string UserName { get; set; }
|
||||
public DateTime? From { get; set; }
|
||||
public DateTime? To { get; set; }
|
@@ -1,6 +1,7 @@
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public enum AuditTrailOrderBy {
|
||||
DateDescending,
|
||||
CategoryAscending,
|
||||
EventAscending
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class DescribeContext {
|
||||
private readonly IDictionary<string, DescribeFor> _describes = new Dictionary<string, DescribeFor>();
|
||||
private readonly IList<Action<QueryFilterContext>> _queryFilters = new List<Action<QueryFilterContext>>();
|
||||
private readonly IList<Action<DisplayFilterContext>> _filterDisplays = new List<Action<DisplayFilterContext>>();
|
||||
|
||||
public IEnumerable<Action<QueryFilterContext>> QueryFilters {
|
||||
get { return _queryFilters; }
|
||||
}
|
||||
|
||||
public IEnumerable<Action<DisplayFilterContext>> FilterDisplays {
|
||||
get { return _filterDisplays; }
|
||||
}
|
||||
|
||||
public IEnumerable<AuditTrailCategoryDescriptor> Describe() {
|
||||
var query =
|
||||
from d in _describes.Values
|
||||
select new AuditTrailCategoryDescriptor {
|
||||
Category = d.Category,
|
||||
Name = d.Name,
|
||||
Events = d.Events
|
||||
};
|
||||
|
||||
return query.ToArray();
|
||||
}
|
||||
|
||||
public DescribeFor For(string category, LocalizedString name) {
|
||||
DescribeFor describeFor;
|
||||
if (!_describes.TryGetValue(category, out describeFor)) {
|
||||
describeFor = new DescribeFor(category, name);
|
||||
_describes[category] = describeFor;
|
||||
}
|
||||
return describeFor;
|
||||
}
|
||||
|
||||
public DescribeContext QueryFilter(Action<QueryFilterContext> queryAction) {
|
||||
_queryFilters.Add(queryAction);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DescribeContext DisplayFilter(Action<DisplayFilterContext> displayFilter) {
|
||||
_filterDisplays.Add(displayFilter);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.AuditTrail.Helpers;
|
||||
using Orchard.AuditTrail.Services;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.AuditTrail.Models {
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class DescribeFor {
|
||||
private readonly IList<AuditTrailEventDescriptor> _events = new List<AuditTrailEventDescriptor>();
|
||||
|
@@ -0,0 +1,15 @@
|
||||
using Orchard.DisplayManagement;
|
||||
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class DisplayFilterContext {
|
||||
public DisplayFilterContext(IShapeFactory shapeFactory, Filters filters, dynamic filterLayout) {
|
||||
ShapeFactory = shapeFactory;
|
||||
Filters = filters;
|
||||
FilterLayout = filterLayout;
|
||||
}
|
||||
|
||||
public dynamic ShapeFactory { get; set; }
|
||||
public Filters Filters { get; set; }
|
||||
public dynamic FilterLayout { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class Filters : Dictionary<string, string> {
|
||||
public static Filters From(NameValueCollection nameValues) {
|
||||
var filters = new Filters();
|
||||
|
||||
foreach (string nameValue in nameValues) {
|
||||
filters.Add(nameValue, nameValues[nameValue]);
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
public Filters AddFilter(string key, string value) {
|
||||
Add(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
using System.Linq;
|
||||
using Orchard.AuditTrail.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.Services.Models {
|
||||
public class QueryFilterContext {
|
||||
public QueryFilterContext(IQueryable<AuditTrailEventRecord> query, Filters filters) {
|
||||
Query = query;
|
||||
Filters = filters;
|
||||
}
|
||||
|
||||
public IQueryable<AuditTrailEventRecord> Query { get; set; }
|
||||
public Filters Filters { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
using System.IO;
|
||||
using Orchard.DisplayManagement;
|
||||
|
||||
namespace Orchard.AuditTrail.Shapes {
|
||||
public class AuditTrailShapes : IDependency {
|
||||
[Shape]
|
||||
public void AuditTrailFilters(dynamic Shape, dynamic Display, TextWriter Output) {
|
||||
DispayChildren(Shape, Display, Output);
|
||||
}
|
||||
|
||||
[Shape]
|
||||
public void AuditTrailFilters_TripleFirst(dynamic Shape, dynamic Display, TextWriter Output) {
|
||||
DispayChildren(Shape, Display, Output);
|
||||
}
|
||||
|
||||
[Shape]
|
||||
public void AuditTrailFilters_TripleSecond(dynamic Shape, dynamic Display, TextWriter Output) {
|
||||
DispayChildren(Shape, Display, Output);
|
||||
}
|
||||
|
||||
[Shape]
|
||||
public void AuditTrailFilters_TripleThird(dynamic Shape, dynamic Display, TextWriter Output) {
|
||||
DispayChildren(Shape, Display, Output);
|
||||
}
|
||||
|
||||
private void DispayChildren(dynamic shape, dynamic display, TextWriter output) {
|
||||
foreach (var child in shape) {
|
||||
output.Write(display(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,6 +2,16 @@
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.audit-trail-filter fieldset label {
|
||||
display: inline-block;
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
.audit-trail-filter fieldset label.inline {
|
||||
display: inline;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.audit-trail-list .info {
|
||||
line-height: 25px;
|
||||
}
|
||||
@@ -20,4 +30,4 @@
|
||||
|
||||
.audit-trail-site-settings table th.event-enabled {
|
||||
width: 60px;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,285 @@
|
||||
.table, .row, .cell {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.table > .row {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table.fixed > .row {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: block;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.cell {
|
||||
display: block;
|
||||
float: left;
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.row > .cell:last-of-type {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.row > .cell:first-of-type {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/* Opt-in outside padding */
|
||||
.row-pad {
|
||||
padding: 20px 0 20px 20px;
|
||||
}
|
||||
|
||||
.row-pad .cell:last-of-type {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.span-1-1 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.span-1-2 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.span-1-3 {
|
||||
width: 33.33%;
|
||||
}
|
||||
|
||||
.span-1-4 {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.span-1-5 {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.span-1-6 {
|
||||
width: 16.66%;
|
||||
}
|
||||
|
||||
.span-1-7 {
|
||||
width: 14.28%;
|
||||
}
|
||||
|
||||
.span-1-8 {
|
||||
width: 12.5%;
|
||||
}
|
||||
|
||||
.span-1-9 {
|
||||
width: 11.11%;
|
||||
}
|
||||
|
||||
.span-1-10 {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.span-1-11 {
|
||||
width: 9.09%;
|
||||
}
|
||||
|
||||
.span-1-12 {
|
||||
width: 8.33%;
|
||||
}
|
||||
|
||||
.span-2-3 {
|
||||
width: 66.66%;
|
||||
}
|
||||
|
||||
.span-2-4 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.span-2-5 {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.span-2-6 {
|
||||
width: 33.33%;
|
||||
}
|
||||
|
||||
.span-2-8 {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.span-2-10 {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.span-2-12 {
|
||||
width: 16.66%;
|
||||
}
|
||||
|
||||
.span-3-4 {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.span-3-5 {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.span-3-6 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.span-3-8 {
|
||||
width: 37.5%;
|
||||
}
|
||||
|
||||
.span-3-10 {
|
||||
width: 33.33%;
|
||||
}
|
||||
|
||||
.span-3-12 {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.span-4-5 {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.span-4-6 {
|
||||
width: 66.66%;
|
||||
}
|
||||
|
||||
.span-4-8 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.span-4-10 {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.span-4-12 {
|
||||
width: 33.33%;
|
||||
}
|
||||
|
||||
.span-5-6 {
|
||||
width: 83.33%;
|
||||
}
|
||||
|
||||
.span-5-8 {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.span-5-10 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.span-5-12 {
|
||||
width: 41.66%;
|
||||
}
|
||||
|
||||
.span-6-8 {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.span-6-10 {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.span-6-12 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.span-7-8 {
|
||||
width: 87.5%;
|
||||
}
|
||||
|
||||
.span-7-10 {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.span-7-12 {
|
||||
width: 58.33%;
|
||||
}
|
||||
|
||||
.span-8-10 {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.span-8-12 {
|
||||
width: 66.66%;
|
||||
}
|
||||
|
||||
.span-9-10 {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.span-9-12 {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.span-10-12 {
|
||||
width: 83.33%;
|
||||
}
|
||||
|
||||
.span-11-12 {
|
||||
width: 91.66%;
|
||||
}
|
||||
|
||||
/* Bootstrap compatible spans */
|
||||
.span-1 { width: 8.33%; }
|
||||
.span-2 { width: 16.66%; }
|
||||
.span-3 { width: 25%; }
|
||||
.span-4 { width: 33.33%; }
|
||||
.span-5 { width: 41.66%; }
|
||||
.span-6 { width: 50%; }
|
||||
.span-7 { width: 58.33%; }
|
||||
.span-8 { width: 66.66%; }
|
||||
.span-9 { width: 75%; }
|
||||
.span-10 { width: 83.33%; }
|
||||
.span-11 { width: 91.66%; }
|
||||
.span-12 { width: 100%; }
|
||||
|
||||
|
||||
/* RESPONSIVENESS */
|
||||
|
||||
/* Large desktop */
|
||||
@media (min-width: 1200px) {
|
||||
.table.fixed > .row {
|
||||
width: 1170px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Default */
|
||||
@media (min-width: 980px) and (max-width: 1199px) {
|
||||
.table.fixed > .row {
|
||||
width: 960px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Portrait tablet to landscape and desktop */
|
||||
@media (min-width: 768px) and (max-width: 979px) {
|
||||
.table.fixed > .row {
|
||||
width: 724px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Landscape phone to portrait tablet */
|
||||
@media (max-width: 767px) {
|
||||
.table.fixed > .row {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Landscape phones and down */
|
||||
@media (max-width: 480px) {
|
||||
.table.fixed > .row {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.ViewModels {
|
||||
public class AuditTrailDetailsViewModel {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.ViewModels {
|
||||
public class AuditTrailEventSummaryViewModel {
|
||||
|
@@ -1,12 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.AuditTrail.Services.Models;
|
||||
|
||||
namespace Orchard.AuditTrail.ViewModels {
|
||||
public class AuditTrailViewModel {
|
||||
public AuditTrailViewModel() {
|
||||
Filter = new AuditTrailFilterViewModel();
|
||||
}
|
||||
|
||||
public AuditTrailFilterViewModel Filter { get; set; }
|
||||
public dynamic FilterLayout { get; set; }
|
||||
public AuditTrailOrderBy OrderBy { get; set; }
|
||||
public IEnumerable<AuditTrailEventSummaryViewModel> Records { get; set; }
|
||||
public dynamic List { get; set; }
|
||||
public dynamic Pager { get; set; }
|
||||
|
@@ -1,17 +1,14 @@
|
||||
using Orchard.AuditTrail.Models;
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
|
||||
namespace Orchard.AuditTrail.ViewModels {
|
||||
public class AuditTrailFilterViewModel {
|
||||
public AuditTrailFilterViewModel() {
|
||||
public class CommonAuditTrailFilterViewModel {
|
||||
public CommonAuditTrailFilterViewModel() {
|
||||
From = new DateTimeEditor { ShowDate = true, ShowTime = false};
|
||||
To = new DateTimeEditor { ShowDate = true, ShowTime = false };
|
||||
}
|
||||
public string FilterKey { get; set; }
|
||||
public string FilterValue { get; set; }
|
||||
|
||||
public string UserName { get; set; }
|
||||
public DateTimeEditor From { get; set; }
|
||||
public DateTimeEditor To { get; set; }
|
||||
public AuditTrailOrderBy OrderBy { get; set; }
|
||||
}
|
||||
}
|
@@ -1,36 +1,47 @@
|
||||
@using Orchard.AuditTrail.Models
|
||||
@using Orchard.AuditTrail.Services.Models
|
||||
@model Orchard.AuditTrail.ViewModels.AuditTrailViewModel
|
||||
@{
|
||||
Style.Include("custom-grid.css");
|
||||
Style.Include("admin.css");
|
||||
var from = Model.Filter.From;
|
||||
var to = Model.Filter.To;
|
||||
var orderBy = Model.Filter.OrderBy;
|
||||
var orderBy = Model.OrderBy;
|
||||
var orderByItems = new List<SelectListItem> {
|
||||
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},
|
||||
new SelectListItem {Text = T("Date (desc)").Text, Value = AuditTrailOrderBy.DateDescending.ToString(), Selected = Model.OrderBy == AuditTrailOrderBy.DateDescending},
|
||||
new SelectListItem {Text = T("Category (asc)").Text, Value = AuditTrailOrderBy.CategoryAscending.ToString(), Selected = Model.OrderBy == AuditTrailOrderBy.CategoryAscending},
|
||||
new SelectListItem {Text = T("Event (asc)").Text, Value = AuditTrailOrderBy.EventAscending.ToString(), Selected = Model.OrderBy == AuditTrailOrderBy.EventAscending},
|
||||
};
|
||||
|
||||
Layout.Title = T("Audit Trail");
|
||||
}
|
||||
<section class="audit-trail-filter">
|
||||
@using (Html.BeginForm("Index", "Admin", new { area = "Orchard.AuditTrail" }, FormMethod.Get)) {
|
||||
<fieldset class="bulk-actions">
|
||||
@Html.Hidden("filterkey", Model.Filter.FilterKey)
|
||||
@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("From:"))
|
||||
@Html.EditorFor(m => from)
|
||||
@Html.LabelFor(m => to, T("To:"))
|
||||
@Html.EditorFor(m => to)
|
||||
@Html.LabelFor(m => orderBy, T("Ordered by:"))
|
||||
@Html.DropDownListFor(m => orderBy, orderByItems)
|
||||
<button type="submit" value="yes">@T("Apply")</button>
|
||||
</fieldset>
|
||||
<div class="table">
|
||||
<div class="row">
|
||||
<div class="cell span-12">
|
||||
@Display(Model.FilterLayout)
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="cell span-4">
|
||||
@Display(Model.FilterLayout.TripleFirst)
|
||||
<fieldset>
|
||||
@Html.LabelFor(m => orderBy, T("Ordered by:"))
|
||||
@Html.DropDownListFor(m => orderBy, orderByItems)
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="cell span-4">
|
||||
@Display(Model.FilterLayout.TripleSecond)
|
||||
</div>
|
||||
<div class="cell span-4">
|
||||
@Display(Model.FilterLayout.TripleThird)
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="cell span-12">
|
||||
<button type="submit" value="yes">@T("Apply")</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="manage">
|
||||
<a id="auditTrailSettings" href="#" class="button primaryAction">@T("Settings")</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="audit-trail-list">
|
||||
@if (!Model.Records.Any()) {
|
||||
|
@@ -0,0 +1,11 @@
|
||||
@using Orchard.Core.Common.ViewModels
|
||||
@{
|
||||
var from = (DateTimeEditor)Model.From;
|
||||
var to = (DateTimeEditor)Model.To;
|
||||
}
|
||||
<fieldset>
|
||||
@Html.Label("from.Date", T("From:").Text)
|
||||
@Html.EditorFor(m => from)
|
||||
@Html.Label("to.Date", T("To:").Text, new { @class = "inline" })
|
||||
@Html.EditorFor(m => to)
|
||||
</fieldset>
|
@@ -0,0 +1,4 @@
|
||||
<fieldset>
|
||||
@Html.Label("username", T("User:").Text)
|
||||
@Html.TextBox("username", (string)Model.UserName, new { @class = "text" })
|
||||
</fieldset>
|
@@ -0,0 +1,11 @@
|
||||
@using Orchard.ContentManagement
|
||||
@{
|
||||
var contentItem = (ContentItem)Model.ContentItem;
|
||||
}
|
||||
@if (contentItem != null) {
|
||||
<fieldset>
|
||||
@Html.Label("contentitem", T("Content Item:").Text)
|
||||
@Html.ItemEditLink(contentItem)
|
||||
@Html.Hidden("content", contentItem.Id)
|
||||
</fieldset>
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
@using Orchard.ContentManagement.MetaData.Models
|
||||
@{
|
||||
var contentTypes = (IList<ContentTypeDefinition>) Model.ContentTypes;
|
||||
var currentContentType = (string)Model.ContentType;
|
||||
var listItems = contentTypes.Select(x => new SelectListItem {Text = x.DisplayName, Value = x.Name, Selected = x.Name == currentContentType});
|
||||
}
|
||||
<fieldset>
|
||||
@Html.Label("contenttype", T("Content Type:").Text)
|
||||
@Html.DropDownList("contenttype", listItems, "")
|
||||
</fieldset>
|
@@ -11,7 +11,7 @@
|
||||
@foreach (var category in Model.Categories) {
|
||||
<fieldset>
|
||||
<legend>@category.Name</legend>
|
||||
<input type="hidden" name="AuditTrailSiteSettingsPart.Categories[@i].Category" value="@category.Category" />
|
||||
<input type="hidden" name="AuditTrailSettingsPart.Categories[@i].Category" value="@category.Category" />
|
||||
<table class="items">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -25,12 +25,12 @@
|
||||
var checkboxId = String.Format("Event{0}{1}", i, j);
|
||||
<tr>
|
||||
<td>
|
||||
<input type="hidden" name="AuditTrailSiteSettingsPart.Categories[@i].Events[@j].Event" value="@evnt.Event" />
|
||||
<input type="hidden" name="AuditTrailSettingsPart.Categories[@i].Events[@j].Event" value="@evnt.Event" />
|
||||
@evnt.Name
|
||||
</td>
|
||||
<td>@evnt.Description</td>
|
||||
<td>
|
||||
<input type="checkbox" id="@checkboxId" name="AuditTrailSiteSettingsPart.Categories[@i].Events[@j].IsEnabled" value="@Boolean.TrueString" @if(evnt.IsEnabled){<text>checked="checked"</text>} />
|
||||
<input type="checkbox" id="@checkboxId" name="AuditTrailSettingsPart.Categories[@i].Events[@j].IsEnabled" value="@Boolean.TrueString" @if(evnt.IsEnabled){<text>checked="checked"</text>} />
|
||||
</td>
|
||||
</tr>
|
||||
j++;
|
||||
|
@@ -3,6 +3,6 @@
|
||||
}
|
||||
@if (contentId > 0) {
|
||||
<fieldset>
|
||||
@Html.ActionLink(T("View Audit Trail").Text, "Index", "Admin", new { filterkey = "content", filtervalue = contentId, area = "Orchard.AuditTrail" }, null)
|
||||
@Html.ActionLink(T("View Audit Trail").Text, "Index", "Admin", new { content = contentId, area = "Orchard.AuditTrail" }, null)
|
||||
</fieldset>
|
||||
}
|
@@ -48,7 +48,7 @@
|
||||
<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)
|
||||
@Html.ActionLink(T("Show more events").Text, "Index", "Admin", new { content = auditTrailPart.Id, page = 2, area = "Orchard.AuditTrail" }, null)
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
@@ -1 +1 @@
|
||||
<a href="@Url.Action("Index", "Admin", new { filterkey = "content", filtervalue = Model.ContentItem.Id, area = "Orchard.AuditTrail" })">@T("Audit Trail")</a>@T(" | ")
|
||||
<a href="@Url.Action("Index", "Admin", new { content = Model.ContentItem.Id, area = "Orchard.AuditTrail" })">@T("Audit Trail")</a>@T(" | ")
|
Reference in New Issue
Block a user