diff options
Diffstat (limited to 'MediaBrowser.Api/Reports/Data')
| -rw-r--r-- | MediaBrowser.Api/Reports/Data/ReportBuilder.cs | 589 | ||||
| -rw-r--r-- | MediaBrowser.Api/Reports/Data/ReportExport.cs | 212 | ||||
| -rw-r--r-- | MediaBrowser.Api/Reports/Data/ReportGroup.cs | 44 | ||||
| -rw-r--r-- | MediaBrowser.Api/Reports/Data/ReportHeader.cs | 54 | ||||
| -rw-r--r-- | MediaBrowser.Api/Reports/Data/ReportItem.cs | 34 | ||||
| -rw-r--r-- | MediaBrowser.Api/Reports/Data/ReportOptions.cs | 52 | ||||
| -rw-r--r-- | MediaBrowser.Api/Reports/Data/ReportResult.cs | 53 | ||||
| -rw-r--r-- | MediaBrowser.Api/Reports/Data/ReportRow.cs | 71 |
8 files changed, 1109 insertions, 0 deletions
diff --git a/MediaBrowser.Api/Reports/Data/ReportBuilder.cs b/MediaBrowser.Api/Reports/Data/ReportBuilder.cs new file mode 100644 index 000000000..00ce18317 --- /dev/null +++ b/MediaBrowser.Api/Reports/Data/ReportBuilder.cs @@ -0,0 +1,589 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Localization; +using MediaBrowser.Model.Channels; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Querying; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Reports +{ + /// <summary> A report builder. </summary> + /// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/> + public class ReportBuilder : ReportBuilderBase + { + + /// <summary> + /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilder class. </summary> + /// <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) + { + List<HeaderMetadata> headersMetadata = this.GetFilteredReportHeaderMetadata(reportRowType, request); + + var headers = GetReportHeaders(reportRowType, headersMetadata); + var rows = GetReportRows(items, headersMetadata); + + 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 { Genre = g.Trim(), Rows = x }) + .GroupBy(x => x.Genre) + .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; + } + + public List<ReportHeader> GetReportHeaders(ReportViewType reportRowType, BaseReportRequest request) + { + List<ReportHeader> headersMetadata = this.GetReportHeaders(reportRowType); + if (request != null && !string.IsNullOrEmpty(request.ReportColumns)) + { + List<HeaderMetadata> headersMetadataFiltered = this.GetFilteredReportHeaderMetadata(reportRowType, request); + foreach (ReportHeader reportHeader in headersMetadata) + { + if (!headersMetadataFiltered.Contains(reportHeader.FieldName)) + { + reportHeader.Visible = false; + } + } + + + } + + return headersMetadata; + } + + public List<ReportHeader> GetReportHeaders(ReportViewType reportRowType, List<HeaderMetadata> headersMetadata = null) + { + if (headersMetadata == null) + headersMetadata = this.GetDefaultReportHeaderMetadata(reportRowType); + + List<ReportOptions<BaseItem>> options = new List<ReportOptions<BaseItem>>(); + foreach (HeaderMetadata header in headersMetadata) + { + options.Add(GetReportOption(header)); + } + + + List<ReportHeader> headers = new List<ReportHeader>(); + foreach (ReportOptions<BaseItem> option in options) + { + headers.Add(option.Header); + } + return headers; + } + + 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.Series, + HeaderMetadata.Season, + HeaderMetadata.SeasonNumber, + HeaderMetadata.DateAdded, + HeaderMetadata.Year, + HeaderMetadata.Genres + }; + + case ReportViewType.Series: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.Name, + HeaderMetadata.Network, + HeaderMetadata.DateAdded, + HeaderMetadata.Year, + HeaderMetadata.Genres, + HeaderMetadata.ParentalRating, + HeaderMetadata.CommunityRating, + HeaderMetadata.Runtime, + HeaderMetadata.Trailers, + HeaderMetadata.Specials + }; + + case ReportViewType.MusicAlbum: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.Name, + HeaderMetadata.AlbumArtist, + HeaderMetadata.DateAdded, + HeaderMetadata.ReleaseDate, + HeaderMetadata.Tracks, + HeaderMetadata.Year, + HeaderMetadata.Genres + }; + + case ReportViewType.MusicArtist: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.MusicArtist, + HeaderMetadata.Countries, + HeaderMetadata.DateAdded, + HeaderMetadata.Year, + HeaderMetadata.Genres + }; + + case ReportViewType.Game: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.Name, + HeaderMetadata.GameSystem, + HeaderMetadata.DateAdded, + HeaderMetadata.ReleaseDate, + HeaderMetadata.ParentalRating, + HeaderMetadata.CommunityRating, + HeaderMetadata.Players, + HeaderMetadata.Year, + HeaderMetadata.Genres, + HeaderMetadata.Trailers + }; + + case ReportViewType.Movie: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.Name, + HeaderMetadata.DateAdded, + HeaderMetadata.ReleaseDate, + HeaderMetadata.Year, + HeaderMetadata.Genres, + HeaderMetadata.ParentalRating, + HeaderMetadata.CommunityRating, + HeaderMetadata.Runtime, + HeaderMetadata.Video, + HeaderMetadata.Resolution, + HeaderMetadata.Audio, + HeaderMetadata.Subtitles, + HeaderMetadata.Trailers, + HeaderMetadata.Specials + }; + + case ReportViewType.Book: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.Name, + HeaderMetadata.DateAdded, + HeaderMetadata.ReleaseDate, + HeaderMetadata.Year, + HeaderMetadata.Genres, + HeaderMetadata.ParentalRating, + HeaderMetadata.CommunityRating + }; + + case ReportViewType.BoxSet: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.Name, + HeaderMetadata.DateAdded, + HeaderMetadata.ReleaseDate, + HeaderMetadata.Year, + HeaderMetadata.Genres, + HeaderMetadata.ParentalRating, + HeaderMetadata.CommunityRating, + HeaderMetadata.Trailers + }; + + case ReportViewType.Audio: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.Name, + HeaderMetadata.AudioAlbumArtist, + HeaderMetadata.AudioAlbum, + HeaderMetadata.Disc, + HeaderMetadata.Track, + HeaderMetadata.DateAdded, + HeaderMetadata.ReleaseDate, + HeaderMetadata.Year, + HeaderMetadata.Genres, + HeaderMetadata.ParentalRating, + HeaderMetadata.CommunityRating, + HeaderMetadata.Runtime, + HeaderMetadata.Audio + }; + + case ReportViewType.Episode: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.Name, + HeaderMetadata.EpisodeSeries, + HeaderMetadata.Season, + HeaderMetadata.DateAdded, + HeaderMetadata.ReleaseDate, + HeaderMetadata.Year, + HeaderMetadata.Genres, + HeaderMetadata.ParentalRating, + HeaderMetadata.CommunityRating, + HeaderMetadata.Runtime, + HeaderMetadata.Video, + HeaderMetadata.Resolution, + HeaderMetadata.Audio, + HeaderMetadata.Subtitles, + HeaderMetadata.Trailers, + HeaderMetadata.Specials + }; + + case ReportViewType.Video: + case ReportViewType.MusicVideo: + case ReportViewType.Trailer: + case ReportViewType.BaseItem: + default: + return new List<HeaderMetadata> + { + HeaderMetadata.StatusImage, + HeaderMetadata.Name, + HeaderMetadata.DateAdded, + HeaderMetadata.ReleaseDate, + HeaderMetadata.Year, + HeaderMetadata.Genres, + HeaderMetadata.ParentalRating, + HeaderMetadata.CommunityRating, + HeaderMetadata.Runtime, + HeaderMetadata.Video, + HeaderMetadata.Resolution, + HeaderMetadata.Audio, + HeaderMetadata.Subtitles, + HeaderMetadata.Trailers, + HeaderMetadata.Specials + }; + + } + + } + + /// <summary> Gets report option. </summary> + /// <param name="header"> The header. </param> + /// <param name="sortField"> The sort field. </param> + /// <returns> The report option. </returns> + private ReportOptions<BaseItem> GetReportOption(HeaderMetadata header, string sortField = "") + { + ReportHeader reportHeader = new ReportHeader + { + HeaderFieldType = ReportFieldType.String, + SortField = sortField, + Type = "", + ItemViewType = ItemViewType.None + }; + + Func<BaseItem, ReportRow, object> column = null; + Func<BaseItem, object> itemId = null; + HeaderMetadata internalHeader = header; + + switch (header) + { + case HeaderMetadata.StatusImage: + reportHeader.ItemViewType = ItemViewType.StatusImage; + internalHeader = HeaderMetadata.Status; + reportHeader.CanGroup = false; + break; + + case HeaderMetadata.Name: + column = (i, r) => i.Name; + reportHeader.ItemViewType = ItemViewType.Detail; + reportHeader.SortField = "SortName"; + break; + + case HeaderMetadata.DateAdded: + column = (i, r) => i.DateCreated; + reportHeader.SortField = "DateCreated,SortName"; + reportHeader.HeaderFieldType = ReportFieldType.DateTime; + reportHeader.Type = ""; + break; + + case HeaderMetadata.PremiereDate: + case HeaderMetadata.ReleaseDate: + column = (i, r) => i.PremiereDate; + reportHeader.HeaderFieldType = ReportFieldType.DateTime; + reportHeader.SortField = "ProductionYear,PremiereDate,SortName"; + break; + + case HeaderMetadata.Runtime: + column = (i, r) => this.GetRuntimeDateTime(i.RunTimeTicks); + reportHeader.HeaderFieldType = ReportFieldType.Minutes; + reportHeader.SortField = "Runtime,SortName"; + break; + + case HeaderMetadata.PlayCount: + reportHeader.HeaderFieldType = ReportFieldType.Int; + break; + + case HeaderMetadata.Season: + column = (i, r) => this.GetEpisode(i); + reportHeader.ItemViewType = ItemViewType.Detail; + reportHeader.SortField = "SortName"; + break; + + case HeaderMetadata.SeasonNumber: + column = (i, r) => this.GetObject<Season, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString()); + reportHeader.SortField = "IndexNumber"; + reportHeader.HeaderFieldType = ReportFieldType.Int; + break; + + case HeaderMetadata.Series: + column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName); + reportHeader.ItemViewType = ItemViewType.Detail; + reportHeader.SortField = "SeriesSortName,SortName"; + break; + + case HeaderMetadata.EpisodeSeries: + column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName); + reportHeader.ItemViewType = ItemViewType.Detail; + itemId = (i) => + { + Series series = this.GetObject<Episode, Series>(i, (x) => x.Series); + if (series == null) + return string.Empty; + return series.Id; + }; + reportHeader.SortField = "SeriesSortName,SortName"; + internalHeader = HeaderMetadata.Series; + break; + + case HeaderMetadata.EpisodeSeason: + column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName); + reportHeader.ItemViewType = ItemViewType.Detail; + itemId = (i) => + { + Season season = this.GetObject<Episode, Season>(i, (x) => x.Season); + if (season == null) + return string.Empty; + return season.Id; + }; + reportHeader.SortField = "SortName"; + internalHeader = HeaderMetadata.Season; + break; + + case HeaderMetadata.Network: + column = (i, r) => this.GetListAsString(i.Studios); + itemId = (i) => this.GetStudioID(i.Studios.FirstOrDefault()); + reportHeader.ItemViewType = ItemViewType.ItemByNameDetails; + reportHeader.SortField = "Studio,SortName"; + break; + + case HeaderMetadata.Year: + column = (i, r) => this.GetSeriesProductionYear(i); + reportHeader.SortField = "ProductionYear,PremiereDate,SortName"; + break; + + case HeaderMetadata.ParentalRating: + column = (i, r) => i.OfficialRating; + reportHeader.SortField = "OfficialRating,SortName"; + break; + + case HeaderMetadata.CommunityRating: + column = (i, r) => i.CommunityRating; + reportHeader.SortField = "CommunityRating,SortName"; + break; + + case HeaderMetadata.Trailers: + column = (i, r) => this.GetBoolString(r.HasLocalTrailer); + reportHeader.ItemViewType = ItemViewType.TrailersImage; + break; + + case HeaderMetadata.Specials: + column = (i, r) => this.GetBoolString(r.HasSpecials); + reportHeader.ItemViewType = ItemViewType.SpecialsImage; + break; + + case HeaderMetadata.GameSystem: + column = (i, r) => this.GetObject<Game, string>(i, (x) => x.GameSystem); + reportHeader.SortField = "GameSystem,SortName"; + break; + + case HeaderMetadata.Players: + column = (i, r) => this.GetObject<Game, int?>(i, (x) => x.PlayersSupported); + reportHeader.SortField = "Players,GameSystem,SortName"; + break; + + case HeaderMetadata.AlbumArtist: + column = (i, r) => this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist); + itemId = (i) => this.GetPersonID(this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist)); + reportHeader.ItemViewType = ItemViewType.Detail; + reportHeader.SortField = "AlbumArtist,Album,SortName"; + + break; + case HeaderMetadata.MusicArtist: + column = (i, r) => this.GetObject<MusicArtist, string>(i, (x) => x.GetLookupInfo().Name); + reportHeader.ItemViewType = ItemViewType.Detail; + reportHeader.SortField = "AlbumArtist,Album,SortName"; + internalHeader = HeaderMetadata.AlbumArtist; + break; + case HeaderMetadata.AudioAlbumArtist: + column = (i, r) => this.GetListAsString(this.GetObject<Audio, List<string>>(i, (x) => x.AlbumArtists)); + reportHeader.SortField = "AlbumArtist,Album,SortName"; + internalHeader = HeaderMetadata.AlbumArtist; + break; + + case HeaderMetadata.AudioAlbum: + column = (i, r) => this.GetObject<Audio, string>(i, (x) => x.Album); + reportHeader.SortField = "Album,SortName"; + internalHeader = HeaderMetadata.Album; + break; + + case HeaderMetadata.Countries: + column = (i, r) => this.GetListAsString(this.GetObject<IHasProductionLocations, List<string>>(i, (x) => x.ProductionLocations)); + break; + + case HeaderMetadata.Disc: + column = (i, r) => i.ParentIndexNumber; + break; + + case HeaderMetadata.Track: + 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(); + break; + + case HeaderMetadata.Audio: + column = (i, r) => this.GetAudioStream(i); + break; + + case HeaderMetadata.EmbeddedImage: + break; + + case HeaderMetadata.Video: + column = (i, r) => this.GetVideoStream(i); + break; + + case HeaderMetadata.Resolution: + column = (i, r) => this.GetVideoResolution(i); + break; + + case HeaderMetadata.Subtitles: + column = (i, r) => this.GetBoolString(r.HasSubtitles); + reportHeader.ItemViewType = ItemViewType.SubtitleImage; + break; + + case HeaderMetadata.Genres: + column = (i, r) => this.GetListAsString(i.Genres); + break; + + } + + 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); + } + + reportHeader.Name = headerName; + reportHeader.FieldName = header; + ReportOptions<BaseItem> option = new ReportOptions<BaseItem>() + { + Header = reportHeader, + Column = column, + ItemID = itemId + }; + return option; + } + } +} diff --git a/MediaBrowser.Api/Reports/Data/ReportExport.cs b/MediaBrowser.Api/Reports/Data/ReportExport.cs new file mode 100644 index 000000000..f313cf252 --- /dev/null +++ b/MediaBrowser.Api/Reports/Data/ReportExport.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Reports +{ + /// <summary> A report export. </summary> + public class ReportExport + { + /// <summary> Export to CSV. </summary> + /// <param name="reportResult"> The report result. </param> + /// <returns> A string. </returns> + public string ExportToCsv(ReportResult reportResult) + { + StringBuilder returnValue = new StringBuilder(); + + returnValue.AppendLine(string.Join(";", reportResult.Headers.Select(s => s.Name.Replace(',', ' ')).ToArray())); + + if (reportResult.IsGrouped) + foreach (ReportGroup group in reportResult.Groups) + { + foreach (ReportRow row in reportResult.Rows) + { + returnValue.AppendLine(string.Join(";", row.Columns.Select(s => s.Name.Replace(',', ' ')).ToArray())); + } + } + else + foreach (ReportRow row in reportResult.Rows) + { + returnValue.AppendLine(string.Join(";", row.Columns.Select(s => s.Name.Replace(',', ' ')).ToArray())); + } + + return returnValue.ToString(); + } + + + /// <summary> Export to excel. </summary> + /// <param name="reportResult"> The report result. </param> + /// <returns> A string. </returns> + public string ExportToExcel(ReportResult reportResult) + { + + string style = @"<style type='text/css'> + BODY { + font-family: Arial; + font-size: 12px; + } + + TABLE { + font-family: Arial; + font-size: 12px; + } + + A { + font-family: Arial; + color: #144A86; + font-size: 12px; + cursor: pointer; + text-decoration: none; + font-weight: bold; + } + DIV { + font-family: Arial; + font-size: 12px; + margin-bottom: 0px; + } + P, LI, DIV { + font-size: 12px; + margin-bottom: 0px; + } + + P, UL { + font-size: 12px; + margin-bottom: 6px; + margin-top: 0px; + } + + H1 { + font-size: 18pt; + } + + H2 { + font-weight: bold; + font-size: 14pt; + COLOR: #C0C0C0; + } + + H3 { + font-weight: normal; + font-size: 14pt; + text-indent: +1em; + } + + H4 { + font-size: 10pt; + font-weight: normal; + } + + H5 { + font-size: 10pt; + font-weight: normal; + background: #A9A9A9; + COLOR: white; + display: inline; + } + + H6 { + padding: 2 1 2 5; + font-size: 11px; + font-weight: bold; + text-decoration: none; + margin-bottom: 1px; + } + + UL { + line-height: 1.5em; + list-style-type: disc; + } + + OL { + line-height: 1.5em; + } + + LI { + line-height: 1.5em; + } + + A IMG { + border: 0; + } + + table.gridtable { + color: #333333; + border-width: 0.1pt; + border-color: #666666; + border-collapse: collapse; + } + + table.gridtable th { + border-width: 0.1pt; + padding: 8px; + border-style: solid; + border-color: #666666; + background-color: #dedede; + } + table.gridtable tr { + background-color: #ffffff; + } + table.gridtable td { + border-width: 0.1pt; + padding: 8px; + border-style: solid; + border-color: #666666; + background-color: #ffffff; + } + </style>"; + + string Html = @"<!DOCTYPE html> + <html xmlns='http://www.w3.org/1999/xhtml'> + <head> + <meta http-equiv='X-UA-Compatible' content='IE=8, IE=9, IE=10' /> + <meta charset='utf-8'> + <title>Emby Reports Export</title>"; + Html += "\n" + style + "\n"; + Html += "</head>\n"; + Html += "<body>\n"; + + StringBuilder returnValue = new StringBuilder(); + returnValue.AppendLine("<table class='gridtable'>"); + returnValue.AppendLine("<tr>"); + returnValue.AppendLine(string.Join("", reportResult.Headers.Select(s => string.Format("<th>{0}</th>", s.Name)).ToArray())); + returnValue.AppendLine("</tr>"); + if (reportResult.IsGrouped) + foreach (ReportGroup group in reportResult.Groups) + { + returnValue.AppendLine("<tr>"); + returnValue.AppendLine("<th scope='rowgroup' colspan='" + reportResult.Headers.Count + "'>" + (string.IsNullOrEmpty(group.Name) ? " " : group.Name) + "</th>"); + returnValue.AppendLine("</tr>"); + foreach (ReportRow row in group.Rows) + { + ExportToExcelRow(reportResult, returnValue, row); + } + returnValue.AppendLine("<tr>"); + returnValue.AppendLine("<th style='background-color: #ffffff;' scope='rowgroup' colspan='" + reportResult.Headers.Count + "'>" + " " + "</th>"); + returnValue.AppendLine("</tr>"); + } + + else + foreach (ReportRow row in reportResult.Rows) + { + ExportToExcelRow(reportResult, returnValue, row); + } + returnValue.AppendLine("</table>"); + + Html += returnValue.ToString(); + Html += "</body>"; + Html += "</html>"; + return Html; + } + private static void ExportToExcelRow(ReportResult reportResult, + StringBuilder returnValue, + ReportRow row) + { + returnValue.AppendLine("<tr>"); + returnValue.AppendLine(string.Join("", row.Columns.Select(s => string.Format("<td>{0}</td>", s.Name)).ToArray())); + returnValue.AppendLine("</tr>"); + } + } + +} diff --git a/MediaBrowser.Api/Reports/Data/ReportGroup.cs b/MediaBrowser.Api/Reports/Data/ReportGroup.cs new file mode 100644 index 000000000..49c76c7ba --- /dev/null +++ b/MediaBrowser.Api/Reports/Data/ReportGroup.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Reports +{ + + /// <summary> A report group. </summary> + public class ReportGroup + { + /// <summary> + /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportGroup class. </summary> + public ReportGroup() + { + Rows = new List<ReportRow>(); + } + + /// <summary> + /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportGroup class. </summary> + /// <param name="rows"> The rows. </param> + public ReportGroup(List<ReportRow> rows) + { + Rows = rows; + } + + /// <summary> Gets or sets the name. </summary> + /// <value> The name. </value> + public string Name { get; set; } + + /// <summary> Gets or sets the rows. </summary> + /// <value> The rows. </value> + public List<ReportRow> Rows { get; set; } + + /// <summary> Returns a string that represents the current object. </summary> + /// <returns> A string that represents the current object. </returns> + /// <seealso cref="M:System.Object.ToString()"/> + public override string ToString() + { + return Name; + } + } +} diff --git a/MediaBrowser.Api/Reports/Data/ReportHeader.cs b/MediaBrowser.Api/Reports/Data/ReportHeader.cs new file mode 100644 index 000000000..81b85954a --- /dev/null +++ b/MediaBrowser.Api/Reports/Data/ReportHeader.cs @@ -0,0 +1,54 @@ +using MediaBrowser.Controller.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Reports +{ + /// <summary> A report header. </summary> + public class ReportHeader + { + /// <summary> Initializes a new instance of the ReportHeader class. </summary> + public ReportHeader() + { + ItemViewType = ItemViewType.None; + Visible = true; + CanGroup = true; + } + + /// <summary> Gets or sets the type of the header field. </summary> + /// <value> The type of the header field. </value> + public ReportFieldType HeaderFieldType { get; set; } + + /// <summary> Gets or sets the name of the header. </summary> + /// <value> The name of the header. </value> + public string Name { get; set; } + + /// <summary> Gets or sets the name of the field. </summary> + /// <value> The name of the field. </value> + public HeaderMetadata FieldName { get; set; } + + /// <summary> Gets or sets the sort field. </summary> + /// <value> The sort field. </value> + public string SortField { get; set; } + + /// <summary> Gets or sets the type. </summary> + /// <value> The type. </value> + public string Type { get; set; } + + /// <summary> Gets or sets the type of the item view. </summary> + /// <value> The type of the item view. </value> + public ItemViewType ItemViewType { get; set; } + + /// <summary> Gets or sets a value indicating whether this object is visible. </summary> + /// <value> true if visible, false if not. </value> + public bool Visible { get; set; } + + /// <summary> Gets or sets a value indicating whether we can group. </summary> + /// <value> true if we can group, false if not. </value> + public bool CanGroup { get; set; } + + } +} diff --git a/MediaBrowser.Api/Reports/Data/ReportItem.cs b/MediaBrowser.Api/Reports/Data/ReportItem.cs new file mode 100644 index 000000000..06d0b0c46 --- /dev/null +++ b/MediaBrowser.Api/Reports/Data/ReportItem.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Reports +{ + /// <summary> A report item. </summary> + public class ReportItem + { + /// <summary> Gets or sets the identifier. </summary> + /// <value> The identifier. </value> + public string Id { get; set; } + + /// <summary> Gets or sets the name. </summary> + /// <value> The name. </value> + public string Name { get; set; } + + public string Image { get; set; } + + /// <summary> Gets or sets the custom tag. </summary> + /// <value> The custom tag. </value> + public string CustomTag { get; set; } + + /// <summary> Returns a string that represents the current object. </summary> + /// <returns> A string that represents the current object. </returns> + /// <seealso cref="M:System.Object.ToString()"/> + public override string ToString() + { + return Name; + } + } +} diff --git a/MediaBrowser.Api/Reports/Data/ReportOptions.cs b/MediaBrowser.Api/Reports/Data/ReportOptions.cs new file mode 100644 index 000000000..aed15d428 --- /dev/null +++ b/MediaBrowser.Api/Reports/Data/ReportOptions.cs @@ -0,0 +1,52 @@ +using MediaBrowser.Controller.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Reports +{ + /// <summary> A report options. </summary> + internal class ReportOptions<I> + { + /// <summary> Initializes a new instance of the ReportOptions class. </summary> + public ReportOptions() + { + } + + /// <summary> Initializes a new instance of the ReportOptions class. </summary> + /// <param name="header"> . </param> + /// <param name="row"> . </param> + public ReportOptions(ReportHeader header, Func<I, ReportRow, object> column) + { + Header = header; + Column = column; + } + + /// <summary> + /// Initializes a new instance of the ReportOptions class. + /// </summary> + /// <param name="header"></param> + /// <param name="column"></param> + /// <param name="itemID"></param> + public ReportOptions(ReportHeader header, Func<I, ReportRow, object> column, Func<I, object> itemID) + { + Header = header; + Column = column; + ItemID = itemID; + } + + /// <summary> Gets or sets the header. </summary> + /// <value> The header. </value> + public ReportHeader Header { get; set; } + + /// <summary> Gets or sets the column. </summary> + /// <value> The column. </value> + public Func<I, ReportRow, object> Column { get; set; } + + /// <summary> Gets or sets the identifier of the item. </summary> + /// <value> The identifier of the item. </value> + public Func<I, object> ItemID { get; set; } + } +} diff --git a/MediaBrowser.Api/Reports/Data/ReportResult.cs b/MediaBrowser.Api/Reports/Data/ReportResult.cs new file mode 100644 index 000000000..a4bc95aa1 --- /dev/null +++ b/MediaBrowser.Api/Reports/Data/ReportResult.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Api.Reports +{ + + /// <summary> Encapsulates the result of a report. </summary> + public class ReportResult + { + /// <summary> + /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportResult class. </summary> + public ReportResult() + { + Rows = new List<ReportRow>(); + Headers = new List<ReportHeader>(); + Groups = new List<ReportGroup>(); + TotalRecordCount = 0; + IsGrouped = false; + } + + /// <summary> + /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportResult class. </summary> + /// <param name="headers"> The headers. </param> + /// <param name="rows"> The rows. </param> + public ReportResult(List<ReportHeader> headers, List<ReportRow> rows) + { + Rows = rows; + Headers = headers; + TotalRecordCount = 0; + } + + /// <summary> Gets or sets the rows. </summary> + /// <value> The rows. </value> + public List<ReportRow> Rows { get; set; } + + /// <summary> Gets or sets the headers. </summary> + /// <value> The headers. </value> + public List<ReportHeader> Headers { get; set; } + + /// <summary> Gets or sets the groups. </summary> + /// <value> The groups. </value> + public List<ReportGroup> Groups { get; set; } + + + /// <summary> Gets or sets the number of total records. </summary> + /// <value> The total number of record count. </value> + public int TotalRecordCount { get; set; } + + /// <summary> Gets or sets the is grouped. </summary> + /// <value> The is grouped. </value> + public bool IsGrouped { get; set; } + + } +} diff --git a/MediaBrowser.Api/Reports/Data/ReportRow.cs b/MediaBrowser.Api/Reports/Data/ReportRow.cs new file mode 100644 index 000000000..f2165344a --- /dev/null +++ b/MediaBrowser.Api/Reports/Data/ReportRow.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Reports +{ + public class ReportRow + { + /// <summary> + /// Initializes a new instance of the ReportRow class. + /// </summary> + public ReportRow() + { + Columns = new List<ReportItem>(); + } + + /// <summary> Gets or sets the identifier. </summary> + /// <value> The identifier. </value> + public string Id { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this object has backdrop image. </summary> + /// <value> true if this object has backdrop image, false if not. </value> + public bool HasImageTagsBackdrop { get; set; } + + /// <summary> Gets or sets a value indicating whether this object has image tags. </summary> + /// <value> true if this object has image tags, false if not. </value> + public bool HasImageTagsPrimary { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this object has image tags logo. </summary> + /// <value> true if this object has image tags logo, false if not. </value> + public bool HasImageTagsLogo { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this object has local trailer. </summary> + /// <value> true if this object has local trailer, false if not. </value> + public bool HasLocalTrailer { get; set; } + + /// <summary> Gets or sets a value indicating whether this object has lock data. </summary> + /// <value> true if this object has lock data, false if not. </value> + public bool HasLockData { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this object has embedded image. </summary> + /// <value> true if this object has embedded image, false if not. </value> + public bool HasEmbeddedImage { get; set; } + + /// <summary> Gets or sets a value indicating whether this object has subtitles. </summary> + /// <value> true if this object has subtitles, false if not. </value> + public bool HasSubtitles { get; set; } + + /// <summary> Gets or sets a value indicating whether this object has specials. </summary> + /// <value> true if this object has specials, false if not. </value> + public bool HasSpecials { get; set; } + + /// <summary> Gets or sets a value indicating whether this object is unidentified. </summary> + /// <value> true if this object is unidentified, false if not. </value> + public bool IsUnidentified { get; set; } + + /// <summary> Gets or sets the columns. </summary> + /// <value> The columns. </value> + public List<ReportItem> Columns { get; set; } + + /// <summary> Gets or sets the type. </summary> + /// <value> The type. </value> + public ReportViewType RowType { get; set; } + } +} |
