mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-04-05 21:01:35 +08:00
Reports module
- Stores service management reports - Use IReportsCoordinator to write message to the same report through multiple components - Views to display reports --HG-- branch : dev
This commit is contained in:
parent
f397d25d66
commit
a9dc5abd50
@ -82,11 +82,16 @@
|
||||
<Compile Include="Contents\ViewModels\EditItemViewModel.cs" />
|
||||
<Compile Include="Contents\ViewModels\ListContentsViewModel.cs" />
|
||||
<Compile Include="Contents\ViewModels\ListContentTypesViewModel.cs" />
|
||||
<Compile Include="Reports\AdminMenu.cs" />
|
||||
<Compile Include="Reports\Controllers\AdminController.cs" />
|
||||
<Compile Include="Reports\Routes.cs" />
|
||||
<Compile Include="Localization\Controllers\AdminController.cs" />
|
||||
<Compile Include="Localization\DataMigrations\LocalizationDataMigration.cs" />
|
||||
<Compile Include="Localization\ViewModels\ContentTranslationsViewModel.cs" />
|
||||
<Compile Include="Localization\Drivers\LocalizationDriver.cs" />
|
||||
<Compile Include="Navigation\DataMigrations\NavigationDataMigration.cs" />
|
||||
<Compile Include="Reports\ViewModels\DisplayReportViewModel.cs" />
|
||||
<Compile Include="Reports\ViewModels\ReportsAdminIndexViewModel.cs" />
|
||||
<Compile Include="Routable\Controllers\ItemController.cs" />
|
||||
<Compile Include="Routable\Drivers\RoutableDriver.cs" />
|
||||
<Compile Include="Routable\Handlers\RoutableHandler.cs" />
|
||||
@ -234,6 +239,9 @@
|
||||
<Content Include="Contents\Views\EditorTemplates\Items\Contents.Item.ascx" />
|
||||
<Content Include="Contents\Views\Item\Preview.aspx" />
|
||||
<Content Include="Contents\Views\Item\Display.aspx" />
|
||||
<Content Include="Reports\Module.txt" />
|
||||
<Content Include="Reports\Views\Admin\Display.aspx" />
|
||||
<Content Include="Reports\Views\Admin\Index.aspx" />
|
||||
<Content Include="Localization\Module.txt" />
|
||||
<Content Include="Localization\Views\Admin\Translate.ascx" />
|
||||
<Content Include="Localization\Views\DisplayTemplates\Parts\Localization.ContentTranslations.SummaryAdmin.ascx" />
|
||||
@ -300,6 +308,7 @@
|
||||
<Content Include="Contents\Views\Web.config" />
|
||||
<Content Include="Routable\Views\Web.config" />
|
||||
<Content Include="Localization\Views\Web.config" />
|
||||
<Content Include="Reports\Views\Web.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
|
||||
|
15
src/Orchard.Web/Core/Reports/AdminMenu.cs
Normal file
15
src/Orchard.Web/Core/Reports/AdminMenu.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Orchard.Localization;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.Core.Reports {
|
||||
public class AdminMenu : INavigationProvider {
|
||||
public Localizer T { get; set; }
|
||||
public string MenuName { get { return "admin"; } }
|
||||
|
||||
public void GetNavigation(NavigationBuilder builder) {
|
||||
builder.Add(T("Site Configuration"), "0",
|
||||
menu => menu.Add(T("Reports"), "0", item => item.Action("Index", "Admin", new { area = "Reports" }).Permission(StandardPermissions.AccessAdminPanel)));
|
||||
}
|
||||
}
|
||||
}
|
28
src/Orchard.Web/Core/Reports/Controllers/AdminController.cs
Normal file
28
src/Orchard.Web/Core/Reports/Controllers/AdminController.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Core.Reports.ViewModels;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
using Orchard.Reports.Services;
|
||||
|
||||
namespace Orchard.Core.Reports.Controllers {
|
||||
public class AdminController : Controller {
|
||||
private readonly IReportsManager _reportsManager;
|
||||
|
||||
public AdminController(IReportsManager reportsManager) {
|
||||
_reportsManager = reportsManager;
|
||||
}
|
||||
|
||||
public ActionResult Index() {
|
||||
var model = new ReportsAdminIndexViewModel { Reports = _reportsManager.GetReports().ToList() };
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
public ActionResult Display(int id) {
|
||||
var model = new DisplayReportViewModel { Report = _reportsManager.Get(id) };
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
11
src/Orchard.Web/Core/Reports/Module.txt
Normal file
11
src/Orchard.Web/Core/Reports/Module.txt
Normal file
@ -0,0 +1,11 @@
|
||||
name: Reports
|
||||
antiforgery: enabled
|
||||
author: The Orchard Team
|
||||
website: http://orchardproject.net
|
||||
version: 0.1
|
||||
orchardversion: 0.1.2010.0312
|
||||
description: The dashboard module is providing the reports screen of the application.
|
||||
features:
|
||||
Dashboard:
|
||||
Description: Reports management.
|
||||
Category: Core
|
33
src/Orchard.Web/Core/Reports/Routes.cs
Normal file
33
src/Orchard.Web/Core/Reports/Routes.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Orchard.Mvc.Routes;
|
||||
|
||||
namespace Orchard.Core.Reports {
|
||||
public class Routes : IRouteProvider {
|
||||
public void GetRoutes(ICollection<RouteDescriptor> routes) {
|
||||
foreach (var routeDescriptor in GetRoutes())
|
||||
routes.Add(routeDescriptor);
|
||||
}
|
||||
|
||||
public IEnumerable<RouteDescriptor> GetRoutes() {
|
||||
return new[] {
|
||||
new RouteDescriptor {
|
||||
Priority = -5,
|
||||
Route = new Route(
|
||||
"Admin/Reports",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Reports"},
|
||||
{"controller", "Admin"},
|
||||
{"action", "Index"}
|
||||
},
|
||||
new RouteValueDictionary(),
|
||||
new RouteValueDictionary {
|
||||
{"area", "Reports"}
|
||||
},
|
||||
new MvcRouteHandler())
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
using Orchard.Reports;
|
||||
|
||||
namespace Orchard.Core.Reports.ViewModels {
|
||||
public class DisplayReportViewModel : BaseViewModel {
|
||||
public Report Report { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
using Orchard.Reports;
|
||||
|
||||
namespace Orchard.Core.Reports.ViewModels {
|
||||
public class ReportsAdminIndexViewModel : BaseViewModel {
|
||||
public IList<Report> Reports { get; set; }
|
||||
}
|
||||
}
|
40
src/Orchard.Web/Core/Reports/Views/Admin/Display.aspx
Normal file
40
src/Orchard.Web/Core/Reports/Views/Admin/Display.aspx
Normal file
@ -0,0 +1,40 @@
|
||||
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<DisplayReportViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Reports.ViewModels"%>
|
||||
<h1><%: Html.TitleForPage(T("Display Report").ToString())%></h1>
|
||||
<% using(Html.BeginFormAntiForgeryPost()) { %>
|
||||
<%: Html.ValidationSummary() %>
|
||||
<fieldset>
|
||||
<table class="items" summary="<%: T("This is a table of the reports in your application") %>">
|
||||
<colgroup>
|
||||
<col id="Col1" />
|
||||
<col id="Col2" />
|
||||
<col id="Col3" />
|
||||
<col id="Col4" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"><%: T("Type")%></th>
|
||||
<th scope="col"><%: T("Message")%></th>
|
||||
<th scope="col"><%: T("Date")%></th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<%
|
||||
foreach (var reportEntry in Model.Report.Entries) {
|
||||
%>
|
||||
<tr>
|
||||
<td>
|
||||
<%:reportEntry.Type %>
|
||||
</td>
|
||||
<td>
|
||||
<%:reportEntry.Message %>
|
||||
</td>
|
||||
<td>
|
||||
<%:reportEntry.Utc.ToLocalTime().ToShortDateString()%> <%:reportEntry.Utc.ToLocalTime().ToShortTimeString()%>
|
||||
</td>
|
||||
</tr>
|
||||
<%
|
||||
}%>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% } %>
|
40
src/Orchard.Web/Core/Reports/Views/Admin/Index.aspx
Normal file
40
src/Orchard.Web/Core/Reports/Views/Admin/Index.aspx
Normal file
@ -0,0 +1,40 @@
|
||||
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<ReportsAdminIndexViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Reports.ViewModels"%>
|
||||
<h1><%: Html.TitleForPage(T("Manage Reports").ToString())%></h1>
|
||||
<% using(Html.BeginFormAntiForgeryPost()) { %>
|
||||
<%: Html.ValidationSummary() %>
|
||||
<fieldset>
|
||||
<table class="items" summary="<%: T("This is a table of the reports in your application") %>">
|
||||
<colgroup>
|
||||
<col id="Col1" />
|
||||
<col id="Col2" />
|
||||
<col id="Col3" />
|
||||
<col id="Col4" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"><%: T("Name")%></th>
|
||||
<th scope="col"><%: T("Title")%></th>
|
||||
<th scope="col"><%: T("Date")%></th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<%
|
||||
foreach (var report in Model.Reports) {
|
||||
%>
|
||||
<tr>
|
||||
<td>
|
||||
<%: Html.ActionLink(Html.Encode(report.ActivityName), "Display", new {id = report.ReportId}) %>
|
||||
</td>
|
||||
<td>
|
||||
<%:report.Title%>
|
||||
</td>
|
||||
<td>
|
||||
<%:report.Utc.ToLocalTime().ToShortDateString()%> <%:report.Utc.ToLocalTime().ToShortTimeString()%>
|
||||
</td>
|
||||
</tr>
|
||||
<%
|
||||
}%>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% } %>
|
34
src/Orchard.Web/Core/Reports/Views/Web.config
Normal file
34
src/Orchard.Web/Core/Reports/Views/Web.config
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<system.web>
|
||||
<httpHandlers>
|
||||
<add path="*" verb="*"
|
||||
type="System.Web.HttpNotFoundHandler"/>
|
||||
</httpHandlers>
|
||||
|
||||
<!--
|
||||
Enabling request validation in view pages would cause validation to occur
|
||||
after the input has already been processed by the controller. By default
|
||||
MVC performs request validation before a controller processes the input.
|
||||
To change this behavior apply the ValidateInputAttribute to a
|
||||
controller or action.
|
||||
-->
|
||||
<pages
|
||||
validateRequest="false"
|
||||
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
|
||||
<controls>
|
||||
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
|
||||
</controls>
|
||||
</pages>
|
||||
</system.web>
|
||||
|
||||
<system.webServer>
|
||||
<validation validateIntegratedModeConfiguration="false"/>
|
||||
<handlers>
|
||||
<remove name="BlockViewHandler"/>
|
||||
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
</configuration>
|
@ -21,6 +21,7 @@ using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Indexing;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Localization.Services;
|
||||
using Orchard.Reports.Services;
|
||||
using Orchard.Security;
|
||||
using Orchard.Settings;
|
||||
using Orchard.Themes;
|
||||
@ -68,6 +69,7 @@ namespace Orchard.Setup.Services {
|
||||
"Common",
|
||||
"Contents",
|
||||
"Dashboard",
|
||||
"Reports",
|
||||
"Feeds",
|
||||
"HomePage",
|
||||
"Navigation",
|
||||
@ -111,6 +113,9 @@ namespace Orchard.Setup.Services {
|
||||
using (var environment = new StandaloneEnvironment(bootstrapLifetimeScope)) {
|
||||
|
||||
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>() );
|
||||
var reportsCoordinator = environment.Resolve<IReportsCoordinator>();
|
||||
|
||||
reportsCoordinator.Register("Data Migration", "Setup", "Orchard installation");
|
||||
|
||||
schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table
|
||||
.Column<int>("Id", column => column.PrimaryKey().Identity())
|
||||
|
@ -8,7 +8,9 @@ using Orchard.Data.Migration.Records;
|
||||
using Orchard.Data.Migration.Schema;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.State;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Reports.Services;
|
||||
|
||||
namespace Orchard.Data.Migration {
|
||||
/// <summary>
|
||||
@ -19,21 +21,24 @@ namespace Orchard.Data.Migration {
|
||||
private readonly IRepository<DataMigrationRecord> _dataMigrationRepository;
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly IDataMigrationInterpreter _interpreter;
|
||||
private readonly IReportsCoordinator _reportsCoordinator;
|
||||
|
||||
public DataMigrationManager(
|
||||
IEnumerable<IDataMigration> dataMigrations,
|
||||
IRepository<DataMigrationRecord> dataMigrationRepository,
|
||||
IExtensionManager extensionManager,
|
||||
IDataMigrationInterpreter interpreter
|
||||
IDataMigrationInterpreter interpreter,
|
||||
IReportsCoordinator reportsCoordinator
|
||||
) {
|
||||
_dataMigrations = dataMigrations;
|
||||
_dataMigrationRepository = dataMigrationRepository;
|
||||
_extensionManager = extensionManager;
|
||||
_interpreter = interpreter;
|
||||
_reportsCoordinator = reportsCoordinator;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public IEnumerable<string> GetFeaturesThatNeedUpdate() {
|
||||
@ -78,7 +83,8 @@ namespace Orchard.Data.Migration {
|
||||
}
|
||||
|
||||
public void Update(string feature){
|
||||
Logger.Information("Updating {0}", feature);
|
||||
|
||||
Logger.Information("Updating feature: {0}", feature);
|
||||
|
||||
// proceed with dependent features first, whatever the module it's in
|
||||
var dependencies = ShellStateCoordinator.OrderByDependencies(_extensionManager.AvailableExtensions()
|
||||
|
@ -9,7 +9,9 @@ using NHibernate.SqlTypes;
|
||||
using Orchard.Data.Migration.Schema;
|
||||
using Orchard.Data.Providers;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Reports.Services;
|
||||
|
||||
namespace Orchard.Data.Migration.Interpreters {
|
||||
public class DefaultDataMigrationInterpreter : AbstractDataMigrationInterpreter, IDataMigrationInterpreter {
|
||||
@ -20,6 +22,7 @@ namespace Orchard.Data.Migration.Interpreters {
|
||||
private readonly List<string> _sqlStatements;
|
||||
private readonly IDataServicesProviderFactory _dataServicesProviderFactory;
|
||||
private readonly ISessionFactoryHolder _sessionFactoryHolder;
|
||||
private readonly IReportsCoordinator _reportsCoordinator;
|
||||
|
||||
private const char Space = ' ' ;
|
||||
|
||||
@ -28,13 +31,15 @@ namespace Orchard.Data.Migration.Interpreters {
|
||||
ISessionLocator sessionLocator,
|
||||
IEnumerable<ICommandInterpreter> commandInterpreters,
|
||||
IDataServicesProviderFactory dataServicesProviderFactory,
|
||||
ISessionFactoryHolder sessionFactoryHolder) {
|
||||
ISessionFactoryHolder sessionFactoryHolder,
|
||||
IReportsCoordinator reportsCoordinator) {
|
||||
_shellSettings = shellSettings;
|
||||
_commandInterpreters = commandInterpreters;
|
||||
_session = sessionLocator.For(typeof(DefaultDataMigrationInterpreter));
|
||||
_sqlStatements = new List<string>();
|
||||
_dataServicesProviderFactory = dataServicesProviderFactory;
|
||||
_sessionFactoryHolder = sessionFactoryHolder;
|
||||
_reportsCoordinator = reportsCoordinator;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
|
||||
@ -44,6 +49,7 @@ namespace Orchard.Data.Migration.Interpreters {
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public IEnumerable<string> SqlStatements {
|
||||
get { return _sqlStatements; }
|
||||
@ -318,6 +324,8 @@ namespace Orchard.Data.Migration.Interpreters {
|
||||
command.CommandText = sqlStatement;
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
_reportsCoordinator.Information("Data Migration", String.Format("Executing SQL Query: {0}", sqlStatement));
|
||||
}
|
||||
|
||||
_sqlStatements.Clear();
|
||||
|
@ -54,7 +54,7 @@ namespace Orchard.Localization.Services {
|
||||
.Where(x => x != null)
|
||||
.OrderByDescending(x => x.Priority);
|
||||
|
||||
if (requestCulture.Count() < 1)
|
||||
if ( requestCulture.Count() < 1 )
|
||||
return String.Empty;
|
||||
|
||||
foreach (var culture in requestCulture) {
|
||||
|
@ -408,6 +408,15 @@
|
||||
<Compile Include="Environment\Extensions\Compilers\IProjectFileParser.cs" />
|
||||
<Compile Include="Indexing\MetaDataExtensions.cs" />
|
||||
<Compile Include="Localization\Commands\CultureCommands.cs" />
|
||||
<Compile Include="Reports\Report.cs" />
|
||||
<Compile Include="Reports\ReportEntry.cs" />
|
||||
<Compile Include="Reports\ReportExtentions.cs" />
|
||||
<Compile Include="Reports\Services\IReportsCoordinator.cs" />
|
||||
<Compile Include="Reports\Services\IReportsManager.cs" />
|
||||
<Compile Include="Reports\Services\IReportsPersister.cs" />
|
||||
<Compile Include="Reports\Services\ReportsCoordinator.cs" />
|
||||
<Compile Include="Reports\Services\ReportsManager.cs" />
|
||||
<Compile Include="Reports\Services\ReportsPersister.cs" />
|
||||
<Compile Include="UI\Admin\Notification\NotificationFilter.cs" />
|
||||
<Compile Include="Data\Migration\DataMigrationNotificationProvider.cs" />
|
||||
<Compile Include="UI\Admin\Notification\INotificationManager.cs" />
|
||||
|
17
src/Orchard/Reports/Report.cs
Normal file
17
src/Orchard/Reports/Report.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.Reports {
|
||||
public class Report {
|
||||
public Report() {
|
||||
Entries = new List<ReportEntry>();
|
||||
}
|
||||
|
||||
public IList<ReportEntry> Entries { get; set;}
|
||||
public int ReportId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string ActivityName { get; set; }
|
||||
public DateTime Utc { get; set; }
|
||||
}
|
||||
}
|
16
src/Orchard/Reports/ReportEntry.cs
Normal file
16
src/Orchard/Reports/ReportEntry.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.Reports {
|
||||
public enum ReportEntryType {
|
||||
Information,
|
||||
Warning,
|
||||
Error
|
||||
}
|
||||
|
||||
public class ReportEntry {
|
||||
public ReportEntryType Type { get; set; }
|
||||
public string Message { get; set; }
|
||||
public DateTime Utc { get; set; }
|
||||
}
|
||||
}
|
16
src/Orchard/Reports/ReportExtentions.cs
Normal file
16
src/Orchard/Reports/ReportExtentions.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using Orchard.Localization;
|
||||
using Orchard.Reports;
|
||||
using Orchard.Reports.Services;
|
||||
|
||||
public static class ReportExtentions {
|
||||
public static void Information(this IReportsCoordinator reportCoordinator, string reportKey, string message) {
|
||||
reportCoordinator.Add(reportKey, ReportEntryType.Information, message);
|
||||
}
|
||||
public static void Warning(this IReportsCoordinator reportCoordinator, string reportKey, string message) {
|
||||
reportCoordinator.Add(reportKey, ReportEntryType.Warning, message);
|
||||
}
|
||||
public static void Error(this IReportsCoordinator reportCoordinator, string reportKey, string message) {
|
||||
reportCoordinator.Add(reportKey, ReportEntryType.Error, message);
|
||||
}
|
||||
}
|
||||
|
8
src/Orchard/Reports/Services/IReportsCoordinator.cs
Normal file
8
src/Orchard/Reports/Services/IReportsCoordinator.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.Reports.Services {
|
||||
public interface IReportsCoordinator : IDependency {
|
||||
void Add(string reportKey, ReportEntryType type, string message);
|
||||
void Register(string reportKey, string activityName, string title);
|
||||
}
|
||||
}
|
11
src/Orchard/Reports/Services/IReportsManager.cs
Normal file
11
src/Orchard/Reports/Services/IReportsManager.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Reports.Services {
|
||||
public interface IReportsManager : ISingletonDependency {
|
||||
void Add(int reportId, ReportEntryType type, string message);
|
||||
int CreateReport(string title, string activityName);
|
||||
Report Get(int reportId);
|
||||
IEnumerable<Report> GetReports();
|
||||
void Flush();
|
||||
}
|
||||
}
|
8
src/Orchard/Reports/Services/IReportsPersister.cs
Normal file
8
src/Orchard/Reports/Services/IReportsPersister.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Reports.Services {
|
||||
public interface IReportsPersister : IDependency {
|
||||
IEnumerable<Report> Fetch();
|
||||
void Save(IEnumerable<Report> reports);
|
||||
}
|
||||
}
|
35
src/Orchard/Reports/Services/ReportsCoordinator.cs
Normal file
35
src/Orchard/Reports/Services/ReportsCoordinator.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Reports.Services {
|
||||
public class ReportsCoordinator : IReportsCoordinator, IDisposable {
|
||||
private readonly IReportsManager _reportsManager;
|
||||
private readonly IDictionary<string, int> _reports;
|
||||
|
||||
public ReportsCoordinator(IReportsManager reportsManager) {
|
||||
_reportsManager = reportsManager;
|
||||
Logger = NullLogger.Instance;
|
||||
_reports = new Dictionary<string, int>();
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
public void Dispose() {
|
||||
_reportsManager.Flush();
|
||||
}
|
||||
|
||||
public void Add(string reportKey, ReportEntryType type, string message) {
|
||||
if(!_reports.ContainsKey(reportKey)) {
|
||||
// ignore message if no corresponding report
|
||||
return;
|
||||
}
|
||||
|
||||
_reportsManager.Add(_reports[reportKey], type, message);
|
||||
}
|
||||
|
||||
public void Register(string reportKey, string activityName, string title) {
|
||||
_reports.Add(reportKey, _reportsManager.CreateReport(title, activityName));
|
||||
}
|
||||
}
|
||||
}
|
74
src/Orchard/Reports/Services/ReportsManager.cs
Normal file
74
src/Orchard/Reports/Services/ReportsManager.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Reports.Services {
|
||||
public class ReportsManager : IReportsManager {
|
||||
private readonly IReportsPersister _reportsPersister;
|
||||
private List<Report> _reports;
|
||||
private static readonly object _synLock = new object();
|
||||
private bool _isDirty;
|
||||
|
||||
public ReportsManager(IReportsPersister reportsPersister) {
|
||||
_reportsPersister = reportsPersister;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public void Add(int reportId, ReportEntryType type, string message) {
|
||||
lock ( _synLock ) {
|
||||
LoadReports();
|
||||
_isDirty = true;
|
||||
var report = Get(reportId);
|
||||
if(report == null) {
|
||||
return;
|
||||
}
|
||||
report.Entries.Add(new ReportEntry {Message = message, Type = type, Utc = DateTime.UtcNow});
|
||||
}
|
||||
}
|
||||
|
||||
public int CreateReport(string title, string activityName) {
|
||||
lock ( _synLock ) {
|
||||
LoadReports();
|
||||
_isDirty = true;
|
||||
var reportId = _reports.Count == 0 ? 1 : _reports.Max(r => r.ReportId) + 1;
|
||||
var report = new Report {ActivityName = activityName, ReportId = reportId, Title = title, Utc = DateTime.UtcNow};
|
||||
_reports.Add(report);
|
||||
return reportId;
|
||||
}
|
||||
}
|
||||
|
||||
public Report Get(int reportId) {
|
||||
lock(_synLock) {
|
||||
LoadReports();
|
||||
return _reports.Where(r => r.ReportId == reportId).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Report> GetReports() {
|
||||
lock ( _synLock ) {
|
||||
LoadReports();
|
||||
return _reports.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public void Flush() {
|
||||
if ( _reports == null || !_isDirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock ( _synLock ) {
|
||||
_reportsPersister.Save(_reports);
|
||||
_isDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadReports() {
|
||||
if(_reports == null) {
|
||||
_reports = _reportsPersister.Fetch().ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
src/Orchard/Reports/Services/ReportsPersister.cs
Normal file
69
src/Orchard/Reports/Services/ReportsPersister.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.FileSystems.AppData;
|
||||
using System.IO;
|
||||
|
||||
namespace Orchard.Reports.Services {
|
||||
public class ReportsPersister : IReportsPersister {
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
private readonly ShellSettings _shellSettings;
|
||||
private readonly string _reportsFileName;
|
||||
private readonly DataContractSerializer _dataContractSerializer;
|
||||
private readonly object _synLock = new object();
|
||||
|
||||
public ReportsPersister(IAppDataFolder appDataFolder, ShellSettings shellSettings) {
|
||||
_appDataFolder = appDataFolder;
|
||||
_shellSettings = shellSettings;
|
||||
_dataContractSerializer = new DataContractSerializer(typeof(Report), new [] { typeof(ReportEntry) });
|
||||
_reportsFileName = Path.Combine(Path.Combine("Sites", _shellSettings.Name), "reports.dat");
|
||||
}
|
||||
|
||||
public IEnumerable<Report> Fetch() {
|
||||
lock ( _synLock ) {
|
||||
if ( !_appDataFolder.FileExists(_reportsFileName) ) {
|
||||
yield break;
|
||||
}
|
||||
|
||||
var text = _appDataFolder.ReadFile(_reportsFileName);
|
||||
var xmlDocument = XDocument.Parse(text);
|
||||
var rootNode = xmlDocument.Root;
|
||||
if (rootNode == null) {
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var reportNode in rootNode.Elements()) {
|
||||
var reader = new StringReader(reportNode.Value);
|
||||
using (var xmlReader = XmlReader.Create(reader)) {
|
||||
yield return (Report) _dataContractSerializer.ReadObject(xmlReader, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(IEnumerable<Report> reports) {
|
||||
lock ( _synLock ) {
|
||||
var xmlDocument = new XDocument();
|
||||
xmlDocument.Add(new XElement("Reports"));
|
||||
foreach (var report in reports) {
|
||||
var reportNode = new XElement("Report");
|
||||
var writer = new StringWriter();
|
||||
using (var xmlWriter = XmlWriter.Create(writer)) {
|
||||
_dataContractSerializer.WriteObject(xmlWriter, report);
|
||||
}
|
||||
reportNode.Value = writer.ToString();
|
||||
xmlDocument.Root.Add(reportNode);
|
||||
}
|
||||
|
||||
var saveWriter = new StringWriter();
|
||||
xmlDocument.Save(saveWriter);
|
||||
_appDataFolder.CreateFile(_reportsFileName, saveWriter.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user