/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { var rockContext = new RockContext(); var mediaElementService = new MediaElementService(rockContext); // Use AsNoTracking() since these records won't be modified, and therefore don't need to be tracked by the EF change tracker var qry = mediaElementService.Queryable().AsNoTracking().Where(a => a.MediaFolderId == _mediaFolder.Id); // name filter string nameFilter = gfFilter.GetUserPreference(UserPreferenceKey.Name); if (!string.IsNullOrEmpty(nameFilter)) { qry = qry.Where(a => a.Name.Contains(nameFilter)); } var sortProperty = gElementList.SortProperty; if (gElementList.AllowSorting && sortProperty != null) { qry = qry.Sort(sortProperty); } else { qry = qry.OrderBy(a => a.Name); } gElementList.EntityTypeId = EntityTypeCache.GetId <MediaElement>(); gElementList.DataSource = qry.ToList(); gElementList.DataBind(); }
/// <summary> /// Sets the value. ( as Guid ) /// </summary> /// <param name="control">The control.</param> /// <param name="configurationValues">The configuration values.</param> /// <param name="value">The value.</param> public override void SetEditValue(System.Web.UI.Control control, Dictionary <string, ConfigurationValue> configurationValues, string value) { if (!(control is MediaElementPicker mediaElementPicker)) { return; } var mediaElementGuid = value.AsGuidOrNull(); if (mediaElementGuid.HasValue) { using (var rockContext = new RockContext()) { var mediaElementInfo = new MediaElementService(rockContext).Queryable() .Where(a => a.Guid == mediaElementGuid.Value) .Select(a => new { a.Id, a.MediaFolderId, a.MediaFolder.MediaAccountId }) .SingleOrDefault(); if (mediaElementInfo != null) { var limitAccountId = GetLimitToAccountId(configurationValues); var limitFolderId = GetLimitToFolderId(configurationValues); bool accountOk = limitAccountId.IsNullOrZero() || limitAccountId.Value == mediaElementInfo.MediaAccountId; bool folderOk = limitFolderId.IsNullOrZero() || limitFolderId.Value == mediaElementInfo.MediaFolderId; // This is a little odd, but here is the logic. // If the admin has limited to a specific folder or account // then we need to enforce that. Which means if the old // value is for a different folder/account then we // basically just don't set the value because they won't // be able to save it anyway. Similar logic to a custom // drop down list where the admin removes one of the // options. The next time the value is edited it won't // be selected anymore because it doesn't exist. if (accountOk && folderOk) { mediaElementPicker.MediaElementId = mediaElementInfo.Id; return; } } } } // We couldn't find the stored value or there wasn't one, set // the defaults to nothing selected and ensure the forced // account and folder are still selected. mediaElementPicker.MediaElementId = null; SetAccountAndFolderValues(mediaElementPicker, configurationValues); }
/// <summary> /// Sets the edit value from IEntity.Id value /// </summary> /// <param name="control">The control.</param> /// <param name="configurationValues">The configuration values.</param> /// <param name="id">The identifier.</param> public void SetEditValueFromEntityId(System.Web.UI.Control control, Dictionary <string, ConfigurationValue> configurationValues, int?id) { if (id.HasValue) { using (var rockContext = new RockContext()) { var mediaGuid = new MediaElementService(rockContext).GetGuid(id.Value); SetEditValue(control, configurationValues, mediaGuid.ToStringSafe()); } } else { SetEditValue(control, configurationValues, string.Empty); } }
/// <summary> /// Handles the DeleteClick event of the gElementList control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="Rock.Web.UI.Controls.RowEventArgs"/> instance containing the event data.</param> protected void gElementList_DeleteClick(object sender, Rock.Web.UI.Controls.RowEventArgs e) { var rockContext = new RockContext(); var mediaElementService = new MediaElementService(rockContext); var mediaElement = mediaElementService.Get(e.RowKeyId); if (mediaElement != null) { string errorMessage; if (!mediaElementService.CanDelete(mediaElement, out errorMessage)) { mdGridWarning.Show(errorMessage, ModalAlertType.Information); return; } mediaElementService.Delete(mediaElement); rockContext.SaveChanges(); } BindGrid(); }
/// <summary> /// Reads new values entered by the user for the field ( as Guid ) /// </summary> /// <param name="control">Parent control that controls were added to in the CreateEditControl() method</param> /// <param name="configurationValues">The configuration values.</param> /// <returns></returns> public override string GetEditValue(System.Web.UI.Control control, Dictionary <string, ConfigurationValue> configurationValues) { if (control is MediaElementPicker mediaElementPicker) { var rockContext = new RockContext(); if (mediaElementPicker.MediaElementId.IsNotNullOrZero()) { var mediaElementGuid = new MediaElementService(rockContext).Queryable() .Where(a => a.Id == mediaElementPicker.MediaElementId.Value) .Select(a => a.Guid) .SingleOrDefault(); if (mediaElementGuid != null) { return(mediaElementGuid.ToString()); } } } return(null); }
/// <summary> /// Formats the value as HTML. /// </summary> /// <param name="parentControl">The parent control.</param> /// <param name="value">The value.</param> /// <param name="configurationValues">The configuration values.</param> /// <param name="condensed">if set to <c>true</c> then the value will be displayed in a condensed area; otherwise <c>false</c>.</param> /// <returns></returns> public override string FormatValueAsHtml(Control parentControl, string value, Dictionary <string, ConfigurationValue> configurationValues, bool condensed = false) { var mediaElementGuid = value.AsGuidOrNull(); if (!mediaElementGuid.HasValue) { return(string.Empty); } using (var rockContext = new RockContext()) { var mediaInfo = new MediaElementService(rockContext).Queryable() .Where(a => a.Guid == mediaElementGuid.Value) .Select(a => new { a.Name, a.ThumbnailDataJson }) .SingleOrDefault(); if (mediaInfo == null) { return(string.Empty); } var thumbnails = mediaInfo.ThumbnailDataJson.FromJsonOrNull <List <MediaElementThumbnailData> >(); var thumbnailUrl = string.Empty; if (thumbnails != null) { if (condensed) { // Attempt to get the smallest thumbnail above 400px in // width. If that fails then just get the largest // thumbnail we have available. thumbnailUrl = thumbnails.Where(t => t.Link.IsNotNullOrWhiteSpace() && t.Width >= 400) .OrderBy(t => t.Height) .Select(t => t.Link) .FirstOrDefault() ?? string.Empty; if (thumbnailUrl == string.Empty) { thumbnailUrl = thumbnails.Where(t => t.Link.IsNotNullOrWhiteSpace()) .OrderByDescending(t => t.Height) .Select(t => t.Link) .FirstOrDefault() ?? string.Empty; } } else { thumbnailUrl = thumbnails.Where(t => t.Link.IsNotNullOrWhiteSpace()) .OrderByDescending(t => t.Height) .Select(t => t.Link) .FirstOrDefault() ?? string.Empty; } } if (condensed) { return($"<img src='{thumbnailUrl}' alt='{mediaInfo.Name.EncodeXml( true )}' class='img-responsive grid-img' />"); } else { return($"<img src='{thumbnailUrl}' alt='{mediaInfo.Name.EncodeXml( true )}' class='img-responsive' />"); } } }
public MediaElementInteraction GetWatchInteraction([FromUri] Guid?mediaElementGuid = null, [FromUri] Guid?personGuid = null, Guid?personAliasGuid = null) { var rockContext = Service.Context as RockContext; var personService = new PersonService(rockContext); var personAliasService = new PersonAliasService(rockContext); var interactionService = new InteractionService(rockContext); int?personAliasId; // Get the person alias to associate with the interaction in // order of provided Person.Guid, then PersonAlias.Guid, then // the logged in Person. if (personGuid.HasValue) { personAliasId = personAliasService.GetPrimaryAliasId(personGuid.Value); } else if (personAliasGuid.HasValue) { personAliasId = personAliasService.GetId(personAliasGuid.Value); } else { personAliasId = GetPersonAliasId(rockContext); } // Verify we have a person alias, otherwise bail out. if (!personAliasId.HasValue) { var errorResponse = Request.CreateErrorResponse(HttpStatusCode.BadRequest, $"The personAliasId could not be determined."); throw new HttpResponseException(errorResponse); } MediaElement mediaElement = null; // In the future we might make MediaElementGuid optional so // perform the check this way rather than making it required // in the parameter list. if (mediaElementGuid.HasValue) { mediaElement = new MediaElementService(rockContext).GetNoTracking(mediaElementGuid.Value); } // Ensure we have our required MediaElement. if (mediaElement == null) { var errorResponse = Request.CreateErrorResponse(HttpStatusCode.BadRequest, $"The MediaElement could not be found."); throw new HttpResponseException(errorResponse); } // Get (or create) the component. var interactionChannelId = InteractionChannelCache.Get(SystemGuid.InteractionChannel.MEDIA_EVENTS).Id; var interactionComponentId = InteractionComponentCache.GetComponentIdByChannelIdAndEntityId(interactionChannelId, mediaElement.Id, mediaElement.Name); Interaction interaction = interactionService.Queryable() .AsNoTracking() .Include(a => a.PersonAlias) .Where(a => a.InteractionComponentId == interactionComponentId) .Where(a => a.PersonAliasId == personAliasId || a.PersonAlias.Person.Aliases.Any(b => b.Id == personAliasId)) .OrderByDescending(a => a.InteractionEndDateTime) .ThenByDescending(a => a.InteractionDateTime) .FirstOrDefault(); if (interaction == null) { var errorResponse = Request.CreateErrorResponse(HttpStatusCode.NotFound, $"The Interaction could not be found."); throw new HttpResponseException(errorResponse); } var data = interaction.InteractionData.FromJsonOrNull <MediaWatchedInteractionData>(); return(new MediaElementInteraction { InteractionGuid = interaction.Guid, MediaElementGuid = mediaElement.Guid, PersonGuid = interaction.PersonAlias.Person?.Guid, PersonAliasGuid = interaction.PersonAlias.Guid, RelatedEntityTypeId = interaction.RelatedEntityTypeId, RelatedEntityId = interaction.RelatedEntityId, WatchMap = data?.WatchMap ?? string.Empty }); }
public MediaElementInteraction PostWatchInteraction(MediaElementInteraction mediaInteraction) { var rockContext = Service.Context as RockContext; var personService = new PersonService(rockContext); var personAliasService = new PersonAliasService(rockContext); var interactionService = new InteractionService(rockContext); int?personAliasId; if (!IsWatchMapValid(mediaInteraction.WatchMap)) { var errorResponse = Request.CreateErrorResponse(HttpStatusCode.BadRequest, $"The WatchMap contains invalid characters."); throw new HttpResponseException(errorResponse); } // Get the person alias to associate with the interaction in // order of provided Person.Guid, then PersonAlias.Guid, then // the logged in Person. if (mediaInteraction.PersonGuid.HasValue) { personAliasId = personAliasService.GetPrimaryAliasId(mediaInteraction.PersonGuid.Value); } else if (mediaInteraction.PersonAliasGuid.HasValue) { personAliasId = personAliasService.GetId(mediaInteraction.PersonAliasGuid.Value); } else { personAliasId = GetPersonAliasId(rockContext); } var mediaElement = new MediaElementService(rockContext).GetNoTracking(mediaInteraction.MediaElementGuid); // Ensure we have our required MediaElement. if (mediaElement == null) { var errorResponse = Request.CreateErrorResponse(HttpStatusCode.BadRequest, $"The MediaElement could not be found."); throw new HttpResponseException(errorResponse); } // Get (or create) the component. var interactionChannelId = InteractionChannelCache.Get(SystemGuid.InteractionChannel.MEDIA_EVENTS).Id; var interactionComponentId = InteractionComponentCache.GetComponentIdByChannelIdAndEntityId(interactionChannelId, mediaElement.Id, mediaElement.Name); Interaction interaction = null; if (mediaInteraction.InteractionGuid.HasValue) { // Look for an existing Interaction by it's Guid and the // component it is supposed to show up under. But also // check that the RelatedEntityTypeId/RelatedEntityId values // are either null or match what was passed by the user. // Finally also make sure the Interaction Person Alias is // either the one for this user OR if there is a Person // record attached to that alias that the alias Id we have is // also attached to that Person record OR the interaction is // not tied to a person. interaction = interactionService.Queryable() .Where(a => a.Guid == mediaInteraction.InteractionGuid.Value && a.InteractionComponentId == interactionComponentId) .Where(a => !a.RelatedEntityTypeId.HasValue || !mediaInteraction.RelatedEntityTypeId.HasValue || a.RelatedEntityTypeId == mediaInteraction.RelatedEntityTypeId) .Where(a => !a.RelatedEntityId.HasValue || !mediaInteraction.RelatedEntityId.HasValue || a.RelatedEntityId == mediaInteraction.RelatedEntityId) .Where(a => !a.PersonAliasId.HasValue || a.PersonAliasId == personAliasId || a.PersonAlias.Person.Aliases.Any(b => b.Id == personAliasId)) .SingleOrDefault(); } var watchedPercentage = CalculateWatchedPercentage(mediaInteraction.WatchMap); if (interaction != null) { // Update the interaction data with the new watch map. var data = interaction.InteractionData.FromJsonOrNull <MediaWatchedInteractionData>() ?? new MediaWatchedInteractionData(); data.WatchMap = mediaInteraction.WatchMap; data.WatchedPercentage = watchedPercentage; interaction.InteractionData = data.ToJson(); interaction.InteractionLength = watchedPercentage; interaction.InteractionEndDateTime = RockDateTime.Now; interaction.PersonAliasId = interaction.PersonAliasId ?? personAliasId; if (mediaInteraction.RelatedEntityTypeId.HasValue) { interaction.RelatedEntityTypeId = mediaInteraction.RelatedEntityTypeId; } if (mediaInteraction.RelatedEntityId.HasValue) { interaction.RelatedEntityId = mediaInteraction.RelatedEntityId; } } else { // Generate the interaction data from the watch map. var data = new MediaWatchedInteractionData { WatchMap = mediaInteraction.WatchMap, WatchedPercentage = watchedPercentage }; interaction = interactionService.CreateInteraction(interactionComponentId, null, "Watch", string.Empty, data.ToJson(), personAliasId, RockDateTime.Now, null, null, null, null, null, null); interaction.InteractionLength = watchedPercentage; interaction.InteractionEndDateTime = RockDateTime.Now; interaction.RelatedEntityTypeId = mediaInteraction.RelatedEntityTypeId; interaction.RelatedEntityId = mediaInteraction.RelatedEntityId; interactionService.Add(interaction); } rockContext.SaveChanges(); mediaInteraction.InteractionGuid = interaction.Guid; return(mediaInteraction); }
/// <summary> /// Updates the options from a <see cref="MediaElement"/>. If one is /// not found then no changes are made. /// </summary> /// <param name="options">The options to be updated.</param> /// <param name="mediaElementId">The media element identifier.</param> /// <param name="mediaElementGuid">The media element unique identifier.</param> /// <param name="autoResumeInDays">The number of days back to look for an existing watch map to auto-resume from. Pass -1 to mean forever or 0 to disable.</param> /// <param name="combinePlayStatisticsInDays">The number of days back to look for an existing interaction to be updated. Pass -1 to mean forever or 0 to disable.</param> /// <param name="currentPerson">The person to use when searching for existing interactions.</param> internal static void UpdateValuesFromMedia(this MediaPlayerOptions options, int?mediaElementId, Guid?mediaElementGuid, int autoResumeInDays, int combinePlayStatisticsInDays, Person currentPerson) { if (!mediaElementId.HasValue && !mediaElementGuid.HasValue) { return; } using (var rockContext = new RockContext()) { var mediaElementService = new MediaElementService(rockContext); var interactionService = new InteractionService(rockContext); var mediaEventsChannelGuid = Rock.SystemGuid.InteractionChannel.MEDIA_EVENTS.AsGuid(); var now = RockDateTime.Now; MediaElement mediaElement = null; // Load the media element by either Id or Guid value. if (mediaElementId.HasValue) { mediaElement = mediaElementService.Get(mediaElementId.Value); } else { mediaElement = mediaElementService.Get(mediaElementGuid.Value); } // No media found means we don't have anything to do. if (mediaElement == null) { return; } options.MediaUrl = mediaElement.DefaultFileUrl; options.MediaElementGuid = mediaElement.Guid; // Let the users value override the default thumbnail. if (options.PosterUrl.IsNullOrWhiteSpace()) { options.PosterUrl = mediaElement.DefaultThumbnailUrl; } // Check if either autoResumeInDays or combinePlayStatisticsInDays // are enabled. If not we are done. if (autoResumeInDays == 0 && combinePlayStatisticsInDays == 0) { return; } // If we don't have a person, then we can't get interactions. if (currentPerson == null) { return; } // Build a query to find Interactions for this person having // previously watched this media element. var interactionQry = interactionService.Queryable() .Where(i => i.InteractionComponent.InteractionChannel.Guid == mediaEventsChannelGuid && i.InteractionComponent.EntityId == mediaElement.Id && i.PersonAlias.PersonId == currentPerson.Id); // A negative value means "forever". int daysBack = Math.Max(autoResumeInDays >= 0 ? autoResumeInDays : int.MaxValue, combinePlayStatisticsInDays >= 0 ? combinePlayStatisticsInDays : int.MaxValue); // A value of MaxValue means "forever" now so we don't need // to filter on it. if (daysBack != int.MaxValue) { var limitDateTime = now.AddDays(-daysBack); interactionQry = interactionQry.Where(i => i.InteractionDateTime >= limitDateTime); } // Look for the most recent Interaction. var interaction = interactionQry.OrderByDescending(i => i.InteractionDateTime) .Select(i => new { i.Guid, i.InteractionDateTime, i.InteractionData }) .FirstOrDefault(); // If we didn't find any interaction then we are done. if (interaction == null) { return; } // Check if this interaction is within our auto-resume window. if (autoResumeInDays != 0) { if (autoResumeInDays < 0 || interaction.InteractionDateTime >= now.AddDays(-autoResumeInDays)) { options.ResumePlaying = true; var data = interaction.InteractionData.FromJsonOrNull <MediaWatchedInteractionData>(); options.Map = data?.WatchMap; } } // Check if this interaction is within our combine window. if (combinePlayStatisticsInDays != 0) { if (combinePlayStatisticsInDays < 0 || interaction.InteractionDateTime >= now.AddDays(-combinePlayStatisticsInDays)) { options.InteractionGuid = interaction.Guid; } } } }