Merge pull request #1117 from t-andre/dev

Reports - Add Users activities
pull/702/head
Luke 9 years ago
commit 76d7953074

@ -84,6 +84,8 @@
<Compile Include="Playback\MediaInfoService.cs" /> <Compile Include="Playback\MediaInfoService.cs" />
<Compile Include="Playback\TranscodingThrottler.cs" /> <Compile Include="Playback\TranscodingThrottler.cs" />
<Compile Include="PlaylistService.cs" /> <Compile Include="PlaylistService.cs" />
<Compile Include="Reports\Activities\ReportActivitiesBuilder.cs" />
<Compile Include="Reports\Common\HeaderActivitiesMetadata.cs" />
<Compile Include="Reports\Common\HeaderMetadata.cs" /> <Compile Include="Reports\Common\HeaderMetadata.cs" />
<Compile Include="Reports\Common\ItemViewType.cs" /> <Compile Include="Reports\Common\ItemViewType.cs" />
<Compile Include="Reports\Common\ReportBuilderBase.cs" /> <Compile Include="Reports\Common\ReportBuilderBase.cs" />
@ -91,15 +93,16 @@
<Compile Include="Reports\Common\ReportFieldType.cs" /> <Compile Include="Reports\Common\ReportFieldType.cs" />
<Compile Include="Reports\Common\ReportHeaderIdType.cs" /> <Compile Include="Reports\Common\ReportHeaderIdType.cs" />
<Compile Include="Reports\Common\ReportHelper.cs" /> <Compile Include="Reports\Common\ReportHelper.cs" />
<Compile Include="Reports\Common\ReportIncludeItemTypes.cs" />
<Compile Include="Reports\Common\ReportViewType.cs" /> <Compile Include="Reports\Common\ReportViewType.cs" />
<Compile Include="Reports\Data\ReportBuilder.cs" /> <Compile Include="Reports\Data\ReportBuilder.cs" />
<Compile Include="Reports\Data\ReportExport.cs" /> <Compile Include="Reports\Data\ReportExport.cs" />
<Compile Include="Reports\Data\ReportGroup.cs" />
<Compile Include="Reports\Data\ReportHeader.cs" />
<Compile Include="Reports\Data\ReportItem.cs" />
<Compile Include="Reports\Data\ReportOptions.cs" /> <Compile Include="Reports\Data\ReportOptions.cs" />
<Compile Include="Reports\Data\ReportResult.cs" /> <Compile Include="Reports\Model\ReportGroup.cs" />
<Compile Include="Reports\Data\ReportRow.cs" /> <Compile Include="Reports\Model\ReportHeader.cs" />
<Compile Include="Reports\Model\ReportItem.cs" />
<Compile Include="Reports\Model\ReportResult.cs" />
<Compile Include="Reports\Model\ReportRow.cs" />
<Compile Include="Reports\ReportRequests.cs" /> <Compile Include="Reports\ReportRequests.cs" />
<Compile Include="Reports\ReportsService.cs" /> <Compile Include="Reports\ReportsService.cs" />
<Compile Include="Reports\Stat\ReportStatBuilder.cs" /> <Compile Include="Reports\Stat\ReportStatBuilder.cs" />
@ -205,6 +208,13 @@
<PostBuildEvent> <PostBuildEvent>
</PostBuildEvent> </PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

@ -0,0 +1,250 @@
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Querying;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
namespace MediaBrowser.Api.Reports
{
/// <summary> A report activities builder. </summary>
/// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
public class ReportActivitiesBuilder : ReportBuilderBase
{
#region [Constructors]
/// <summary>
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportActivitiesBuilder class. </summary>
/// <param name="libraryManager"> Manager for library. </param>
/// <param name="userManager"> Manager for user. </param>
public ReportActivitiesBuilder(ILibraryManager libraryManager, IUserManager userManager)
: base(libraryManager)
{
_userManager = userManager;
}
#endregion
#region [Private Fields]
private readonly IUserManager _userManager; ///< Manager for user
#endregion
#region [Public Methods]
/// <summary> Gets a result. </summary>
/// <param name="queryResult"> The query result. </param>
/// <param name="request"> The request. </param>
/// <returns> The result. </returns>
public ReportResult GetResult(QueryResult<ActivityLogEntry> queryResult, IReportsQuery request)
{
List<ReportOptions<ActivityLogEntry>> options = this.GetReportOptions<ActivityLogEntry>(request,
() => this.GetDefaultHeaderMetadata(),
(hm) => this.GetOption(hm)).Where(x => x.Header.Visible == true).ToList();
var headers = GetHeaders<ActivityLogEntry>(options);
var rows = GetReportRows(queryResult.Items, options);
ReportResult result = new ReportResult { Headers = headers };
HeaderMetadata groupBy = ReportHelper.GetHeaderMetadataType(request.GroupBy);
int i = headers.FindIndex(x => x.FieldName == groupBy);
if (groupBy != HeaderMetadata.None && i >= 0)
{
var rowsGroup = rows.SelectMany(x => x.Columns[i].Name.Split(';'), (x, g) => new { Group = g.Trim(), Rows = x })
.GroupBy(x => x.Group)
.OrderBy(x => x.Key)
.Select(x => new ReportGroup { Name = x.Key, Rows = x.Select(r => r.Rows).ToList() });
result.Groups = rowsGroup.ToList();
result.IsGrouped = true;
}
else
{
result.Rows = rows;
result.IsGrouped = false;
}
return result;
}
#endregion
#region [Protected Internal Methods]
/// <summary> Gets the headers. </summary>
/// <typeparam name="H"> Type of the header. </typeparam>
/// <param name="request"> The request. </param>
/// <returns> The headers. </returns>
/// <seealso cref="M:MediaBrowser.Api.Reports.ReportBuilderBase.GetHeaders{H}(H)"/>
protected internal override List<ReportHeader> GetHeaders<H>(H request)
{
return this.GetHeaders<ActivityLogEntry>(request, () => this.GetDefaultHeaderMetadata(), (hm) => this.GetOption(hm));
}
#endregion
#region [Private Methods]
/// <summary> Gets default header metadata. </summary>
/// <returns> The default header metadata. </returns>
private List<HeaderMetadata> GetDefaultHeaderMetadata()
{
return new List<HeaderMetadata>
{
HeaderMetadata.Date,
HeaderMetadata.User,
HeaderMetadata.Type,
HeaderMetadata.Severity,
HeaderMetadata.Name,
HeaderMetadata.ShortOverview,
HeaderMetadata.Overview,
//HeaderMetadata.UserPrimaryImageTag,
//HeaderMetadata.Item,
};
}
/// <summary> Gets an option. </summary>
/// <param name="header"> The header. </param>
/// <param name="sortField"> The sort field. </param>
/// <returns> The option. </returns>
private ReportOptions<ActivityLogEntry> GetOption(HeaderMetadata header, string sortField = "")
{
HeaderMetadata internalHeader = header;
ReportOptions<ActivityLogEntry> option = new ReportOptions<ActivityLogEntry>()
{
Header = new ReportHeader
{
HeaderFieldType = ReportFieldType.String,
SortField = sortField,
Type = "",
ItemViewType = ItemViewType.None
}
};
switch (header)
{
case HeaderMetadata.StatusImage:
option.Header.ItemViewType = ItemViewType.StatusImage;
internalHeader = HeaderMetadata.Status;
option.Header.CanGroup = false;
break;
case HeaderMetadata.Name:
option.Column = (i, r) => i.Name;
break;
case HeaderMetadata.Overview:
option.Column = (i, r) => i.Overview;
option.Header.SortField = "";
option.Header.CanGroup = false;
break;
case HeaderMetadata.ShortOverview:
option.Column = (i, r) => i.ShortOverview;
option.Header.SortField = "";
option.Header.CanGroup = false;
break;
case HeaderMetadata.Type:
option.Column = (i, r) => i.Type;
option.Header.SortField = "";
break;
case HeaderMetadata.Date:
option.Column = (i, r) => i.Date;
option.Header.SortField = "";
option.Header.HeaderFieldType = ReportFieldType.DateTime;
option.Header.Type = "";
break;
case HeaderMetadata.UserPrimaryImageTag:
//option.Column = (i, r) => i.UserPrimaryImageTag;
option.Column = (i, r) =>
{
if (!string.IsNullOrEmpty(i.UserId))
{
MediaBrowser.Controller.Entities.User user = _userManager.GetUserById(i.UserId);
if (user != null)
return user.PrimaryImagePath;
}
return string.Empty;
};
option.Header.SortField = "";
break;
case HeaderMetadata.Severity:
option.Column = (i, r) => i.Severity;
option.Header.SortField = "";
break;
case HeaderMetadata.Item:
option.Column = (i, r) => i.ItemId;
option.Header.SortField = "";
break;
case HeaderMetadata.User:
option.Column = (i, r) =>
{
if (!string.IsNullOrEmpty(i.UserId))
{
MediaBrowser.Controller.Entities.User user = _userManager.GetUserById(i.UserId);
if (user != null)
return user.Name;
}
return string.Empty;
};
option.Header.SortField = "";
break;
}
option.Header.Name = GetLocalizedHeader(internalHeader);
option.Header.FieldName = header;
return option;
}
/// <summary> Gets report rows. </summary>
/// <param name="items"> The items. </param>
/// <param name="options"> Options for controlling the operation. </param>
/// <returns> The report rows. </returns>
private List<ReportRow> GetReportRows(IEnumerable<ActivityLogEntry> items, List<ReportOptions<ActivityLogEntry>> options)
{
var rows = new List<ReportRow>();
foreach (ActivityLogEntry item in items)
{
ReportRow rRow = GetRow(item);
foreach (ReportOptions<ActivityLogEntry> option in options)
{
object itemColumn = option.Column != null ? option.Column(item, rRow) : "";
object itemId = option.ItemID != null ? option.ItemID(item) : "";
ReportItem rItem = new ReportItem
{
Name = ReportHelper.ConvertToString(itemColumn, option.Header.HeaderFieldType),
Id = ReportHelper.ConvertToString(itemId, ReportFieldType.Object)
};
rRow.Columns.Add(rItem);
}
rows.Add(rRow);
}
return rows;
}
/// <summary> Gets a row. </summary>
/// <param name="item"> The item. </param>
/// <returns> The row. </returns>
private ReportRow GetRow(ActivityLogEntry item)
{
ReportRow rRow = new ReportRow
{
Id = item.Id,
};
return rRow;
}
#endregion
}
}

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Api.Reports
{
public enum HeaderActivitiesMetadata
{
None,
Name,
Overview,
ShortOverview,
Type,
Date,
UserPrimaryImageTag,
Severity,
Item,
User
}
}

@ -42,6 +42,15 @@ namespace MediaBrowser.Api.Reports
AudioAlbumArtist, AudioAlbumArtist,
MusicArtist, MusicArtist,
AudioAlbum, AudioAlbum,
Status Status,
//Activity logs
Overview,
ShortOverview,
Type,
Date,
UserPrimaryImageTag,
Severity,
Item,
User
} }
} }

@ -13,217 +13,330 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.Reports namespace MediaBrowser.Api.Reports
{ {
/// <summary> A report builder base. </summary> /// <summary> A report builder base. </summary>
public class ReportBuilderBase public abstract class ReportBuilderBase
{ {
/// <summary>
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilderBase class. </summary> #region [Constructors]
/// <param name="libraryManager"> Manager for library. </param>
public ReportBuilderBase(ILibraryManager libraryManager) /// <summary>
{ /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilderBase class. </summary>
_libraryManager = libraryManager; /// <param name="libraryManager"> Manager for library. </param>
} public ReportBuilderBase(ILibraryManager libraryManager)
{
/// <summary> Manager for library. </summary> _libraryManager = libraryManager;
protected readonly ILibraryManager _libraryManager; }
/// <summary> Gets audio stream. </summary> #endregion
/// <param name="item"> The item. </param>
/// <returns> The audio stream. </returns> #region [Protected Fields]
protected string GetAudioStream(BaseItem item)
{ /// <summary> Manager for library. </summary>
var stream = GetStream(item, MediaStreamType.Audio); protected readonly ILibraryManager _libraryManager; ///< Manager for library
if (stream != null)
return stream.Codec.ToUpper() == "DCA" ? stream.Profile : stream.Codec. protected Func<bool, string> GetBoolString = s => s == true ? "x" : ""; ///< .
ToUpper();
#endregion
return string.Empty;
} #region [Protected Internal Methods]
/// <summary> Gets an episode. </summary> /// <summary> Gets the headers. </summary>
/// <param name="item"> The item. </param> /// <typeparam name="H"> Type of the header. </typeparam>
/// <returns> The episode. </returns> /// <param name="request"> The request. </param>
protected string GetEpisode(BaseItem item) /// <returns> The headers. </returns>
{ protected internal abstract List<ReportHeader> GetHeaders<H>(H request) where H : IReportsHeader;
if (item.GetClientTypeName() == ChannelMediaContentType.Episode.ToString() && item.ParentIndexNumber != null) #endregion
return "Season " + item.ParentIndexNumber;
else #region [Protected Methods]
return item.Name;
} /// <summary> Gets active headers. </summary>
/// <typeparam name="T"> Generic type parameter. </typeparam>
/// <summary> Gets a genre. </summary> /// <param name="options"> Options for controlling the operation. </param>
/// <param name="name"> The name. </param> /// <returns> The active headers. </returns>
/// <returns> The genre. </returns> protected List<ReportHeader> GetActiveHeaders<T>(List<ReportOptions<T>> options)
protected Genre GetGenre(string name) {
{ List<ReportHeader> headers = new List<ReportHeader>();
if (string.IsNullOrEmpty(name)) foreach (ReportOptions<T> option in options.Where(x => x.Header.Visible == true))
return null; {
return _libraryManager.GetGenre(name); headers.Add(option.Header);
} }
/// <summary> Gets genre identifier. </summary> return headers;
/// <param name="name"> The name. </param> }
/// <returns> The genre identifier. </returns>
protected string GetGenreID(string name) /// <summary> Gets audio stream. </summary>
{ /// <param name="item"> The item. </param>
if (string.IsNullOrEmpty(name)) /// <returns> The audio stream. </returns>
return string.Empty; protected string GetAudioStream(BaseItem item)
return string.Format("{0:N}", {
GetGenre(name).Id); var stream = GetStream(item, MediaStreamType.Audio);
} if (stream != null)
return stream.Codec.ToUpper() == "DCA" ? stream.Profile : stream.Codec.
/// <summary> Gets list as string. </summary> ToUpper();
/// <param name="items"> The items. </param>
/// <returns> The list as string. </returns> return string.Empty;
protected string GetListAsString(List<string> items) }
{
return String.Join("; ", items); /// <summary> Gets an episode. </summary>
} /// <param name="item"> The item. </param>
/// <returns> The episode. </returns>
/// <summary> Gets media source information. </summary> protected string GetEpisode(BaseItem item)
/// <param name="item"> The item. </param> {
/// <returns> The media source information. </returns>
protected MediaSourceInfo GetMediaSourceInfo(BaseItem item) if (item.GetClientTypeName() == ChannelMediaContentType.Episode.ToString() && item.ParentIndexNumber != null)
{ return "Season " + item.ParentIndexNumber;
var mediaSource = item as IHasMediaSources; else
if (mediaSource != null) return item.Name;
return mediaSource.GetMediaSources(false).FirstOrDefault(n => n.Type == MediaSourceType.Default); }
return null; /// <summary> Gets a genre. </summary>
} /// <param name="name"> The name. </param>
/// <returns> The genre. </returns>
/// <summary> Gets an object. </summary> protected Genre GetGenre(string name)
/// <typeparam name="T"> Generic type parameter. </typeparam> {
/// <typeparam name="R"> Type of the r. </typeparam> if (string.IsNullOrEmpty(name))
/// <param name="item"> The item. </param> return null;
/// <param name="function"> The function. </param> return _libraryManager.GetGenre(name);
/// <param name="defaultValue"> The default value. </param> }
/// <returns> The object. </returns>
protected R GetObject<T, R>(BaseItem item, Func<T, R> function, R defaultValue = default(R)) where T : class /// <summary> Gets genre identifier. </summary>
{ /// <param name="name"> The name. </param>
var value = item as T; /// <returns> The genre identifier. </returns>
if (value != null && function != null) protected string GetGenreID(string name)
return function(value); {
else if (string.IsNullOrEmpty(name))
return defaultValue; return string.Empty;
} return string.Format("{0:N}",
GetGenre(name).Id);
/// <summary> Gets a person. </summary> }
/// <param name="name"> The name. </param>
/// <returns> The person. </returns> /// <summary> Gets the headers. </summary>
protected Person GetPerson(string name) /// <typeparam name="T"> Generic type parameter. </typeparam>
{ /// <param name="options"> Options for controlling the operation. </param>
if (string.IsNullOrEmpty(name)) /// <returns> The headers. </returns>
return null; protected List<ReportHeader> GetHeaders<T>(List<ReportOptions<T>> options)
return _libraryManager.GetPerson(name); {
} List<ReportHeader> headers = new List<ReportHeader>();
foreach (ReportOptions<T> option in options)
/// <summary> Gets person identifier. </summary> {
/// <param name="name"> The name. </param> headers.Add(option.Header);
/// <returns> The person identifier. </returns> }
protected string GetPersonID(string name)
{ return headers;
if (string.IsNullOrEmpty(name)) }
return string.Empty;
return string.Format("{0:N}", /// <summary> Gets the headers. </summary>
GetPerson(name).Id); /// <typeparam name="T"> Generic type parameter. </typeparam>
} /// <param name="request"> The request. </param>
/// <param name="getHeadersMetadata"> The get headers metadata. </param>
/// <summary> Gets runtime date time. </summary> /// <param name="getOptions"> Options for controlling the get. </param>
/// <param name="runtime"> The runtime. </param> /// <returns> The headers. </returns>
/// <returns> The runtime date time. </returns> protected List<ReportHeader> GetHeaders<T>(IReportsHeader request, Func<List<HeaderMetadata>> getHeadersMetadata, Func<HeaderMetadata, ReportOptions<T>> getOptions)
protected double? GetRuntimeDateTime(long? runtime) {
{ List<ReportOptions<T>> options = this.GetReportOptions(request, getHeadersMetadata, getOptions);
if (runtime.HasValue) return this.GetHeaders(options);
}
/// <summary> Gets list as string. </summary>
/// <param name="items"> The items. </param>
/// <returns> The list as string. </returns>
protected string GetListAsString(List<string> items)
{
return String.Join("; ", items);
}
/// <summary> Gets localized header. </summary>
/// <param name="internalHeader"> The internal header. </param>
/// <returns> The localized header. </returns>
protected static string GetLocalizedHeader(HeaderMetadata internalHeader)
{
string headerName = "";
if (internalHeader != HeaderMetadata.None)
{
string localHeader = "Header" + internalHeader.ToString();
headerName = internalHeader != HeaderMetadata.None ? ReportHelper.GetJavaScriptLocalizedString(localHeader) : "";
if (string.Compare(localHeader, headerName, StringComparison.CurrentCultureIgnoreCase) == 0)
headerName = ReportHelper.GetServerLocalizedString(localHeader);
}
return headerName;
}
/// <summary> Gets media source information. </summary>
/// <param name="item"> The item. </param>
/// <returns> The media source information. </returns>
protected MediaSourceInfo GetMediaSourceInfo(BaseItem item)
{
var mediaSource = item as IHasMediaSources;
if (mediaSource != null)
return mediaSource.GetMediaSources(false).FirstOrDefault(n => n.Type == MediaSourceType.Default);
return null;
}
/// <summary> Gets an object. </summary>
/// <typeparam name="T"> Generic type parameter. </typeparam>
/// <typeparam name="R"> Type of the r. </typeparam>
/// <param name="item"> The item. </param>
/// <param name="function"> The function. </param>
/// <param name="defaultValue"> The default value. </param>
/// <returns> The object. </returns>
protected R GetObject<T, R>(BaseItem item, Func<T, R> function, R defaultValue = default(R)) where T : class
{
var value = item as T;
if (value != null && function != null)
return function(value);
else
return defaultValue;
}
/// <summary> Gets a person. </summary>
/// <param name="name"> The name. </param>
/// <returns> The person. </returns>
protected Person GetPerson(string name)
{
if (string.IsNullOrEmpty(name))
return null;
return _libraryManager.GetPerson(name);
}
/// <summary> Gets person identifier. </summary>
/// <param name="name"> The name. </param>
/// <returns> The person identifier. </returns>
protected string GetPersonID(string name)
{
if (string.IsNullOrEmpty(name))
return string.Empty;
return string.Format("{0:N}",
GetPerson(name).Id);
}
/// <summary> Gets report options. </summary>
/// <typeparam name="T"> Generic type parameter. </typeparam>
/// <param name="request"> The request. </param>
/// <param name="getHeadersMetadata"> The get headers metadata. </param>
/// <param name="getOptions"> Options for controlling the get. </param>
/// <returns> The report options. </returns>
protected List<ReportOptions<T>> GetReportOptions<T>(IReportsHeader request, Func<List<HeaderMetadata>> getHeadersMetadata, Func<HeaderMetadata, ReportOptions<T>> getOptions)
{
List<HeaderMetadata> headersMetadata = getHeadersMetadata();
List<ReportOptions<T>> options = new List<ReportOptions<T>>();
foreach (HeaderMetadata header in headersMetadata)
{
options.Add(getOptions(header));
}
if (request != null && !string.IsNullOrEmpty(request.ReportColumns))
{
List<HeaderMetadata> headersMetadataFiltered = ReportHelper.GetFilteredReportHeaderMetadata(request.ReportColumns, () => headersMetadata);
foreach (ReportHeader header in options.Select(x => x.Header))
{
if (!headersMetadataFiltered.Contains(header.FieldName))
{
header.Visible = false;
}
}
}
return options;
}
/// <summary> Gets runtime date time. </summary>
/// <param name="runtime"> The runtime. </param>
/// <returns> The runtime date time. </returns>
protected double? GetRuntimeDateTime(long? runtime)
{
if (runtime.HasValue)
return Math.Ceiling(new TimeSpan(runtime.Value).TotalMinutes); return Math.Ceiling(new TimeSpan(runtime.Value).TotalMinutes);
return null; return null;
} }
/// <summary> Gets series production year. </summary> /// <summary> Gets series production year. </summary>
/// <param name="item"> The item. </param> /// <param name="item"> The item. </param>
/// <returns> The series production year. </returns> /// <returns> The series production year. </returns>
protected string GetSeriesProductionYear(BaseItem item) protected string GetSeriesProductionYear(BaseItem item)
{ {
string productionYear = item.ProductionYear.ToString(); string productionYear = item.ProductionYear.ToString();
var series = item as Series; var series = item as Series;
if (series == null) if (series == null)
{ {
if (item.ProductionYear == null || item.ProductionYear == 0) if (item.ProductionYear == null || item.ProductionYear == 0)
return string.Empty; return string.Empty;
return productionYear; return productionYear;
} }
if (series.Status == SeriesStatus.Continuing) if (series.Status == SeriesStatus.Continuing)
return productionYear += "-Present"; return productionYear += "-Present";
if (series.EndDate != null && series.EndDate.Value.Year != series.ProductionYear) if (series.EndDate != null && series.EndDate.Value.Year != series.ProductionYear)
return productionYear += "-" + series.EndDate.Value.Year; return productionYear += "-" + series.EndDate.Value.Year;
return productionYear; return productionYear;
} }
/// <summary> Gets a stream. </summary> /// <summary> Gets a stream. </summary>
/// <param name="item"> The item. </param> /// <param name="item"> The item. </param>
/// <param name="streamType"> Type of the stream. </param> /// <param name="streamType"> Type of the stream. </param>
/// <returns> The stream. </returns> /// <returns> The stream. </returns>
protected MediaStream GetStream(BaseItem item, MediaStreamType streamType) protected MediaStream GetStream(BaseItem item, MediaStreamType streamType)
{ {
var itemInfo = GetMediaSourceInfo(item); var itemInfo = GetMediaSourceInfo(item);
if (itemInfo != null) if (itemInfo != null)
return itemInfo.MediaStreams.FirstOrDefault(n => n.Type == streamType); return itemInfo.MediaStreams.FirstOrDefault(n => n.Type == streamType);
return null; return null;
} }
/// <summary> Gets a studio. </summary> /// <summary> Gets a studio. </summary>
/// <param name="name"> The name. </param> /// <param name="name"> The name. </param>
/// <returns> The studio. </returns> /// <returns> The studio. </returns>
protected Studio GetStudio(string name) protected Studio GetStudio(string name)
{ {
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
return null; return null;
return _libraryManager.GetStudio(name); return _libraryManager.GetStudio(name);
} }
/// <summary> Gets studio identifier. </summary> /// <summary> Gets studio identifier. </summary>
/// <param name="name"> The name. </param> /// <param name="name"> The name. </param>
/// <returns> The studio identifier. </returns> /// <returns> The studio identifier. </returns>
protected string GetStudioID(string name) protected string GetStudioID(string name)
{ {
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
return string.Empty; return string.Empty;
return string.Format("{0:N}", return string.Format("{0:N}",
GetStudio(name).Id); GetStudio(name).Id);
} }
/// <summary> Gets video resolution. </summary> /// <summary> Gets video resolution. </summary>
/// <param name="item"> The item. </param> /// <param name="item"> The item. </param>
/// <returns> The video resolution. </returns> /// <returns> The video resolution. </returns>
protected string GetVideoResolution(BaseItem item) protected string GetVideoResolution(BaseItem item)
{ {
var stream = GetStream(item, var stream = GetStream(item,
MediaStreamType.Video); MediaStreamType.Video);
if (stream != null && stream.Width != null) if (stream != null && stream.Width != null)
return string.Format("{0} * {1}", return string.Format("{0} * {1}",
stream.Width, stream.Width,
(stream.Height != null ? stream.Height.ToString() : "-")); (stream.Height != null ? stream.Height.ToString() : "-"));
return string.Empty; return string.Empty;
} }
/// <summary> Gets video stream. </summary> /// <summary> Gets video stream. </summary>
/// <param name="item"> The item. </param> /// <param name="item"> The item. </param>
/// <returns> The video stream. </returns> /// <returns> The video stream. </returns>
protected string GetVideoStream(BaseItem item) protected string GetVideoStream(BaseItem item)
{ {
var stream = GetStream(item, MediaStreamType.Video); var stream = GetStream(item, MediaStreamType.Video);
if (stream != null) if (stream != null)
return stream.Codec.ToUpper(); return stream.Codec.ToUpper();
return string.Empty; return string.Empty;
} }
} #endregion
}
} }

@ -7,95 +7,135 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.Reports namespace MediaBrowser.Api.Reports
{ {
public class ReportHelper /// <summary> A report helper. </summary>
{ public class ReportHelper
/// <summary> Gets java script localized string. </summary> {
/// <param name="phrase"> The phrase. </param> #region [Public Methods]
/// <returns> The java script localized string. </returns>
public static string GetJavaScriptLocalizedString(string phrase) /// <summary> Convert field to string. </summary>
{ /// <typeparam name="T"> Generic type parameter. </typeparam>
var dictionary = BaseItem.LocalizationManager.GetJavaScriptLocalizationDictionary(BaseItem.ConfigurationManager.Configuration.UICulture); /// <param name="value"> The value. </param>
/// <param name="fieldType"> Type of the field. </param>
string value; /// <returns> The field converted to string. </returns>
public static string ConvertToString<T>(T value, ReportFieldType fieldType)
if (dictionary.TryGetValue(phrase, out value)) {
{ if (value == null)
return value; return "";
} switch (fieldType)
{
return phrase; case ReportFieldType.String:
} return value.ToString();
case ReportFieldType.Boolean:
/// <summary> Gets server localized string. </summary> return value.ToString();
/// <param name="phrase"> The phrase. </param> case ReportFieldType.Date:
/// <returns> The server localized string. </returns> return string.Format("{0:d}", value);
public static string GetServerLocalizedString(string phrase) case ReportFieldType.Time:
{ return string.Format("{0:t}", value);
return BaseItem.LocalizationManager.GetLocalizedString(phrase, BaseItem.ConfigurationManager.Configuration.UICulture); case ReportFieldType.DateTime:
} return string.Format("{0:d}", value);
/// <summary> Gets row type. </summary>
/// <param name="rowType"> The type. </param>
/// <returns> The row type. </returns>
public static ReportViewType GetRowType(string rowType)
{
if (string.IsNullOrEmpty(rowType))
return ReportViewType.BaseItem;
ReportViewType rType;
if (!Enum.TryParse<ReportViewType>(rowType, out rType))
return ReportViewType.BaseItem;
return rType;
}
/// <summary> Gets header metadata type. </summary>
/// <param name="header"> The header. </param>
/// <returns> The header metadata type. </returns>
public static HeaderMetadata GetHeaderMetadataType(string header)
{
if (string.IsNullOrEmpty(header))
return HeaderMetadata.None;
HeaderMetadata rType;
if (!Enum.TryParse<HeaderMetadata>(header, out rType))
return HeaderMetadata.None;
return rType;
}
/// <summary> Convert field to string. </summary>
/// <typeparam name="T"> Generic type parameter. </typeparam>
/// <param name="value"> The value. </param>
/// <param name="fieldType"> Type of the field. </param>
/// <returns> The field converted to string. </returns>
public static string ConvertToString<T>(T value, ReportFieldType fieldType)
{
if (value == null)
return "";
switch (fieldType)
{
case ReportFieldType.String:
return value.ToString();
case ReportFieldType.Boolean:
return value.ToString();
case ReportFieldType.Date:
return string.Format("{0:d}", value);
case ReportFieldType.Time:
return string.Format("{0:t}", value);
case ReportFieldType.DateTime:
return string.Format("{0:d}", value);
case ReportFieldType.Minutes: case ReportFieldType.Minutes:
return string.Format("{0}mn", value); return string.Format("{0}mn", value);
case ReportFieldType.Int: case ReportFieldType.Int:
return string.Format("", value); return string.Format("", value);
default: default:
if (value is Guid) if (value is Guid)
return string.Format("{0:N}", value); return string.Format("{0:N}", value);
return value.ToString(); return value.ToString();
} }
} }
}
/// <summary> Gets filtered report header metadata. </summary>
/// <param name="reportColumns"> The report columns. </param>
/// <param name="defaultReturnValue"> The default return value. </param>
/// <returns> The filtered report header metadata. </returns>
public static List<HeaderMetadata> GetFilteredReportHeaderMetadata(string reportColumns, Func<List<HeaderMetadata>> defaultReturnValue = null)
{
if (!string.IsNullOrEmpty(reportColumns))
{
var s = reportColumns.Split('|').Select(x => ReportHelper.GetHeaderMetadataType(x)).Where(x => x != HeaderMetadata.None);
return s.ToList();
}
else
if (defaultReturnValue != null)
return defaultReturnValue();
else
return new List<HeaderMetadata>();
}
/// <summary> Gets header metadata type. </summary>
/// <param name="header"> The header. </param>
/// <returns> The header metadata type. </returns>
public static HeaderMetadata GetHeaderMetadataType(string header)
{
if (string.IsNullOrEmpty(header))
return HeaderMetadata.None;
HeaderMetadata rType;
if (!Enum.TryParse<HeaderMetadata>(header, out rType))
return HeaderMetadata.None;
return rType;
}
/// <summary> Gets java script localized string. </summary>
/// <param name="phrase"> The phrase. </param>
/// <returns> The java script localized string. </returns>
public static string GetJavaScriptLocalizedString(string phrase)
{
var dictionary = BaseItem.LocalizationManager.GetJavaScriptLocalizationDictionary(BaseItem.ConfigurationManager.Configuration.UICulture);
string value;
if (dictionary.TryGetValue(phrase, out value))
{
return value;
}
return phrase;
}
/// <summary> Gets report view type. </summary>
/// <param name="rowType"> The type. </param>
/// <returns> The report view type. </returns>
public static ReportViewType GetReportViewType(string rowType)
{
if (string.IsNullOrEmpty(rowType))
return ReportViewType.ReportData;
ReportViewType rType;
if (!Enum.TryParse<ReportViewType>(rowType, out rType))
return ReportViewType.ReportData;
return rType;
}
/// <summary> Gets row type. </summary>
/// <param name="rowType"> The type. </param>
/// <returns> The row type. </returns>
public static ReportIncludeItemTypes GetRowType(string rowType)
{
if (string.IsNullOrEmpty(rowType))
return ReportIncludeItemTypes.BaseItem;
ReportIncludeItemTypes rType;
if (!Enum.TryParse<ReportIncludeItemTypes>(rowType, out rType))
return ReportIncludeItemTypes.BaseItem;
return rType;
}
/// <summary> Gets server localized string. </summary>
/// <param name="phrase"> The phrase. </param>
/// <returns> The server localized string. </returns>
public static string GetServerLocalizedString(string phrase)
{
return BaseItem.LocalizationManager.GetLocalizedString(phrase, BaseItem.ConfigurationManager.Configuration.UICulture);
}
#endregion
}
} }

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Api.Reports
{
public enum ReportIncludeItemTypes
{
MusicArtist,
MusicAlbum,
Book,
BoxSet,
Episode,
Game,
Video,
Movie,
MusicVideo,
Trailer,
Season,
Series,
Audio,
BaseItem,
Artist
}
}

@ -6,20 +6,9 @@ namespace MediaBrowser.Api.Reports
{ {
public enum ReportViewType public enum ReportViewType
{ {
MusicArtist, ReportData,
MusicAlbum, ReportStatistics,
Book, ReportActivities
BoxSet,
Episode,
Game,
Video,
Movie,
MusicVideo,
Trailer,
Season,
Series,
Audio,
BaseItem,
Artist
} }
} }

@ -17,162 +17,89 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.Reports namespace MediaBrowser.Api.Reports
{ {
/// <summary> A report builder. </summary> /// <summary> A report builder. </summary>
/// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/> /// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
public class ReportBuilder : ReportBuilderBase public class ReportBuilder : ReportBuilderBase
{ {
/// <summary> #region [Constructors]
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilder class. </summary>
/// <param name="libraryManager"> Manager for library. </param> /// <summary>
public ReportBuilder(ILibraryManager libraryManager) /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilder class. </summary>
: base(libraryManager) /// <param name="libraryManager"> Manager for library. </param>
{ public ReportBuilder(ILibraryManager libraryManager)
} : base(libraryManager)
{
private Func<bool, string> GetBoolString = s => s == true ? "x" : ""; }
public ReportResult GetReportResult(BaseItem[] items, ReportViewType reportRowType, BaseReportRequest request) #endregion
{
List<HeaderMetadata> headersMetadata = this.GetFilteredReportHeaderMetadata(reportRowType, request); #region [Public Methods]
var headers = GetReportHeaders(reportRowType, headersMetadata); /// <summary> Gets report result. </summary>
var rows = GetReportRows(items, headersMetadata); /// <param name="items"> The items. </param>
/// <param name="request"> The request. </param>
ReportResult result = new ReportResult { Headers = headers }; /// <returns> The report result. </returns>
HeaderMetadata groupBy = ReportHelper.GetHeaderMetadataType(request.GroupBy); public ReportResult GetResult(BaseItem[] items, IReportsQuery request)
int i = headers.FindIndex(x => x.FieldName == groupBy); {
if (groupBy != HeaderMetadata.None && i > 0) ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
{ List<ReportOptions<BaseItem>> options = this.GetReportOptions<BaseItem>(request,
var rowsGroup = rows.SelectMany(x => x.Columns[i].Name.Split(';'), (x, g) => new { Genre = g.Trim(), Rows = x }) () => this.GetDefaultHeaderMetadata(reportRowType),
.GroupBy(x => x.Genre) (hm) => this.GetOption(hm)).Where(x => x.Header.Visible == true).ToList();
.OrderBy(x => x.Key)
.Select(x => new ReportGroup { Name = x.Key, Rows = x.Select(r => r.Rows).ToList() }); var headers = GetHeaders<BaseItem>(options);
var rows = GetReportRows(items, options);
result.Groups = rowsGroup.ToList();
result.IsGrouped = true; ReportResult result = new ReportResult { Headers = headers };
} HeaderMetadata groupBy = ReportHelper.GetHeaderMetadataType(request.GroupBy);
else int i = headers.FindIndex(x => x.FieldName == groupBy);
{ if (groupBy != HeaderMetadata.None && i >= 0)
result.Rows = rows; {
result.IsGrouped = false; var rowsGroup = rows.SelectMany(x => x.Columns[i].Name.Split(';'), (x, g) => new { Group = g.Trim(), Rows = x })
} .GroupBy(x => x.Group)
.OrderBy(x => x.Key)
return result; .Select(x => new ReportGroup { Name = x.Key, Rows = x.Select(r => r.Rows).ToList() });
}
result.Groups = rowsGroup.ToList();
public List<ReportHeader> GetReportHeaders(ReportViewType reportRowType, BaseReportRequest request) result.IsGrouped = true;
{ }
List<ReportHeader> headersMetadata = this.GetReportHeaders(reportRowType); else
if (request != null && !string.IsNullOrEmpty(request.ReportColumns)) {
{ result.Rows = rows;
List<HeaderMetadata> headersMetadataFiltered = this.GetFilteredReportHeaderMetadata(reportRowType, request); result.IsGrouped = false;
foreach (ReportHeader reportHeader in headersMetadata) }
{
if (!headersMetadataFiltered.Contains(reportHeader.FieldName)) return result;
{ }
reportHeader.Visible = false;
} #endregion
}
#region [Protected Internal Methods]
} /// <summary> Gets the headers. </summary>
/// <typeparam name="H"> Type of the header. </typeparam>
return headersMetadata; /// <param name="request"> The request. </param>
} /// <returns> The headers. </returns>
/// <seealso cref="M:MediaBrowser.Api.Reports.ReportBuilderBase.GetHeaders{H}(H)"/>
public List<ReportHeader> GetReportHeaders(ReportViewType reportRowType, List<HeaderMetadata> headersMetadata = null) protected internal override List<ReportHeader> GetHeaders<H>(H request)
{ {
if (headersMetadata == null) ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
headersMetadata = this.GetDefaultReportHeaderMetadata(reportRowType); return this.GetHeaders<BaseItem>(request, () => this.GetDefaultHeaderMetadata(reportRowType), (hm) => this.GetOption(hm));
}
List<ReportOptions<BaseItem>> options = new List<ReportOptions<BaseItem>>();
foreach (HeaderMetadata header in headersMetadata) #endregion
{
options.Add(GetReportOption(header)); #region [Private Methods]
}
/// <summary> Gets default report header metadata. </summary>
/// <param name="reportIncludeItemTypes"> Type of the report row. </param>
List<ReportHeader> headers = new List<ReportHeader>(); /// <returns> The default report header metadata. </returns>
foreach (ReportOptions<BaseItem> option in options) private List<HeaderMetadata> GetDefaultHeaderMetadata(ReportIncludeItemTypes reportIncludeItemTypes)
{ {
headers.Add(option.Header); switch (reportIncludeItemTypes)
} {
return headers; case ReportIncludeItemTypes.Season:
} return new List<HeaderMetadata>
private List<ReportRow> GetReportRows(IEnumerable<BaseItem> items, List<HeaderMetadata> headersMetadata)
{
List<ReportOptions<BaseItem>> options = new List<ReportOptions<BaseItem>>();
foreach (HeaderMetadata header in headersMetadata)
{
options.Add(GetReportOption(header));
}
var rows = new List<ReportRow>();
foreach (BaseItem item in items)
{
ReportRow rRow = GetRow(item);
foreach (ReportOptions<BaseItem> option in options)
{
object itemColumn = option.Column != null ? option.Column(item, rRow) : "";
object itemId = option.ItemID != null ? option.ItemID(item) : "";
ReportItem rItem = new ReportItem
{
Name = ReportHelper.ConvertToString(itemColumn, option.Header.HeaderFieldType),
Id = ReportHelper.ConvertToString(itemId, ReportFieldType.Object)
};
rRow.Columns.Add(rItem);
}
rows.Add(rRow);
}
return rows;
}
/// <summary> Gets a row. </summary>
/// <param name="item"> The item. </param>
/// <returns> The row. </returns>
private ReportRow GetRow(BaseItem item)
{
var hasTrailers = item as IHasTrailers;
var hasSpecialFeatures = item as IHasSpecialFeatures;
var video = item as Video;
ReportRow rRow = new ReportRow
{
Id = item.Id.ToString("N"),
HasLockData = item.IsLocked,
IsUnidentified = item.IsUnidentified,
HasLocalTrailer = hasTrailers != null ? hasTrailers.GetTrailerIds().Count() > 0 : false,
HasImageTagsPrimary = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Primary) > 0),
HasImageTagsBackdrop = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Backdrop) > 0),
HasImageTagsLogo = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Logo) > 0),
HasSpecials = hasSpecialFeatures != null ? hasSpecialFeatures.SpecialFeatureIds.Count > 0 : false,
HasSubtitles = video != null ? video.HasSubtitles : false,
RowType = ReportHelper.GetRowType(item.GetClientTypeName())
};
return rRow;
}
public List<HeaderMetadata> GetFilteredReportHeaderMetadata(ReportViewType reportRowType, BaseReportRequest request)
{
if (request != null && !string.IsNullOrEmpty(request.ReportColumns))
{
var s = request.ReportColumns.Split('|').Select(x => ReportHelper.GetHeaderMetadataType(x)).Where(x => x != HeaderMetadata.None);
return s.ToList();
}
else
return this.GetDefaultReportHeaderMetadata(reportRowType);
}
public List<HeaderMetadata> GetDefaultReportHeaderMetadata(ReportViewType reportRowType)
{
switch (reportRowType)
{
case ReportViewType.Season:
return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Series, HeaderMetadata.Series,
@ -183,8 +110,8 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Genres HeaderMetadata.Genres
}; };
case ReportViewType.Series: case ReportIncludeItemTypes.Series:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Name, HeaderMetadata.Name,
@ -199,8 +126,8 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Specials HeaderMetadata.Specials
}; };
case ReportViewType.MusicAlbum: case ReportIncludeItemTypes.MusicAlbum:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Name, HeaderMetadata.Name,
@ -212,8 +139,8 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Genres HeaderMetadata.Genres
}; };
case ReportViewType.MusicArtist: case ReportIncludeItemTypes.MusicArtist:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.MusicArtist, HeaderMetadata.MusicArtist,
@ -223,8 +150,8 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Genres HeaderMetadata.Genres
}; };
case ReportViewType.Game: case ReportIncludeItemTypes.Game:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Name, HeaderMetadata.Name,
@ -239,8 +166,8 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Trailers HeaderMetadata.Trailers
}; };
case ReportViewType.Movie: case ReportIncludeItemTypes.Movie:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Name, HeaderMetadata.Name,
@ -259,8 +186,8 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Specials HeaderMetadata.Specials
}; };
case ReportViewType.Book: case ReportIncludeItemTypes.Book:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Name, HeaderMetadata.Name,
@ -272,8 +199,8 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.CommunityRating HeaderMetadata.CommunityRating
}; };
case ReportViewType.BoxSet: case ReportIncludeItemTypes.BoxSet:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Name, HeaderMetadata.Name,
@ -286,8 +213,8 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Trailers HeaderMetadata.Trailers
}; };
case ReportViewType.Audio: case ReportIncludeItemTypes.Audio:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Name, HeaderMetadata.Name,
@ -305,8 +232,8 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Audio HeaderMetadata.Audio
}; };
case ReportViewType.Episode: case ReportIncludeItemTypes.Episode:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Name, HeaderMetadata.Name,
@ -327,12 +254,12 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Specials HeaderMetadata.Specials
}; };
case ReportViewType.Video: case ReportIncludeItemTypes.Video:
case ReportViewType.MusicVideo: case ReportIncludeItemTypes.MusicVideo:
case ReportViewType.Trailer: case ReportIncludeItemTypes.Trailer:
case ReportViewType.BaseItem: case ReportIncludeItemTypes.BaseItem:
default: default:
return new List<HeaderMetadata> return new List<HeaderMetadata>
{ {
HeaderMetadata.StatusImage, HeaderMetadata.StatusImage,
HeaderMetadata.Name, HeaderMetadata.Name,
@ -351,239 +278,282 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Specials HeaderMetadata.Specials
}; };
} }
} }
/// <summary> Gets report option. </summary> /// <summary> Gets report option. </summary>
/// <param name="header"> The header. </param> /// <param name="header"> The header. </param>
/// <param name="sortField"> The sort field. </param> /// <param name="sortField"> The sort field. </param>
/// <returns> The report option. </returns> /// <returns> The report option. </returns>
private ReportOptions<BaseItem> GetReportOption(HeaderMetadata header, string sortField = "") private ReportOptions<BaseItem> GetOption(HeaderMetadata header, string sortField = "")
{ {
ReportHeader reportHeader = new ReportHeader HeaderMetadata internalHeader = header;
{
HeaderFieldType = ReportFieldType.String, ReportOptions<BaseItem> option = new ReportOptions<BaseItem>()
SortField = sortField, {
Type = "", Header = new ReportHeader
ItemViewType = ItemViewType.None {
}; HeaderFieldType = ReportFieldType.String,
SortField = sortField,
Func<BaseItem, ReportRow, object> column = null; Type = "",
Func<BaseItem, object> itemId = null; ItemViewType = ItemViewType.None
HeaderMetadata internalHeader = header; }
};
switch (header)
{ switch (header)
case HeaderMetadata.StatusImage: {
reportHeader.ItemViewType = ItemViewType.StatusImage; case HeaderMetadata.StatusImage:
internalHeader = HeaderMetadata.Status; option.Header.ItemViewType = ItemViewType.StatusImage;
reportHeader.CanGroup = false; internalHeader = HeaderMetadata.Status;
break; option.Header.CanGroup = false;
break;
case HeaderMetadata.Name:
column = (i, r) => i.Name; case HeaderMetadata.Name:
reportHeader.ItemViewType = ItemViewType.Detail; option.Column = (i, r) => i.Name;
reportHeader.SortField = "SortName"; option.Header.ItemViewType = ItemViewType.Detail;
break; option.Header.SortField = "SortName";
break;
case HeaderMetadata.DateAdded:
column = (i, r) => i.DateCreated; case HeaderMetadata.DateAdded:
reportHeader.SortField = "DateCreated,SortName"; option.Column = (i, r) => i.DateCreated;
reportHeader.HeaderFieldType = ReportFieldType.DateTime; option.Header.SortField = "DateCreated,SortName";
reportHeader.Type = ""; option.Header.HeaderFieldType = ReportFieldType.DateTime;
break; option.Header.Type = "";
break;
case HeaderMetadata.PremiereDate:
case HeaderMetadata.ReleaseDate: case HeaderMetadata.PremiereDate:
column = (i, r) => i.PremiereDate; case HeaderMetadata.ReleaseDate:
reportHeader.HeaderFieldType = ReportFieldType.DateTime; option.Column = (i, r) => i.PremiereDate;
reportHeader.SortField = "ProductionYear,PremiereDate,SortName"; option.Header.HeaderFieldType = ReportFieldType.DateTime;
break; option.Header.SortField = "ProductionYear,PremiereDate,SortName";
break;
case HeaderMetadata.Runtime:
column = (i, r) => this.GetRuntimeDateTime(i.RunTimeTicks); case HeaderMetadata.Runtime:
reportHeader.HeaderFieldType = ReportFieldType.Minutes; option.Column = (i, r) => this.GetRuntimeDateTime(i.RunTimeTicks);
reportHeader.SortField = "Runtime,SortName"; option.Header.HeaderFieldType = ReportFieldType.Minutes;
break; option.Header.SortField = "Runtime,SortName";
break;
case HeaderMetadata.PlayCount:
reportHeader.HeaderFieldType = ReportFieldType.Int; case HeaderMetadata.PlayCount:
break; option.Header.HeaderFieldType = ReportFieldType.Int;
break;
case HeaderMetadata.Season:
column = (i, r) => this.GetEpisode(i); case HeaderMetadata.Season:
reportHeader.ItemViewType = ItemViewType.Detail; option.Column = (i, r) => this.GetEpisode(i);
reportHeader.SortField = "SortName"; option.Header.ItemViewType = ItemViewType.Detail;
break; option.Header.SortField = "SortName";
break;
case HeaderMetadata.SeasonNumber:
column = (i, r) => this.GetObject<Season, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString()); case HeaderMetadata.SeasonNumber:
reportHeader.SortField = "IndexNumber"; option.Column = (i, r) => this.GetObject<Season, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString());
reportHeader.HeaderFieldType = ReportFieldType.Int; option.Header.SortField = "IndexNumber";
break; option.Header.HeaderFieldType = ReportFieldType.Int;
break;
case HeaderMetadata.Series:
column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName); case HeaderMetadata.Series:
reportHeader.ItemViewType = ItemViewType.Detail; option.Column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
reportHeader.SortField = "SeriesSortName,SortName"; option.Header.ItemViewType = ItemViewType.Detail;
break; option.Header.SortField = "SeriesSortName,SortName";
break;
case HeaderMetadata.EpisodeSeries:
column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName); case HeaderMetadata.EpisodeSeries:
reportHeader.ItemViewType = ItemViewType.Detail; option.Column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
itemId = (i) => option.Header.ItemViewType = ItemViewType.Detail;
{ option.ItemID = (i) =>
Series series = this.GetObject<Episode, Series>(i, (x) => x.Series); {
if (series == null) Series series = this.GetObject<Episode, Series>(i, (x) => x.Series);
return string.Empty; if (series == null)
return series.Id; return string.Empty;
}; return series.Id;
reportHeader.SortField = "SeriesSortName,SortName"; };
internalHeader = HeaderMetadata.Series; option.Header.SortField = "SeriesSortName,SortName";
break; internalHeader = HeaderMetadata.Series;
break;
case HeaderMetadata.EpisodeSeason:
column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName); case HeaderMetadata.EpisodeSeason:
reportHeader.ItemViewType = ItemViewType.Detail; option.Column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
itemId = (i) => option.Header.ItemViewType = ItemViewType.Detail;
{ option.ItemID = (i) =>
Season season = this.GetObject<Episode, Season>(i, (x) => x.Season); {
if (season == null) Season season = this.GetObject<Episode, Season>(i, (x) => x.Season);
return string.Empty; if (season == null)
return season.Id; return string.Empty;
}; return season.Id;
reportHeader.SortField = "SortName"; };
internalHeader = HeaderMetadata.Season; option.Header.SortField = "SortName";
break; internalHeader = HeaderMetadata.Season;
break;
case HeaderMetadata.Network:
column = (i, r) => this.GetListAsString(i.Studios); case HeaderMetadata.Network:
itemId = (i) => this.GetStudioID(i.Studios.FirstOrDefault()); option.Column = (i, r) => this.GetListAsString(i.Studios);
reportHeader.ItemViewType = ItemViewType.ItemByNameDetails; option.ItemID = (i) => this.GetStudioID(i.Studios.FirstOrDefault());
reportHeader.SortField = "Studio,SortName"; option.Header.ItemViewType = ItemViewType.ItemByNameDetails;
break; option.Header.SortField = "Studio,SortName";
break;
case HeaderMetadata.Year:
column = (i, r) => this.GetSeriesProductionYear(i); case HeaderMetadata.Year:
reportHeader.SortField = "ProductionYear,PremiereDate,SortName"; option.Column = (i, r) => this.GetSeriesProductionYear(i);
break; option.Header.SortField = "ProductionYear,PremiereDate,SortName";
break;
case HeaderMetadata.ParentalRating:
column = (i, r) => i.OfficialRating; case HeaderMetadata.ParentalRating:
reportHeader.SortField = "OfficialRating,SortName"; option.Column = (i, r) => i.OfficialRating;
break; option.Header.SortField = "OfficialRating,SortName";
break;
case HeaderMetadata.CommunityRating:
column = (i, r) => i.CommunityRating; case HeaderMetadata.CommunityRating:
reportHeader.SortField = "CommunityRating,SortName"; option.Column = (i, r) => i.CommunityRating;
break; option.Header.SortField = "CommunityRating,SortName";
break;
case HeaderMetadata.Trailers:
column = (i, r) => this.GetBoolString(r.HasLocalTrailer); case HeaderMetadata.Trailers:
reportHeader.ItemViewType = ItemViewType.TrailersImage; option.Column = (i, r) => this.GetBoolString(r.HasLocalTrailer);
break; option.Header.ItemViewType = ItemViewType.TrailersImage;
break;
case HeaderMetadata.Specials:
column = (i, r) => this.GetBoolString(r.HasSpecials); case HeaderMetadata.Specials:
reportHeader.ItemViewType = ItemViewType.SpecialsImage; option.Column = (i, r) => this.GetBoolString(r.HasSpecials);
break; option.Header.ItemViewType = ItemViewType.SpecialsImage;
break;
case HeaderMetadata.GameSystem:
column = (i, r) => this.GetObject<Game, string>(i, (x) => x.GameSystem); case HeaderMetadata.GameSystem:
reportHeader.SortField = "GameSystem,SortName"; option.Column = (i, r) => this.GetObject<Game, string>(i, (x) => x.GameSystem);
break; option.Header.SortField = "GameSystem,SortName";
break;
case HeaderMetadata.Players:
column = (i, r) => this.GetObject<Game, int?>(i, (x) => x.PlayersSupported); case HeaderMetadata.Players:
reportHeader.SortField = "Players,GameSystem,SortName"; option.Column = (i, r) => this.GetObject<Game, int?>(i, (x) => x.PlayersSupported);
break; option.Header.SortField = "Players,GameSystem,SortName";
break;
case HeaderMetadata.AlbumArtist:
column = (i, r) => this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist); case HeaderMetadata.AlbumArtist:
itemId = (i) => this.GetPersonID(this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist)); option.Column = (i, r) => this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist);
reportHeader.ItemViewType = ItemViewType.Detail; option.ItemID = (i) => this.GetPersonID(this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist));
reportHeader.SortField = "AlbumArtist,Album,SortName"; option.Header.ItemViewType = ItemViewType.Detail;
option.Header.SortField = "AlbumArtist,Album,SortName";
break;
case HeaderMetadata.MusicArtist: break;
column = (i, r) => this.GetObject<MusicArtist, string>(i, (x) => x.GetLookupInfo().Name); case HeaderMetadata.MusicArtist:
reportHeader.ItemViewType = ItemViewType.Detail; option.Column = (i, r) => this.GetObject<MusicArtist, string>(i, (x) => x.GetLookupInfo().Name);
reportHeader.SortField = "AlbumArtist,Album,SortName"; option.Header.ItemViewType = ItemViewType.Detail;
internalHeader = HeaderMetadata.AlbumArtist; option.Header.SortField = "AlbumArtist,Album,SortName";
break; internalHeader = HeaderMetadata.AlbumArtist;
case HeaderMetadata.AudioAlbumArtist: break;
column = (i, r) => this.GetListAsString(this.GetObject<Audio, List<string>>(i, (x) => x.AlbumArtists)); case HeaderMetadata.AudioAlbumArtist:
reportHeader.SortField = "AlbumArtist,Album,SortName"; option.Column = (i, r) => this.GetListAsString(this.GetObject<Audio, List<string>>(i, (x) => x.AlbumArtists));
internalHeader = HeaderMetadata.AlbumArtist; option.Header.SortField = "AlbumArtist,Album,SortName";
break; internalHeader = HeaderMetadata.AlbumArtist;
break;
case HeaderMetadata.AudioAlbum:
column = (i, r) => this.GetObject<Audio, string>(i, (x) => x.Album); case HeaderMetadata.AudioAlbum:
reportHeader.SortField = "Album,SortName"; option.Column = (i, r) => this.GetObject<Audio, string>(i, (x) => x.Album);
internalHeader = HeaderMetadata.Album; option.Header.SortField = "Album,SortName";
break; internalHeader = HeaderMetadata.Album;
break;
case HeaderMetadata.Countries:
column = (i, r) => this.GetListAsString(this.GetObject<IHasProductionLocations, List<string>>(i, (x) => x.ProductionLocations)); case HeaderMetadata.Countries:
break; option.Column = (i, r) => this.GetListAsString(this.GetObject<IHasProductionLocations, List<string>>(i, (x) => x.ProductionLocations));
break;
case HeaderMetadata.Disc:
column = (i, r) => i.ParentIndexNumber; case HeaderMetadata.Disc:
break; option.Column = (i, r) => i.ParentIndexNumber;
break;
case HeaderMetadata.Track:
column = (i, r) => i.IndexNumber; case HeaderMetadata.Track:
break; option.Column = (i, r) => i.IndexNumber;
break;
case HeaderMetadata.Tracks:
column = (i, r) => this.GetObject<MusicAlbum, List<Audio>>(i, (x) => x.Tracks.ToList(), new List<Audio>()).Count(); case HeaderMetadata.Tracks:
break; option.Column = (i, r) => this.GetObject<MusicAlbum, List<Audio>>(i, (x) => x.Tracks.ToList(), new List<Audio>()).Count();
break;
case HeaderMetadata.Audio:
column = (i, r) => this.GetAudioStream(i); case HeaderMetadata.Audio:
break; option.Column = (i, r) => this.GetAudioStream(i);
break;
case HeaderMetadata.EmbeddedImage:
break; case HeaderMetadata.EmbeddedImage:
break;
case HeaderMetadata.Video:
column = (i, r) => this.GetVideoStream(i); case HeaderMetadata.Video:
break; option.Column = (i, r) => this.GetVideoStream(i);
break;
case HeaderMetadata.Resolution:
column = (i, r) => this.GetVideoResolution(i); case HeaderMetadata.Resolution:
break; option.Column = (i, r) => this.GetVideoResolution(i);
break;
case HeaderMetadata.Subtitles:
column = (i, r) => this.GetBoolString(r.HasSubtitles); case HeaderMetadata.Subtitles:
reportHeader.ItemViewType = ItemViewType.SubtitleImage; option.Column = (i, r) => this.GetBoolString(r.HasSubtitles);
break; option.Header.ItemViewType = ItemViewType.SubtitleImage;
break;
case HeaderMetadata.Genres:
column = (i, r) => this.GetListAsString(i.Genres); case HeaderMetadata.Genres:
break; option.Column = (i, r) => this.GetListAsString(i.Genres);
break;
}
}
string headerName = "";
if (internalHeader != HeaderMetadata.None) option.Header.Name = GetLocalizedHeader(internalHeader);
{ option.Header.FieldName = header;
string localHeader = "Header" + internalHeader.ToString();
headerName = internalHeader != HeaderMetadata.None ? ReportHelper.GetJavaScriptLocalizedString(localHeader) : ""; return option;
if (string.Compare(localHeader, headerName, StringComparison.CurrentCultureIgnoreCase) == 0) }
headerName = ReportHelper.GetServerLocalizedString(localHeader);
} /// <summary> Gets report rows. </summary>
/// <param name="items"> The items. </param>
reportHeader.Name = headerName; /// <param name="options"> Options for controlling the operation. </param>
reportHeader.FieldName = header; /// <returns> The report rows. </returns>
ReportOptions<BaseItem> option = new ReportOptions<BaseItem>() private List<ReportRow> GetReportRows(IEnumerable<BaseItem> items, List<ReportOptions<BaseItem>> options)
{ {
Header = reportHeader, var rows = new List<ReportRow>();
Column = column,
ItemID = itemId foreach (BaseItem item in items)
}; {
return option; ReportRow rRow = GetRow(item);
} foreach (ReportOptions<BaseItem> option in options)
} {
object itemColumn = option.Column != null ? option.Column(item, rRow) : "";
object itemId = option.ItemID != null ? option.ItemID(item) : "";
ReportItem rItem = new ReportItem
{
Name = ReportHelper.ConvertToString(itemColumn, option.Header.HeaderFieldType),
Id = ReportHelper.ConvertToString(itemId, ReportFieldType.Object)
};
rRow.Columns.Add(rItem);
}
rows.Add(rRow);
}
return rows;
}
/// <summary> Gets a row. </summary>
/// <param name="item"> The item. </param>
/// <returns> The row. </returns>
private ReportRow GetRow(BaseItem item)
{
var hasTrailers = item as IHasTrailers;
var hasSpecialFeatures = item as IHasSpecialFeatures;
var video = item as Video;
ReportRow rRow = new ReportRow
{
Id = item.Id.ToString("N"),
HasLockData = item.IsLocked,
IsUnidentified = item.IsUnidentified,
HasLocalTrailer = hasTrailers != null ? hasTrailers.GetTrailerIds().Count() > 0 : false,
HasImageTagsPrimary = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Primary) > 0),
HasImageTagsBackdrop = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Backdrop) > 0),
HasImageTagsLogo = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Logo) > 0),
HasSpecials = hasSpecialFeatures != null ? hasSpecialFeatures.SpecialFeatureIds.Count > 0 : false,
HasSubtitles = video != null ? video.HasSubtitles : false,
RowType = ReportHelper.GetRowType(item.GetClientTypeName())
};
return rRow;
}
#endregion
}
} }

@ -7,8 +7,9 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.Reports namespace MediaBrowser.Api.Reports
{ {
/// <summary> A report options. </summary> /// <summary> A report options. </summary>
internal class ReportOptions<I> public class ReportOptions<I>
{ {
/// <summary> Initializes a new instance of the ReportOptions class. </summary> /// <summary> Initializes a new instance of the ReportOptions class. </summary>
public ReportOptions() public ReportOptions()

@ -66,6 +66,6 @@ namespace MediaBrowser.Api.Reports
/// <summary> Gets or sets the type. </summary> /// <summary> Gets or sets the type. </summary>
/// <value> The type. </value> /// <value> The type. </value>
public ReportViewType RowType { get; set; } public ReportIncludeItemTypes RowType { get; set; }
} }
} }

@ -7,8 +7,80 @@ using System.Linq;
namespace MediaBrowser.Api.Reports namespace MediaBrowser.Api.Reports
{ {
public class BaseReportRequest : BaseItemsRequest public interface IReportsDownload : IReportsQuery
{ {
/// <summary> Gets or sets the minimum date. </summary>
/// <value> The minimum date. </value>
string MinDate { get; set; }
}
/// <summary> Interface for reports query. </summary>
public interface IReportsQuery : IReportsHeader
{
/// <summary>
/// Gets or sets a value indicating whether this MediaBrowser.Api.Reports.GetActivityLogs has
/// query limit. </summary>
/// <value>
/// true if this MediaBrowser.Api.Reports.GetActivityLogs has query limit, false if not. </value>
bool HasQueryLimit { get; set; }
/// <summary> Gets or sets who group this MediaBrowser.Api.Reports.GetActivityLogs. </summary>
/// <value> Describes who group this MediaBrowser.Api.Reports.GetActivityLogs. </value>
string GroupBy { get; set; }
/// <summary>
/// Skips over a given number of items within the results. Use for paging.
/// </summary>
/// <value>The start index.</value>
int? StartIndex { get; set; }
/// <summary>
/// The maximum number of items to return
/// </summary>
/// <value>The limit.</value>
int? Limit { get; set; }
}
public interface IReportsHeader
{
/// <summary> Gets or sets the report view. </summary>
/// <value> The report view. </value>
string ReportView { get; set; }
/// <summary> Gets or sets the report columns. </summary>
/// <value> The report columns. </value>
string ReportColumns { get; set; }
/// <summary> Gets or sets a list of types of the include items. </summary>
/// <value> A list of types of the include items. </value>
string IncludeItemTypes { get; set; }
}
public class BaseReportRequest : BaseItemsRequest, IReportsQuery
{
/// <summary> Gets or sets the report view. </summary>
/// <value> The report view. </value>
[ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ReportView { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this MediaBrowser.Api.Reports.BaseReportRequest has
/// query limit. </summary>
/// <value>
/// true if this MediaBrowser.Api.Reports.BaseReportRequest has query limit, false if not. </value>
[ApiMember(Name = "HasQueryLimit", Description = "Optional. If specified, results will include all records.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool HasQueryLimit { get; set; }
/// <summary>
/// Gets or sets who group this MediaBrowser.Api.Reports.BaseReportRequest. </summary>
/// <value> Describes who group this MediaBrowser.Api.Reports.BaseReportRequest. </value>
[ApiMember(Name = "GroupBy", Description = "Optional. If specified, results will include grouped records.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string GroupBy { get; set; }
/// <summary> Gets or sets the report columns. </summary>
/// <value> The report columns. </value>
[ApiMember(Name = "ReportColumns", Description = "Optional. The columns to show.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ReportColumns { get; set; }
/// <summary> /// <summary>
/// Gets or sets the user id. /// Gets or sets the user id.
/// </summary> /// </summary>
@ -63,11 +135,6 @@ namespace MediaBrowser.Api.Reports
[ApiMember(Name = "Ids", Description = "Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Ids", Description = "Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Ids { get; set; } public string Ids { get; set; }
public bool HasQueryLimit { get; set; }
public string GroupBy { get; set; }
public string ReportColumns { get; set; }
/// <summary> /// <summary>
/// Gets or sets the video types. /// Gets or sets the video types.
/// </summary> /// </summary>
@ -261,8 +328,22 @@ namespace MediaBrowser.Api.Reports
} }
[Route("/Reports/Headers", "GET", Summary = "Gets reports headers based on library items")] [Route("/Reports/Headers", "GET", Summary = "Gets reports headers based on library items")]
public class GetReportHeaders : BaseReportRequest, IReturn<List<ReportHeader>> public class GetReportHeaders : IReturn<List<ReportHeader>>, IReportsHeader
{ {
/// <summary> Gets or sets the report view. </summary>
/// <value> The report view. </value>
[ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ReportView { get; set; }
/// <summary> Gets or sets a list of types of the include items. </summary>
/// <value> A list of types of the include items. </value>
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string IncludeItemTypes { get; set; }
/// <summary> Gets or sets the report columns. </summary>
/// <value> The report columns. </value>
[ApiMember(Name = "ReportColumns", Description = "Optional. The columns to show.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ReportColumns { get; set; }
} }
[Route("/Reports/Statistics", "GET", Summary = "Gets reports statistics based on library items")] [Route("/Reports/Statistics", "GET", Summary = "Gets reports statistics based on library items")]
@ -273,7 +354,7 @@ namespace MediaBrowser.Api.Reports
} }
[Route("/Reports/Items/Download", "GET", Summary = "Downloads report")] [Route("/Reports/Items/Download", "GET", Summary = "Downloads report")]
public class GetReportDownload : BaseReportRequest public class GetReportDownload : BaseReportRequest, IReportsDownload
{ {
public GetReportDownload() public GetReportDownload()
{ {
@ -281,6 +362,61 @@ namespace MediaBrowser.Api.Reports
} }
public ReportExportType ExportType { get; set; } public ReportExportType ExportType { get; set; }
/// <summary> Gets or sets the minimum date. </summary>
/// <value> The minimum date. </value>
[ApiMember(Name = "MinDate", Description = "Optional. The minimum date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public string MinDate { get; set; }
} }
[Route("/Reports/Activities", "GET", Summary = "Gets activities entries")]
public class GetActivityLogs : IReturn<ReportResult>, IReportsQuery, IReportsDownload
{
/// <summary> Gets or sets the report view. </summary>
/// <value> The report view. </value>
[ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ReportView { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this MediaBrowser.Api.Reports.GetActivityLogs has
/// query limit. </summary>
/// <value>
/// true if this MediaBrowser.Api.Reports.GetActivityLogs has query limit, false if not. </value>
[ApiMember(Name = "HasQueryLimit", Description = "Optional. If specified, results will include all records.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool HasQueryLimit { get; set; }
/// <summary> Gets or sets who group this MediaBrowser.Api.Reports.GetActivityLogs. </summary>
/// <value> Describes who group this MediaBrowser.Api.Reports.GetActivityLogs. </value>
[ApiMember(Name = "GroupBy", Description = "Optional. If specified, results will include grouped records.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string GroupBy { get; set; }
/// <summary> Gets or sets the report columns. </summary>
/// <value> The report columns. </value>
[ApiMember(Name = "ReportColumns", Description = "Optional. The columns to show.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ReportColumns { get; set; }
/// <summary>
/// Skips over a given number of items within the results. Use for paging.
/// </summary>
/// <value>The start index.</value>
[ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? StartIndex { get; set; }
/// <summary>
/// The maximum number of items to return
/// </summary>
/// <value>The limit.</value>
[ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? Limit { get; set; }
/// <summary> Gets or sets the minimum date. </summary>
/// <value> The minimum date. </value>
[ApiMember(Name = "MinDate", Description = "Optional. The minimum date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public string MinDate { get; set; }
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string IncludeItemTypes { get; set; }
}
} }

File diff suppressed because it is too large Load Diff

@ -9,206 +9,266 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.Reports namespace MediaBrowser.Api.Reports
{ {
/// <summary> A report stat builder. </summary> /// <summary> A report stat builder. </summary>
/// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/> /// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
public class ReportStatBuilder : ReportBuilderBase public class ReportStatBuilder : ReportBuilderBase
{ {
/// <summary> #region [Constructors]
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatBuilder class. </summary>
/// <param name="libraryManager"> Manager for library. </param> /// <summary>
public ReportStatBuilder(ILibraryManager libraryManager) /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatBuilder class. </summary>
: base(libraryManager) /// <param name="libraryManager"> Manager for library. </param>
{ public ReportStatBuilder(ILibraryManager libraryManager)
} : base(libraryManager)
{
/// <summary> Gets report stat result. </summary> }
/// <param name="items"> The items. </param>
/// <param name="reportRowType"> Type of the report row. </param> #endregion
/// <param name="topItem"> The top item. </param>
/// <returns> The report stat result. </returns> #region [Public Methods]
public ReportStatResult GetReportStatResult(BaseItem[] items, ReportViewType reportRowType, int topItem = 5)
{ /// <summary> Gets report stat result. </summary>
ReportStatResult result = new ReportStatResult(); /// <param name="items"> The items. </param>
result = this.GetResultGenres(result, items, topItem); /// <param name="reportIncludeItemTypes"> List of types of the report include items. </param>
result = this.GetResultStudios(result, items, topItem); /// <param name="topItem"> The top item. </param>
result = this.GetResultPersons(result, items, topItem); /// <returns> The report stat result. </returns>
result = this.GetResultProductionYears(result, items, topItem); public ReportStatResult GetResult(BaseItem[] items, ReportIncludeItemTypes reportIncludeItemTypes, int topItem = 5)
result = this.GetResulProductionLocations(result, items, topItem); {
result = this.GetResultCommunityRatings(result, items, topItem); ReportStatResult result = new ReportStatResult();
result = this.GetResultParentalRatings(result, items, topItem); result = this.GetResultGenres(result, items, topItem);
result = this.GetResultStudios(result, items, topItem);
switch (reportRowType) result = this.GetResultPersons(result, items, topItem);
{ result = this.GetResultProductionYears(result, items, topItem);
case ReportViewType.Season: result = this.GetResulProductionLocations(result, items, topItem);
case ReportViewType.Series: result = this.GetResultCommunityRatings(result, items, topItem);
case ReportViewType.MusicAlbum: result = this.GetResultParentalRatings(result, items, topItem);
case ReportViewType.MusicArtist:
case ReportViewType.Game: switch (reportIncludeItemTypes)
break; {
case ReportViewType.Movie: case ReportIncludeItemTypes.Season:
case ReportViewType.BoxSet: case ReportIncludeItemTypes.Series:
case ReportIncludeItemTypes.MusicAlbum:
break; case ReportIncludeItemTypes.MusicArtist:
case ReportViewType.Book: case ReportIncludeItemTypes.Game:
case ReportViewType.Episode: break;
case ReportViewType.Video: case ReportIncludeItemTypes.Movie:
case ReportViewType.MusicVideo: case ReportIncludeItemTypes.BoxSet:
case ReportViewType.Trailer:
case ReportViewType.Audio: break;
case ReportViewType.BaseItem: case ReportIncludeItemTypes.Book:
default: case ReportIncludeItemTypes.Episode:
break; case ReportIncludeItemTypes.Video:
} case ReportIncludeItemTypes.MusicVideo:
case ReportIncludeItemTypes.Trailer:
result.Groups = result.Groups.OrderByDescending(n => n.Items.Count()).ToList(); case ReportIncludeItemTypes.Audio:
case ReportIncludeItemTypes.BaseItem:
return result; default:
} break;
}
private ReportStatResult GetResultGenres(ReportStatResult result, BaseItem[] items, int topItem = 5)
{ result.Groups = result.Groups.OrderByDescending(n => n.Items.Count()).ToList();
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderGenres"), topItem,
items.SelectMany(x => x.Genres) return result;
.GroupBy(x => x) }
.OrderByDescending(x => x.Count())
.Take(topItem) #endregion
.Select(x => new ReportStatItem
{ #region [Protected Internal Methods]
Name = x.Key, /// <summary> Gets the headers. </summary>
Value = x.Count().ToString(), /// <typeparam name="H"> Type of the header. </typeparam>
Id = GetGenreID(x.Key) /// <param name="request"> The request. </param>
})); /// <returns> The headers. </returns>
return result; /// <seealso cref="M:MediaBrowser.Api.Reports.ReportBuilderBase.GetHeaders{H}(H)"/>
protected internal override List<ReportHeader> GetHeaders<H>(H request)
} {
throw new NotImplementedException();
private ReportStatResult GetResultStudios(ReportStatResult result, BaseItem[] items, int topItem = 5) }
{
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderStudios"), topItem, #endregion
items.SelectMany(x => x.Studios)
.GroupBy(x => x) #region [Private Methods]
.OrderByDescending(x => x.Count())
.Take(topItem) /// <summary> Gets the groups. </summary>
.Select(x => new ReportStatItem /// <param name="result"> The result. </param>
{ /// <param name="header"> The header. </param>
Name = x.Key, /// <param name="topItem"> The top item. </param>
Value = x.Count().ToString(), /// <param name="top"> The top. </param>
Id = GetStudioID(x.Key) private void GetGroups(ReportStatResult result, string header, int topItem, IEnumerable<ReportStatItem> top)
}) {
); if (top != null && top.Count() > 0)
{
return result; var group = new ReportStatGroup { Header = ReportStatGroup.FormatedHeader(header, topItem) };
group.Items.AddRange(top);
} result.Groups.Add(group);
}
private ReportStatResult GetResultPersons(ReportStatResult result, BaseItem[] items, int topItem = 5) }
{
List<string> t = new List<string> { PersonType.Actor, PersonType.Composer, PersonType.Director, PersonType.GuestStar, PersonType.Producer, PersonType.Writer, "Artist", "AlbumArtist" }; /// <summary> Gets resul production locations. </summary>
foreach (var item in t) /// <param name="result"> The result. </param>
{ /// <param name="items"> The items. </param>
this.GetGroups(result, ReportHelper.GetServerLocalizedString("Option" + item), topItem, /// <param name="topItem"> The top item. </param>
items.SelectMany(x => _libraryManager.GetPeople(x)) /// <returns> The resul production locations. </returns>
.Where(n => n.Type == item) private ReportStatResult GetResulProductionLocations(ReportStatResult result, BaseItem[] items, int topItem = 5)
.GroupBy(x => x.Name) {
.OrderByDescending(x => x.Count()) this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderCountries"), topItem,
.Take(topItem) items.OfType<IHasProductionLocations>()
.Select(x => new ReportStatItem .Where(x => x.ProductionLocations != null)
{ .SelectMany(x => x.ProductionLocations)
Name = x.Key, .GroupBy(x => x)
Value = x.Count().ToString(), .OrderByDescending(x => x.Count())
Id = GetPersonID(x.Key) .Take(topItem)
}) .Select(x => new ReportStatItem
); {
} Name = x.Key.ToString(),
Value = x.Count().ToString()
return result; })
} );
private ReportStatResult GetResultCommunityRatings(ReportStatResult result, BaseItem[] items, int topItem = 5) return result;
{ }
this.GetGroups(result, ReportHelper.GetServerLocalizedString("LabelCommunityRating"), topItem,
items.Where(x => x.CommunityRating != null && x.CommunityRating > 0) /// <summary> Gets result community ratings. </summary>
.GroupBy(x => x.CommunityRating) /// <param name="result"> The result. </param>
.OrderByDescending(x => x.Count()) /// <param name="items"> The items. </param>
.Take(topItem) /// <param name="topItem"> The top item. </param>
.Select(x => new ReportStatItem /// <returns> The result community ratings. </returns>
{ private ReportStatResult GetResultCommunityRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
Name = x.Key.ToString(), {
Value = x.Count().ToString() this.GetGroups(result, ReportHelper.GetServerLocalizedString("LabelCommunityRating"), topItem,
}) items.Where(x => x.CommunityRating != null && x.CommunityRating > 0)
); .GroupBy(x => x.CommunityRating)
.OrderByDescending(x => x.Count())
return result; .Take(topItem)
} .Select(x => new ReportStatItem
{
private ReportStatResult GetResultParentalRatings(ReportStatResult result, BaseItem[] items, int topItem = 5) Name = x.Key.ToString(),
{ Value = x.Count().ToString()
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderParentalRatings"), topItem, })
items.Where(x => x.OfficialRating != null) );
.GroupBy(x => x.OfficialRating)
.OrderByDescending(x => x.Count()) return result;
.Take(topItem) }
.Select(x => new ReportStatItem
{ /// <summary> Gets result genres. </summary>
Name = x.Key.ToString(), /// <param name="result"> The result. </param>
Value = x.Count().ToString() /// <param name="items"> The items. </param>
}) /// <param name="topItem"> The top item. </param>
); /// <returns> The result genres. </returns>
private ReportStatResult GetResultGenres(ReportStatResult result, BaseItem[] items, int topItem = 5)
return result; {
} this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderGenres"), topItem,
items.SelectMany(x => x.Genres)
.GroupBy(x => x)
private ReportStatResult GetResultProductionYears(ReportStatResult result, BaseItem[] items, int topItem = 5) .OrderByDescending(x => x.Count())
{ .Take(topItem)
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderYears"), topItem, .Select(x => new ReportStatItem
items.Where(x => x.ProductionYear != null && x.ProductionYear > 0) {
.GroupBy(x => x.ProductionYear) Name = x.Key,
.OrderByDescending(x => x.Count()) Value = x.Count().ToString(),
.Take(topItem) Id = GetGenreID(x.Key)
.Select(x => new ReportStatItem }));
{ return result;
Name = x.Key.ToString(),
Value = x.Count().ToString() }
})
); /// <summary> Gets result parental ratings. </summary>
/// <param name="result"> The result. </param>
return result; /// <param name="items"> The items. </param>
} /// <param name="topItem"> The top item. </param>
/// <returns> The result parental ratings. </returns>
private ReportStatResult GetResulProductionLocations(ReportStatResult result, BaseItem[] items, int topItem = 5) private ReportStatResult GetResultParentalRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
{ {
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderCountries"), topItem, this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderParentalRatings"), topItem,
items.OfType<IHasProductionLocations>() items.Where(x => x.OfficialRating != null)
.Where(x => x.ProductionLocations != null) .GroupBy(x => x.OfficialRating)
.SelectMany(x => x.ProductionLocations) .OrderByDescending(x => x.Count())
.GroupBy(x => x) .Take(topItem)
.OrderByDescending(x => x.Count()) .Select(x => new ReportStatItem
.Take(topItem) {
.Select(x => new ReportStatItem Name = x.Key.ToString(),
{ Value = x.Count().ToString()
Name = x.Key.ToString(), })
Value = x.Count().ToString() );
})
); return result;
}
return result;
} /// <summary> Gets result persons. </summary>
/// <param name="result"> The result. </param>
/// <param name="items"> The items. </param>
/// <summary> Gets the groups. </summary> /// <param name="topItem"> The top item. </param>
/// <param name="result"> The result. </param> /// <returns> The result persons. </returns>
/// <param name="header"> The header. </param> private ReportStatResult GetResultPersons(ReportStatResult result, BaseItem[] items, int topItem = 5)
/// <param name="topItem"> The top item. </param> {
/// <param name="top"> The top. </param> List<string> t = new List<string> { PersonType.Actor, PersonType.Composer, PersonType.Director, PersonType.GuestStar, PersonType.Producer, PersonType.Writer, "Artist", "AlbumArtist" };
private void GetGroups(ReportStatResult result, string header, int topItem, IEnumerable<ReportStatItem> top) foreach (var item in t)
{ {
if (top.Count() > 0) var ps = items.Where(x => x.People != null && x.SupportsPeople).SelectMany(x => x.People)
{ .Where(n => n.Type == item)
var group = new ReportStatGroup { Header = ReportStatGroup.FormatedHeader(header, topItem) }; .GroupBy(x => x.Name)
group.Items.AddRange(top); .OrderByDescending(x => x.Count())
result.Groups.Add(group); .Take(topItem);
} if (ps != null && ps.Count() > 0)
} this.GetGroups(result, ReportHelper.GetServerLocalizedString("Option" + item), topItem,
} ps.Select(x => new ReportStatItem
{
Name = x.Key,
Value = x.Count().ToString(),
Id = GetPersonID(x.Key)
})
);
}
return result;
}
/// <summary> Gets result production years. </summary>
/// <param name="result"> The result. </param>
/// <param name="items"> The items. </param>
/// <param name="topItem"> The top item. </param>
/// <returns> The result production years. </returns>
private ReportStatResult GetResultProductionYears(ReportStatResult result, BaseItem[] items, int topItem = 5)
{
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderYears"), topItem,
items.Where(x => x.ProductionYear != null && x.ProductionYear > 0)
.GroupBy(x => x.ProductionYear)
.OrderByDescending(x => x.Count())
.Take(topItem)
.Select(x => new ReportStatItem
{
Name = x.Key.ToString(),
Value = x.Count().ToString()
})
);
return result;
}
/// <summary> Gets result studios. </summary>
/// <param name="result"> The result. </param>
/// <param name="items"> The items. </param>
/// <param name="topItem"> The top item. </param>
/// <returns> The result studios. </returns>
private ReportStatResult GetResultStudios(ReportStatResult result, BaseItem[] items, int topItem = 5)
{
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderStudios"), topItem,
items.SelectMany(x => x.Studios)
.GroupBy(x => x)
.OrderByDescending(x => x.Count())
.Take(topItem)
.Select(x => new ReportStatItem
{
Name = x.Key,
Value = x.Count().ToString(),
Id = GetStudioID(x.Key)
})
);
return result;
}
#endregion
}
} }

@ -1468,5 +1468,10 @@
"HeaderNavigation": "Navigation", "HeaderNavigation": "Navigation",
"LegendTheseSettingsShared": "These settings are shared on all devices", "LegendTheseSettingsShared": "These settings are shared on all devices",
"OptionEnableAutomaticServerUpdates": "Enable automatic server updates", "OptionEnableAutomaticServerUpdates": "Enable automatic server updates",
"OptionOtherTrailers": "Include trailers from older movies" "OptionOtherTrailers": "Include trailers from older movies",
"HeaderOverview": "Overview",
"HeaderShortOverview": "Short Overview",
"HeaderType": "Type",
"HeaderSeverity": "Severity",
"OptionReportActivities": "Activities Log"
} }

Loading…
Cancel
Save