123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626 |
- using MediaBrowser.Controller.Entities;
- using MediaBrowser.Controller.Entities.Audio;
- using MediaBrowser.Controller.Entities.TV;
- using MediaBrowser.Controller.Library;
- using MediaBrowser.Model.Entities;
- using System.Collections.Generic;
- using System.Linq;
- namespace MediaBrowser.Api.Reports
- {
- /// <summary> A report builder. </summary>
- /// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
- public class ReportBuilder : ReportBuilderBase
- {
- #region [Constructors]
- /// <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)
- {
- }
- #endregion
- #region [Public Methods]
- /// <summary> Gets report result. </summary>
- /// <param name="items"> The items. </param>
- /// <param name="request"> The request. </param>
- /// <returns> The report result. </returns>
- public ReportResult GetResult(BaseItem[] items, IReportsQuery request)
- {
- ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
- ReportDisplayType displayType = ReportHelper.GetReportDisplayType(request.DisplayType);
- List<ReportOptions<BaseItem>> options = this.GetReportOptions<BaseItem>(request,
- () => this.GetDefaultHeaderMetadata(reportRowType),
- (hm) => this.GetOption(hm)).Where(x => this.DisplayTypeVisible(x.Header.DisplayType, displayType)).ToList();
- var headers = GetHeaders<BaseItem>(options);
- var rows = GetReportRows(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)
- {
- ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
- return this.GetHeaders<BaseItem>(request, () => this.GetDefaultHeaderMetadata(reportRowType), (hm) => this.GetOption(hm));
- }
- #endregion
- #region [Private Methods]
- /// <summary> Gets default report header metadata. </summary>
- /// <param name="reportIncludeItemTypes"> Type of the report row. </param>
- /// <returns> The default report header metadata. </returns>
- private List<HeaderMetadata> GetDefaultHeaderMetadata(ReportIncludeItemTypes reportIncludeItemTypes)
- {
- switch (reportIncludeItemTypes)
- {
- case ReportIncludeItemTypes.Season:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- HeaderMetadata.Series,
- HeaderMetadata.Season,
- HeaderMetadata.SeasonNumber,
- HeaderMetadata.DateAdded,
- HeaderMetadata.Year,
- HeaderMetadata.Genres
- };
- case ReportIncludeItemTypes.Series:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- HeaderMetadata.Name,
- HeaderMetadata.Network,
- HeaderMetadata.DateAdded,
- HeaderMetadata.Year,
- HeaderMetadata.Genres,
- HeaderMetadata.ParentalRating,
- HeaderMetadata.CommunityRating,
- HeaderMetadata.Runtime,
- HeaderMetadata.Trailers,
- HeaderMetadata.Specials
- };
- case ReportIncludeItemTypes.MusicAlbum:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- HeaderMetadata.Name,
- HeaderMetadata.AlbumArtist,
- HeaderMetadata.DateAdded,
- HeaderMetadata.ReleaseDate,
- HeaderMetadata.Tracks,
- HeaderMetadata.Year,
- HeaderMetadata.Genres
- };
- case ReportIncludeItemTypes.MusicArtist:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- HeaderMetadata.MusicArtist,
- HeaderMetadata.Countries,
- HeaderMetadata.DateAdded,
- HeaderMetadata.Year,
- HeaderMetadata.Genres
- };
- case ReportIncludeItemTypes.Game:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- HeaderMetadata.Name,
- HeaderMetadata.GameSystem,
- HeaderMetadata.DateAdded,
- HeaderMetadata.ReleaseDate,
- HeaderMetadata.ParentalRating,
- HeaderMetadata.CommunityRating,
- HeaderMetadata.Players,
- HeaderMetadata.Year,
- HeaderMetadata.Genres,
- HeaderMetadata.Trailers
- };
- case ReportIncludeItemTypes.Movie:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- 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 ReportIncludeItemTypes.Book:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- HeaderMetadata.Name,
- HeaderMetadata.DateAdded,
- HeaderMetadata.ReleaseDate,
- HeaderMetadata.Year,
- HeaderMetadata.Genres,
- HeaderMetadata.ParentalRating,
- HeaderMetadata.CommunityRating
- };
- case ReportIncludeItemTypes.BoxSet:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- HeaderMetadata.Name,
- HeaderMetadata.DateAdded,
- HeaderMetadata.ReleaseDate,
- HeaderMetadata.Year,
- HeaderMetadata.Genres,
- HeaderMetadata.ParentalRating,
- HeaderMetadata.CommunityRating,
- HeaderMetadata.Trailers
- };
- case ReportIncludeItemTypes.Audio:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- 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 ReportIncludeItemTypes.Episode:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- HeaderMetadata.Name,
- HeaderMetadata.EpisodeSeries,
- HeaderMetadata.Season,
- HeaderMetadata.EpisodeNumber,
- 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 ReportIncludeItemTypes.Video:
- case ReportIncludeItemTypes.MusicVideo:
- case ReportIncludeItemTypes.Trailer:
- case ReportIncludeItemTypes.BaseItem:
- default:
- return new List<HeaderMetadata>
- {
- HeaderMetadata.Status,
- HeaderMetadata.Locked,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- HeaderMetadata.ImagePrimary,
- HeaderMetadata.ImageBackdrop,
- HeaderMetadata.ImageLogo,
- 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> GetOption(HeaderMetadata header, string sortField = "")
- {
- HeaderMetadata internalHeader = header;
- ReportOptions<BaseItem> option = new ReportOptions<BaseItem>()
- {
- Header = new ReportHeader
- {
- HeaderFieldType = ReportFieldType.String,
- SortField = sortField,
- Type = "",
- ItemViewType = ItemViewType.None
- }
- };
- switch (header)
- {
- case HeaderMetadata.Status:
- option.Header.ItemViewType = ItemViewType.StatusImage;
- internalHeader = HeaderMetadata.Status;
- option.Header.CanGroup = false;
- option.Header.DisplayType = ReportDisplayType.Screen;
- break;
- case HeaderMetadata.Locked:
- option.Column = (i, r) => this.GetBoolString(r.HasLockData);
- option.Header.ItemViewType = ItemViewType.LockDataImage;
- option.Header.CanGroup = false;
- option.Header.DisplayType = ReportDisplayType.Export;
- break;
- case HeaderMetadata.ImagePrimary:
- option.Column = (i, r) => this.GetBoolString(r.HasImageTagsPrimary);
- option.Header.ItemViewType = ItemViewType.TagsPrimaryImage;
- option.Header.CanGroup = false;
- option.Header.DisplayType = ReportDisplayType.Export;
- break;
- case HeaderMetadata.ImageBackdrop:
- option.Column = (i, r) => this.GetBoolString(r.HasImageTagsBackdrop);
- option.Header.ItemViewType = ItemViewType.TagsBackdropImage;
- option.Header.CanGroup = false;
- option.Header.DisplayType = ReportDisplayType.Export;
- break;
- case HeaderMetadata.ImageLogo:
- option.Column = (i, r) => this.GetBoolString(r.HasImageTagsLogo);
- option.Header.ItemViewType = ItemViewType.TagsLogoImage;
- option.Header.CanGroup = false;
- option.Header.DisplayType = ReportDisplayType.Export;
- break;
- case HeaderMetadata.Name:
- option.Column = (i, r) => i.Name;
- option.Header.ItemViewType = ItemViewType.Detail;
- option.Header.SortField = "SortName";
- break;
- case HeaderMetadata.DateAdded:
- option.Column = (i, r) => i.DateCreated;
- option.Header.SortField = "DateCreated,SortName";
- option.Header.HeaderFieldType = ReportFieldType.DateTime;
- option.Header.Type = "";
- break;
- case HeaderMetadata.PremiereDate:
- case HeaderMetadata.ReleaseDate:
- option.Column = (i, r) => i.PremiereDate;
- option.Header.HeaderFieldType = ReportFieldType.DateTime;
- option.Header.SortField = "ProductionYear,PremiereDate,SortName";
- break;
- case HeaderMetadata.Runtime:
- option.Column = (i, r) => this.GetRuntimeDateTime(i.RunTimeTicks);
- option.Header.HeaderFieldType = ReportFieldType.Minutes;
- option.Header.SortField = "Runtime,SortName";
- break;
- case HeaderMetadata.PlayCount:
- option.Header.HeaderFieldType = ReportFieldType.Int;
- break;
- case HeaderMetadata.Season:
- option.Column = (i, r) => this.GetEpisode(i);
- option.Header.ItemViewType = ItemViewType.Detail;
- option.Header.SortField = "SortName";
- break;
- case HeaderMetadata.SeasonNumber:
- option.Column = (i, r) => this.GetObject<Season, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString());
- option.Header.SortField = "IndexNumber";
- option.Header.HeaderFieldType = ReportFieldType.Int;
- break;
- case HeaderMetadata.Series:
- option.Column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
- option.Header.ItemViewType = ItemViewType.Detail;
- option.Header.SortField = "SeriesSortName,SortName";
- break;
- case HeaderMetadata.EpisodeSeries:
- option.Column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
- option.Header.ItemViewType = ItemViewType.Detail;
- option.ItemID = (i) =>
- {
- Series series = this.GetObject<Episode, Series>(i, (x) => x.Series);
- if (series == null)
- return string.Empty;
- return series.Id;
- };
- option.Header.SortField = "SeriesSortName,SortName";
- internalHeader = HeaderMetadata.Series;
- break;
- case HeaderMetadata.EpisodeSeason:
- option.Column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
- option.Header.ItemViewType = ItemViewType.Detail;
- option.ItemID = (i) =>
- {
- Season season = this.GetObject<Episode, Season>(i, (x) => x.Season);
- if (season == null)
- return string.Empty;
- return season.Id;
- };
- option.Header.SortField = "SortName";
- internalHeader = HeaderMetadata.Season;
- break;
- case HeaderMetadata.EpisodeNumber:
- option.Column = (i, r) => this.GetObject<BaseItem, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString());
- //option.Header.SortField = "IndexNumber";
- //option.Header.HeaderFieldType = ReportFieldType.Int;
- break;
- case HeaderMetadata.Network:
- option.Column = (i, r) => this.GetListAsString(i.Studios);
- option.ItemID = (i) => this.GetStudioID(i.Studios.FirstOrDefault());
- option.Header.ItemViewType = ItemViewType.ItemByNameDetails;
- option.Header.SortField = "Studio,SortName";
- break;
- case HeaderMetadata.Year:
- option.Column = (i, r) => this.GetSeriesProductionYear(i);
- option.Header.SortField = "ProductionYear,PremiereDate,SortName";
- break;
- case HeaderMetadata.ParentalRating:
- option.Column = (i, r) => i.OfficialRating;
- option.Header.SortField = "OfficialRating,SortName";
- break;
- case HeaderMetadata.CommunityRating:
- option.Column = (i, r) => i.CommunityRating;
- option.Header.SortField = "CommunityRating,SortName";
- break;
- case HeaderMetadata.Trailers:
- option.Column = (i, r) => this.GetBoolString(r.HasLocalTrailer);
- option.Header.ItemViewType = ItemViewType.TrailersImage;
- break;
- case HeaderMetadata.Specials:
- option.Column = (i, r) => this.GetBoolString(r.HasSpecials);
- option.Header.ItemViewType = ItemViewType.SpecialsImage;
- break;
- case HeaderMetadata.GameSystem:
- option.Column = (i, r) => this.GetObject<Game, string>(i, (x) => x.GameSystem);
- option.Header.SortField = "GameSystem,SortName";
- break;
- case HeaderMetadata.Players:
- option.Column = (i, r) => this.GetObject<Game, int?>(i, (x) => x.PlayersSupported);
- option.Header.SortField = "Players,GameSystem,SortName";
- break;
- case HeaderMetadata.AlbumArtist:
- option.Column = (i, r) => this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist);
- option.ItemID = (i) => this.GetPersonID(this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist));
- option.Header.ItemViewType = ItemViewType.Detail;
- option.Header.SortField = "AlbumArtist,Album,SortName";
- break;
- case HeaderMetadata.MusicArtist:
- option.Column = (i, r) => this.GetObject<MusicArtist, string>(i, (x) => x.GetLookupInfo().Name);
- option.Header.ItemViewType = ItemViewType.Detail;
- option.Header.SortField = "AlbumArtist,Album,SortName";
- internalHeader = HeaderMetadata.AlbumArtist;
- break;
- case HeaderMetadata.AudioAlbumArtist:
- option.Column = (i, r) => this.GetListAsString(this.GetObject<Audio, List<string>>(i, (x) => x.AlbumArtists));
- option.Header.SortField = "AlbumArtist,Album,SortName";
- internalHeader = HeaderMetadata.AlbumArtist;
- break;
- case HeaderMetadata.AudioAlbum:
- option.Column = (i, r) => this.GetObject<Audio, string>(i, (x) => x.Album);
- option.Header.SortField = "Album,SortName";
- internalHeader = HeaderMetadata.Album;
- break;
- case HeaderMetadata.Disc:
- option.Column = (i, r) => i.ParentIndexNumber;
- break;
- case HeaderMetadata.Track:
- option.Column = (i, r) => i.IndexNumber;
- break;
- case HeaderMetadata.Tracks:
- option.Column = (i, r) => this.GetObject<MusicAlbum, List<Audio>>(i, (x) => x.Tracks.ToList(), new List<Audio>()).Count();
- break;
- case HeaderMetadata.Audio:
- option.Column = (i, r) => this.GetAudioStream(i);
- break;
- case HeaderMetadata.EmbeddedImage:
- break;
- case HeaderMetadata.Video:
- option.Column = (i, r) => this.GetVideoStream(i);
- break;
- case HeaderMetadata.Resolution:
- option.Column = (i, r) => this.GetVideoResolution(i);
- break;
- case HeaderMetadata.Subtitles:
- option.Column = (i, r) => this.GetBoolString(r.HasSubtitles);
- option.Header.ItemViewType = ItemViewType.SubtitleImage;
- break;
- case HeaderMetadata.Genres:
- option.Column = (i, r) => this.GetListAsString(i.Genres);
- 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<BaseItem> items, List<ReportOptions<BaseItem>> options)
- {
- 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,
- 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
- }
- }
|