Copied to clipboard

Flag this post as spam?

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


  • Jeroen Breuer 4908 posts 12265 karma points MVP 5x admin c-trib
    Sep 05, 2012 @ 09:46
    Jeroen Breuer
    1

    New node at top in the tree

    Hello,

    When a new node is created it is always added at the bottom in the Umbraco tree. Is there an easy way for the created node to appear at the top in the tree right under the parent? 

    Should I create an event after a new node is created which updates the sort value of all nodes or is there a better way?

    Jeroen

  • Stephen 767 posts 2273 karma points c-trib
    Sep 05, 2012 @ 09:56
    Stephen
    0

    Yes, I'd say you have to sort the nodes in an event handler. Which can be tricky, programmatically, because you have to update the DB, the XML cache, the preview XML, etc etc etc.

  • Jeroen Breuer 4908 posts 12265 karma points MVP 5x admin c-trib
    Sep 05, 2012 @ 10:10
    Jeroen Breuer
    0

    That's what I thought. Guess that means I'll need to get all the nodes under the parent (as Document), update the sort value and publish them if they already are published:

    doc.Publish(author);
    umbraco.library.UpdateDocumentCache(doc.Id)

    Can't wait for that new API in v6. Should make things like this easier :-).

    Jeroen

  • Stephen 767 posts 2273 karma points c-trib
    Sep 05, 2012 @ 10:36
    Stephen
    2

    Beware! One nasty bug here. If you publish a node that is already published, then you'll publish ongoing changes. That is, if you already have node A and B and both are published, and you edit and save (but do not publish) node A... then add node C, you'll inadvertently publish node A.

    Here's some code we're using to reorder one document's children.

            public static void ReorderChildren(this Document document, IEnumerable<Document> children, bool refreshEntireCache)
            {
                // this is copied and adapted from nodeSorter.asmx.cs

                // this is insane, there is absolutely no concurrency management in umbraco ?!
                lock (LockObject(document))
                {
                    bool pathPublished = document.PathPublished;

                    int sortOrder = 0;
                    foreach (Document child in children)
                    {
                        child.sortOrder = sortOrder++;

                        if (child.Published)
                        {
                            // refresh sort order in cmsContentXml
                            child.refreshXmlSortOrder();
                            // refresh document in cache, only if cached
                            if (pathPublished)
                                umbraco.library.UpdateDocumentCache(child.Id);
                        }

                        // refresh sort order in preview xml (cmsPreviewXml)
                        child.refreshPreviewXmlSortOrder();
                    }

                    // refresh sort order on cached xml
                    if (document.Published)
                    {
                        // use UmbracoContext because Instance.XmlContent fails with preview
                        //var umbracoXML = umbraco.content.Instance.XmlContent;
                        var umbracoXML = umbraco.presentation.UmbracoContext.Current.GetXml();
                        XmlNode node = umbracoXML.GetElementById(document.Id.ToString());
                        umbraco.content.SortNodes(ref node);
                    }

                    // load balancing - refresh entire cache
                    if (refreshEntireCache && umbraco.UmbracoSettings.UseDistributedCalls)
                        umbraco.library.RefreshContent();
                }
            }

  • Jeroen Breuer 4908 posts 12265 karma points MVP 5x admin c-trib
    Sep 05, 2012 @ 10:46
    Jeroen Breuer
    0

    Hello,

    I'm aware of the problem about of publishing ongoing changes. That's why I started a thread for it here, but I don't think it will be added to the core: https://groups.google.com/forum/#!searchin/umbraco-dev/partial$20publish/umbraco-dev/5LR6fxt6XJU/YVQF4qmolrkJ. Your code looks like a better solution :-). Thanks!

    Jeroen

  • Jeroen Breuer 4908 posts 12265 karma points MVP 5x admin c-trib
    Sep 17, 2012 @ 16:20
    Jeroen Breuer
    0

    Hello,

    I tried to use your code example, but I'm missing some pieces. Could you please show those parts as well? I'm missing:

    LockObject(document)
    document.PathPublished
    child.refreshPreviewXmlSortOrder();

    Thanks :).

    Jeroen

  • Tom Fulton 2030 posts 4998 karma points c-trib
    Sep 17, 2012 @ 17:19
    Tom Fulton
    1

    Hi Jeroen,

    I think you could also use Document Sorter and have it sort by createDate Descending to achieve the same effect.

    HTH,
    Tom 

  • Murray Roke 503 posts 966 karma points c-trib
    Jul 07, 2014 @ 23:54
    Murray Roke
    0

    Here's my solution, which I devised to avoid updating any document apart from the one being inserted.

    documentBeingSaved.sortOrder = GetTopSortOrdinal(documentBeingSaved);
    

    ...

    private static int GetTopSortOrdinal(Document document)
    {
        return new Document(document.Parent.Children.First().Id).sortOrder -1;
    }
    
  • Paul Bowen 11 posts 76 karma points
    Oct 30, 2014 @ 22:53
    Paul Bowen
    2

    I have a solution using the ContentService in v6.1. Thanks to Murray for pointing me in the right direction.

    It uses the splendidly named IRememberBeingDirty interface to check if the content is new. It also allows you to enter a list of the templates to restrict the event firing on and it will only fire on content lists with a single value, not e.g. when sorting the tree or moving multiple nodes etc.

        public class UmbracoEventHandler : ApplicationEventHandler
    {
        public UmbracoEventHandler()
        {       
            ContentService.Saving += OnSaving;
        }
    
        /// <summary>
        ///  On save, if there is one item to save, if the item is new (uses IRememberBeingDirty) and the template is in the acceptable list...
        ///  The sort order is set to one less than the current top child in the list to ensure the content appears at the top of its node tree.
        /// </summary>
        void OnSaving(IContentService sender, SaveEventArgs<IContent> args)
        {
            if (args.SavedEntities.Count() == 1)
            {
                var dirty = (IRememberBeingDirty)args.SavedEntities.First();
                var isNew = dirty.WasPropertyDirty("Id"); // N.B. In 6.2+ use: content.IsNewEntity(); 
    
                var templates = new List<string> { "ApplicationDetailPage", "EventGenericDetailPage", "GenericDetailPage", "TechnologyDetailPage" };
    
                if (isNew && args.SavedEntities.First().Level > 1 && args.SavedEntities.First().Template != null && templates.Contains(args.SavedEntities.First().Template.Alias))
                {
                    var firstChild = args.SavedEntities.First().Parent().Children().OrderBy(o => o.SortOrder).FirstOrDefault();
                    if (firstChild != null)
                    {
                        args.SavedEntities.First().SortOrder = firstChild.SortOrder - 1;
                    }
                }
            }
        }
    }
    
Please Sign in or register to post replies

Write your reply to:

Draft