Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Sören Deger 726 posts 2833 karma points c-trib
    May 12, 2014 @ 11:56
    Sören Deger
    0

    Dynamically set starting node of media picker in richtext editor

    Hi,

    is there a way in the richtext editor dynamically set the starting node of the image picker? 

    For example:
    I set a Media Folder ID in each content node. If I use the Media Picker it would be nice if this media folder is then used as the starting node so you do not have to click through a very extensive media structure.

    Is this possible?

     

    Best regards

    Sören

  • Dr. Sugus 26 posts 101 karma points
    Nov 07, 2014 @ 10:13
    Dr. Sugus
    0

    Hey Sören - did you ever solve this?

  • Sören Deger 726 posts 2833 karma points c-trib
    Nov 07, 2014 @ 10:56
    Sören Deger
    0

    Hi Dr. Sugus,

    no, I have not.
     

    Sören

  • jivan thapa 194 posts 660 karma points
    Nov 07, 2014 @ 12:31
    jivan thapa
    100

    Hi, Soren, It may be possible by overriding a method

     protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            { }
    

    Create a class that inherits from "DelegatingHandler".

    This may help you, http://our.umbraco.org/forum/developers/extending-umbraco/57576-How-to-get-context-node-id-in-Custom-Property-Editor

  • Sören Deger 726 posts 2833 karma points c-trib
    Nov 07, 2014 @ 13:04
    Sören Deger
    0

    Hi Jivan,

    great :-) Thank you!

  • keilo 560 posts 1015 karma points
    Nov 11, 2014 @ 18:01
    keilo
    0

    Hi Soren

    I am using the MediaSync package and I can see how this can be very handy coupled with that package.

    Is there a finalized script that I can drop to App_Code for this to work, or is your final solution too customized?

     

    cheers

  • Sören Deger 726 posts 2833 karma points c-trib
    Nov 12, 2014 @ 08:45
    Sören Deger
    0

    Hi keilo,

    the above requirement for the rich text editor is not related to the uMediaSync package. This was only once a special request for a customer project in which uMediaSync but not used. I did this not also implemented in uMediaSync and currently have unfortunately no time for it, because I'm still busy with other larger projects. But if you can integrate this, of course, I can gladly update the package with your solution.

    Sören

  • Dr. Sugus 26 posts 101 karma points
    Nov 12, 2014 @ 09:30
    Dr. Sugus
    0

    I "solved" it for the media picker in the native RTE the following way. I basically get the id of the media node being loaded - if it is the root, I redirect to another media node id before the root one is loaded. In the example below I hardcoded the "custom root" - irl I use a variable that defines which root I want. I also have some logic to prevent uploading to different media folders, that is not shown in the simplified example below.

    public class MyApiHandler : System.Net.Http.DelegatingHandler
    {
       
    protectedoverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
       
    {
         
    var user =UmbracoContext.Current.Security.CurrentUser;

         
    // If current user is not admin
         
    if(user !=null&& user.Name!="admin")
         
    {
           
    // Catch content tree load events
           
    switch(request.RequestUri.AbsolutePath.ToLower())
           
    {
             
    // Content of RTE media picker
    case "/umbraco/backoffice/umbracoapi/media/getchildren":
    return FilterAllowedRteMedia(request, cancellationToken, user);
    case "/umbraco/backoffice/umbracoapi/entity/getancestors":
    return FilterAllowedRteMedia(request, cancellationToken, user);

             
    default:
               
    returnbase.SendAsync(request, cancellationToken);
           
    }
         
    }

         
    returnbase.SendAsync(request, cancellationToken);

       
    }

       
    private Task FilterAllowedRteMedia(HttpRequestMessage request, CancellationToken cancellationToken,
    Umbraco.Core.Models.Membership.IUser user)
    {
    var selectedNodeId = request.RequestUri.Query
    .Split('&')
    .FirstOrDefault()
    .Replace("?id=", String.Empty);

    // Set media root for RTEs
    if (selectedNodeId == "-1")
    {
    request.RequestUri = new Uri(request.RequestUri.ToString().Replace(String.Format("?id={0}&", selectedNodeId),
    String.Format("?id={0}&", 1061)));
    }

    return base.SendAsync(request, cancellationToken);
    }

  • keilo 560 posts 1015 karma points
    Nov 16, 2014 @ 16:05
    keilo
    0

    Hi Soren

    I didnt mean as direct integration, I am ok to enter the media node ids for the top level nodes inside a property - as they wont change moving forward.

    I was trying to figure if there is a complete .cs file(s) that I can drop to App_Code and change the property name to read the media root ID.

  • keilo 560 posts 1015 karma points
    Nov 16, 2014 @ 16:13
    keilo
    0

    Hi Dr Sugus

    Is there a quick patch that once can add to that code, to make it read the media root id (1061)  from the CurrentPage's Parent at Level 2 property like mediaRootID ?

    Would be interested to see the complete code you mentioned, where prevention of certain nodes is handled - its very helpfull in the learning curve.

    A bit off-topic, I was reading another post on protecting media, i.e. allowing only certain media to be downloaded on the front-end only if a user logged in. Looking at the way these event interrupts handled in v7, do you think there is an easy way to accomplish such? i.e. only allow media download if Membership.GetUser()!=null

  • Dr. Sugus 26 posts 101 karma points
    Nov 17, 2014 @ 09:09
    Dr. Sugus
    0

    Hi Keilo

    I'm not sure I understand the "from the CurrentPage's Parent at Level 2 property like mediaRootID" part - I didn't find a way to get the current content node id though, so if that is part of what you want to do, I'd be very interested in seeing how you get about it :)

    About members vs. media - I don't know of any best practices, but I guess one could implement some logic in the views. If the current user is part of a certain member group, show download link?

  • keilo 560 posts 1015 karma points
    Nov 17, 2014 @ 10:19
    keilo
    0

    Hi Dr Sugus

    I understand Soren has figured out a way to get the Media Root ID from the current page (at least thats what i grasp from his post above) and was wondering if there is a complete example that we can refer to.

    In regards to "CurrentPage's Parent at Level x", assuming we manage to read the property from the current node, and we have a structure like;

    A (Level 2)  - custom property mediaRootID

     a1  (level 3)

     a2

      a21   (level 4)

        a211   (level 5)

         a2111   (level 6)

      ....

    On any of the the sub-nodes like a211 (doesnt matter how deep it is), we will read the custom property MediaRootID of its parent at Level 2 (A).

    Say we capture the media root id for all pages at Level 2, and all sub-levels pages of Level 2 will be opening the Media Root folder (id) that is defined in their parent node at Level 2.

    like @Model.AncestorOrSelf(2)   as discussed here http://our.umbraco.org/forum/developers/razor/18203-Best-way-of-getting-ancestor-of-specific-level

     

    Let me know i managed to clarify.

  • Dr. Sugus 26 posts 101 karma points
    Nov 17, 2014 @ 13:42
    Dr. Sugus
    0

    Hi Keilo

    It's perfectly clear now; as long as one finds a way of getting the current content node, this should be possible. As mentioned I did not find a way with the time I had, but I too would be keen to see if anyone else has solved it.

  • jivan thapa 194 posts 660 karma points
    Nov 17, 2014 @ 16:16
    jivan thapa
    1

    Hi, Kelio. I am not sure, what's your requirements. If I understood correctly, You would like to set Media picker's start node id to the id that you defined on a Content page "A (Level 2) - custom property mediaRootID"

    I assume that mediaRootID = Integer (Id of media folder) and media picker that used as a picker is a "Media picker". "Media picker" and "Legacy media picker" are different.

    Here is my approach. You can use this for an idea,

      public class MediaPickerExtension : DelegatingHandler
        {
            /// <summary>
            /// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation.
            /// </summary>
            /// <param name="request">The HTTP request message to send to the server.</param>
            /// <param name="cancellationToken">A cancellation token to cancel operation.</param>
            /// <returns>
            /// Returns <see cref="T:System.Threading.Tasks.Task`1" />. The task object representing the asynchronous operation.
            /// </returns>
            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                var path = request.RequestUri.AbsolutePath.ToLower();
                switch (path)
                {
                    case "/umbraco/backoffice/umbracoapi/content/getempty":
                    case "/umbraco/backoffice/umbracoapi/content/getbyid":
                        return SetMediaRootStartNode(request, cancellationToken);
                    default:
                        return base.SendAsync(request, cancellationToken);
                }
            }
    
            /// <summary>
            /// Sets the media root start node.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <param name="cancellationToken">The cancellation token.</param>
            /// <returns></returns>
            private Task<HttpResponseMessage> SetMediaRootStartNode(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                return base.SendAsync(request, cancellationToken)
                   .ContinueWith(task =>
                   {
                       var response = task.Result;
                       try
                       {
                           //Get the current content
                           var d = response.Content;
                           var c = ((ObjectContent)(d)).Value as ContentItemDisplay;
    
                           if (c != null)
                               SetStartNode(request, Convert.ToInt32(c.Id), c.ContentTypeAlias, c.Properties);
                       }
                       catch (Exception ex)
                       {
                           // 
                           // "Error:: picker start node."
                       }
                       return response;
                   }, cancellationToken);
            }
    
            /// <summary>
            /// Sets the start node.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <param name="toInt32">To int32.</param>
            /// <param name="contentTypeAlias">The content type alias.</param>
            /// <param name="properties">The properties.</param>
            private void SetStartNode(HttpRequestMessage request, int toInt32, string contentTypeAlias, IEnumerable<ContentPropertyDisplay> properties)
            {
                var mediaNodePickers = properties.Where(x =>
                  Constants.PropertyEditors.MultipleMediaPickerAlias.InvariantEquals(x.Editor)).ToList();
    
                if (!mediaNodePickers.Any()) return;
    
                var contextNode = ApplicationContext.Current.Services.ContentService.GetById(toInt32);
                if (contextNode == null || contextNode.Level < 2) return;
    
    
                // here you get the node (A-level 2 custom property mediaRootID)
    
                var m =
                    contextNode.Ancestors()
                        .FirstOrDefault(
                            x =>
                                x.HasProperty("mediaRootId") && !string.IsNullOrEmpty(x.GetValue<string>("mediaRootId")));
    
                if(m==null) return;
    
                // find media start node, specified on level 2
                var startMediaRootId = m.GetValue<int>("mediaRootId");
    
                var contentPropertyDisplay = mediaNodePickers.FirstOrDefault();
    
                if (contentPropertyDisplay != null)
                {
                    var configs = contentPropertyDisplay.Config;
    
                    if (configs.ContainsKey("startNodeId"))
                    {
                        configs["startNodeId"] = startMediaRootId;
                    }
                    else
                    {
                        configs.Add("startNodeId", startMediaRootId);
                    }
    
                }
            }
        }
    

    And finally hookup on Umbraco application starting

     public class UmbracoStartUp : IApplicationEventHandler
        {
            public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
               // throw new NotImplementedException();
            }
    
            public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
               //hookup the MediaPickerExtension 
                GlobalConfiguration.Configuration.MessageHandlers.Add(new MediaPickerExtension());
            }
    
            public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
               // throw new NotImplementedException();
            }
        }
    
  • keilo 560 posts 1015 karma points
    Nov 17, 2014 @ 17:19
    keilo
    0

    Hi Jivan

    Thank you for the example! Sorry for the convoluted description. I guess what Im trying to do can be explained simly 'how to retrieve media picker root folder from current page's parent x and open media picker at that folder'. Thinking about it, actually one can retrieve that value recursively too, like .GetProperty("mediaRootID",true) so it climbs up the tree until it finds a mediaRootID - this way one can define mediaroot overrides at any level.

    You assumption is correct, mediaRootID is integer and MediaPicker datatype used in pages are of "Media picker" and not legacy picker.

    I have tried to run you code on the remote system by placing it under App_Code folder. Since I dont have access to Visual Studio at this time, I have tried to add the references below, but i think missing obvious ones;

    using System;

    using System.Collections.Generic;

    using System.Threading;

    using System.Threading.Tasks;

    using System.Linq;

    using System.Net.Http;

     

    using Umbraco.Core;

    using Umbraco.Web;

     

    compilation error:

     'Umbraco.Core.Models.IContent' does not contain a definition for 'Ancestors' and the best extension method overload 'Umbraco.Web.PublishedContentExtensions.Ancestors(Umbraco.Core.Models.IPublishedContent)

    on 

     var m =

                contextNode.Ancestors()

                        .FirstOrDefault(

                             x =>

     

    What would be the complete using references I should be adding?

     

  • jivan thapa 194 posts 660 karma points
    Nov 17, 2014 @ 17:33
    jivan thapa
    1

    Here are the references i have used. // for MediaPickerExtension class

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web;
    using Umbraco.Core;
    using Umbraco.Core.Logging;
    using Umbraco.Core.Models;
    using Umbraco.Web.Models.ContentEditing;
    

    // for UmbracoStartUp : IApplicationEventHandler

    using System.Web.Http;
    using Umbraco.Core;
    
  • jivan thapa 194 posts 660 karma points
    Nov 17, 2014 @ 17:34
    jivan thapa
    1

    I have tested on Umbraco 7.1.8 Here are the references i have used. // for MediaPickerExtension class

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web;
    using Umbraco.Core;
    using Umbraco.Core.Logging;
    using Umbraco.Core.Models;
    using Umbraco.Web.Models.ContentEditing;
    

    // for UmbracoStartUp : IApplicationEventHandler

    using System.Web.Http;
    using Umbraco.Core;
    
  • jivan thapa 194 posts 660 karma points
    Nov 17, 2014 @ 17:34
    jivan thapa
    1

    I have tested on Umbraco 7.1.8 Here are the references i have used. // for MediaPickerExtension class

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web;
    using Umbraco.Core;
    using Umbraco.Core.Logging;
    using Umbraco.Core.Models;
    using Umbraco.Web.Models.ContentEditing;
    

    // for UmbracoStartUp : IApplicationEventHandler

    using System.Web.Http;
    using Umbraco.Core;
    
  • keilo 560 posts 1015 karma points
    Nov 17, 2014 @ 18:18
    keilo
    0

    Hi again Jivan

    Many thanks for the quick reply. added references to both accordingly and no errors. I am using 7.1.8 too.

    I have double checked; at level 2 node ,i have property mediaRootID (alias matches) is of Numeric data type, with value of media folder ID like 1325 (media->Doc/Images/Gallery2).  and sub-pages of this node contain Media Picker (not legacy).

    When i open the sub-page (tried children, also descendant) of level-2 node, of above, and select media picker, it doesnt change the root folder in the dialog.

    Is there something I might be missing?

     

  • jivan thapa 194 posts 660 karma points
    Nov 17, 2014 @ 19:07
    jivan thapa
    0

    HI, Kello, Could you try changing uppercase D to lowercase d. I guess mediaRootID => mediaRootId

  • keilo 560 posts 1015 karma points
    Nov 17, 2014 @ 19:25
    keilo
    0

    Ahh.. that was it. I could swear I checked that.

    Its working smooth! Can this logic be adapted if one wants to incorporate this to the RichText Editor Image dialog? 

    Many thanks again for the great help!

  • Pagggy 21 posts 40 karma points
    Apr 22, 2020 @ 13:12
    Pagggy
    0

    Hi Everyone, did anyone managed to implement this in umbraco 8.1?

Please Sign in or register to post replies

Write your reply to:

Draft