using locate folder and displaying its contents

Nando's Avatar

Nando

05 Feb, 2016 04:23 PM

I created an asset factory to create video blocks and put them in a specific folder.. I'd like to use the locate folder tool to display all those videos on a page...

can I use the locate folder tool or do I have to use the locate block tool? having a hard time getting this piece started...

as always, thanks in advance!

  1. 1 Posted by Ryan Griffith on 05 Feb, 2016 04:28 PM

    Ryan Griffith's Avatar

    Hi,

    You can definitely use locateFolder assuming you need the children of that specific folder.

    What you would do is use locateFolder and loop over the returned object's children property. Each child will effectively be each Block object that you can run things like getStructuredDataNode on to obtain their content.

    Please let me know if you have any questions.

    Thanks!

  2. 2 Posted by Nando on 05 Feb, 2016 04:55 PM

    Nando's Avatar

    for testing, I'm trying something like this and its not working :(

    #set ($vlocation = $_.locateFolder('/_library/blocks/videos', $currentPageSiteName))##
    #set ($videos = $vlocation.videos)
    #foreach($video in $videos)
    1
    #end
    

    I should be getting like 7 instances of the #1... no?

  3. 3 Posted by Nando on 05 Feb, 2016 04:58 PM

    Nando's Avatar

    my mistake... I had to use #set ($videos = $vlocation.children) and it worked!

    can i get the blocks from a subfolder without specifying the subfolder?

  4. 4 Posted by Ryan Griffith on 05 Feb, 2016 07:53 PM

    Ryan Griffith's Avatar

    Hi,

    Correct, you would need to use .children to traverse the folder's contents.

    If you wanted to go into a subfolder, you would need to check the child's type to see if it's a folder and, if so, loop over it's children. I would recommend abstracting the processing of a folder into a macro so you can take advantage of recursion as opposed to nested loops.

    Please let me know if you have any questions.

    Thanks!

  5. 5 Posted by Nando on 05 Feb, 2016 07:59 PM

    Nando's Avatar

    this is what I came up with and it works but I'm not sure if its right.. its checking all the subfolders...

    #set ($vlocation = $_.locateFolder('/_library/blocks/videos', $currentPageSiteName))##
    #foreach($children in $vlocation.children)
    #foreach($block in $children.children)
    #if($block.dataDefinitionPath == "Capital Campaign Video")
    $block.name
    #end
    #end            
    #end
    

    not sure how to search for blocks only so i did it by datadef...

    also, not sure how to get any more information in the addition to the name... was trying something like #set($title = $block..getStructuredDataNode("title").textValue) but no go...

    thanks!

  6. 6 Posted by Ryan Griffith on 05 Feb, 2016 08:09 PM

    Ryan Griffith's Avatar

    Hi,

    I picture something more like the following:

    #traverseFolder($vlocation)
    
    #macro(traverseFolder $folder)
      #if($folder.children.size() > 0)
        #foreach($child in $folder.children)
          #if ($child.identifier.type == "folder")
            #traverseFolder($folder)
          #elseif ($child.identifier.type == "block")
            #showVideo($child)
          #end
        #end
      #end
    #end
    
    #macro(showVideo $block)
      #if ($block.dataDefinitionPath == "Capital Campaign Video")
        ## Do something with the video data
      #end
    #end
    

    also, not sure how to get any more information in the addition to the name... was trying something like #set($title = $block..getStructuredDataNode("title").textValue) but no go...

    What you use depends on what data you need. If you need a static metadata field, it's as simple as $block.metadata.title, if dynamic metadata $block.metadata.getDynamicField("field-identifier"), and if it's structured data (ie a data definition field) you would use either $block.getStructuredDataNode("path/to/identifier) or $block.getStructuredDataNodes("path/to/identifier) (if a multiple).

    For additional information on what properties are available for a particular object, use the Property Tool's outputProperties method: $_PropertyTool.outputProperties($block).

    Please let me know if you have any questions.

    Thanks!

  7. 7 Posted by Nando on 05 Feb, 2016 08:21 PM

    Nando's Avatar

    thanks!

    testing your example code gives me an error:

    An error occurred while rendering asset preview: org.apache.velocity.exception.MacroOverflowException: Max calling depth of 20 was exceeded in macro 'traverseFolder' with Call Stack:traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder->traverseFolder at velocityTransform-1454703621219[line 49, column 1]
    
  8. 8 Posted by Nando on 05 Feb, 2016 08:25 PM

    Nando's Avatar

    If I dont check if its a folder, it works fine...

    #macro(traverseFolder $folder)
      #if($folder.children.size() > 0)
        #foreach($child in $folder.children)
         #if ($child.identifier.type == "block")
            #showVideo($child)
          #end
        #end
      #end
    #end
    

    do I need it to check if its a folder? sub folders wont have sub folders...

  9. 9 Posted by Ryan Griffith on 05 Feb, 2016 08:41 PM

    Ryan Griffith's Avatar

    Whoops, my fault, there was a bug in my Format code.

    The line that has #traverseFolder($folder) should read #traverseFolder($child). This was resulting in an infinite loop. Let me know how things work out after making this adjustment.

    Please let me know if you have any questions.

    Thanks!

  10. 10 Posted by Nando on 05 Feb, 2016 08:43 PM

    Nando's Avatar

    ah nice!

    last thing, last thing...

    how can I limit the number shown and order them... all of them, not just from each folder?

  11. 11 Posted by Ryan Griffith on 05 Feb, 2016 09:05 PM

    Ryan Griffith's Avatar

    Hi,

    In that case, you would probably need to create an array of objects so you can check the size as well as sort by the object properties.Then, you would loop over the resulting array.

    Now that I think of it, the Query API might be a better solution here. What you could do is query for blocks that have a specific Metadata Set and limit it to a specific number and add them to the lookup table I mentioned above. Something like the following:

    #set($query = $_.query()) 
    #set($query = $query.byMetadataSet("Basic"))
    #set($query = $query.includeBlocks(true).includeFiles(false).includeFolders(false).includeSymlinks(false))
    #set($blocks = $query.maxResults(10).execute())
    #set($videoArr = [])
    
    #if ($blocks.size() > 0)
        #foreach ($block in $blocks)
            #set ($void = $videoArr.add({
                "id": $block.identifier.id,
                "name": $block.name,
                "path": $block.path,
                "Block": $block
            }))
        #end
        #foreach ($video in $_SortTool.sort($videoArr, "name:asc"))
            $video.name
        #end
    #end
    

    Please let me know if you have any questions.

    Thanks!

  12. 12 Posted by Nando on 05 Feb, 2016 09:10 PM

    Nando's Avatar

    hmmm.. I'm not sure where to put that in relation with the code you provided before... where would i set the folder to query?

  13. 13 Posted by Nando on 06 Feb, 2016 01:22 AM

    Nando's Avatar

    so no query by folder, got it...

    but since I need it by folder, I've done the following::

    #set ($vlocation1 = ("_library/blocks/openhouse/videos"))
    
    #set($query = $_.query())
    #set($query = $query.byMetadataSet("Bootstrap Block Default"))
    #set($query = $query.includeBlocks(true).includeFiles(false).includeFolders(false).includeSymlinks(false).siteName($currentPageSiteName))
    #set($blocks = $query.maxResults(10).execute())
    #set($videoArr = [])
    #if ($blocks.size() > 0)
        #foreach ($block in $blocks)
        
            #set ($void = $videoArr.add({
                "id": $block.identifier.id,
                "name": $block.name,
                "date": $block.created-on,
                "path": $block.path,
                "title": $block.getStructuredDataNode("title").textValue,
                "description": $block.getStructuredDataNode("description").textValue,
                "thumbnail": $block.getStructuredDataNode("thumbnail").asset.link,
                "Block": $block
            }))
        #end
        
        #foreach ($video in $_SortTool.sort($videoArr, "name:asc"))
        #set ($vpath = $video.path)
        #if ($vpath.indexOf($vlocation1) > -1)
            $video.name 
            $video.path
            $video.description
            $video.title
            $video.thumbnail
            $video.date
        #end
        #end
     #end
    

    few things:

    I can't get the created date to come up

    only 2 blocks show when there are about 8 in the video subfolders (all blocks have the same metadata set) 1 video from each subfolder

    how would I sort by created date? newest and/or oldest

  14. 14 Posted by Ryan Griffith on 08 Feb, 2016 12:02 PM

    Ryan Griffith's Avatar

    Hi,

    Sounds like we're getting closer.

    One thing I would recommend is to move the parent folder check into the first foreach loop, this way you have less to sort for the second loop.

    I can't get the created date to come up

    Try using "date": $block.createdOn instead of "date": $block.created-on.

    only 2 blocks show when there are about 8 in the video subfolders (all blocks have the same metadata set) 1 video from each subfolder

    My fault, the snippet I provided was a little incorrect within that second loop. Note that you are using a map in the second loop, so accessing the properties from the first loop would be done using get("KEY"). For example, you get the path:

    #set ($vpath = $video.get("path"))
    

    how would I sort by created date? newest and/or oldest

    You would tweak the second sort parameter passed to the Sort Tool from "name:asc" to date:asc (or desc). Additionally, you can add multiple sort criteria by supplying an array of items. For example:

    $_SortTool.sort($videoArr, ["name:asc", "date:desc"])
    

    Please let me know if you have any questions.

    Thanks!

  15. 15 Posted by Nando on 08 Feb, 2016 02:03 PM

    Nando's Avatar

    closer and closer!

    this is what i have now

    #set($query = $_.query())
    #set($query = $query.byMetadataSet("Bootstrap Block Default"))
    #set($query = $query.includeBlocks(true).includeFiles(false).includeFolders(false).includeSymlinks(false).siteName($currentPageSiteName))
    #set($blocks = $query.maxResults(10).execute())
    #set($videoArr = [])
    ##
    #if ($blocks.size() > 0)
    ##
    #foreach ($block in $blocks)
    #set ($vpath = $block.path)
    ##$vpath
    #if ($vpath.indexOf($vlocation1) > -1)
    #set ($void = $videoArr.add({
    "id": $block.identifier.id,
    "name": $block.name,
    "date": $block.createdOn,
    "path": $block.path,
    "title": $block.getStructuredDataNode("title").textValue,
    "description": $block.getStructuredDataNode("description").textValue,
    "thumbnail": $block.getStructuredDataNode("thumbnail").asset.link,
    "Block": $block
    }))
    #end
    #end
    ##
    #foreach ($video in $_SortTool.sort($videoArr, "date:desc"))
    $video.name 
    $video.path
    $video.description
    $video.title
    $video.thumbnail
    $video.date
    #end
    ##
    #end
    

    I moved the parent folder check up as you suggested and that works fine...

    still only have 2 blocks showing, I'm not sure where I should use the get(xx) since everything is pulling already...

    Also, for the created date - is there anyway to modify the output?

    thanks again

  16. 16 Posted by Ryan Griffith on 08 Feb, 2016 04:33 PM

    Ryan Griffith's Avatar

    Hi,

    still only have 2 blocks showing, I'm not sure where I should use the get(xx) since everything is pulling already...

    Curious, what is the size of $blocks and what is the resulting size of $videoArr?

    For the get() usage, you would replace the following:

    $video.name 
    $video.path
    $video.description
    $video.title
    $video.thumbnail
    $video.date
    

    with:

    $video.get("name") 
    $video.get("path")
    $_EscapeTool.xml($video.get("path"))
    ...
    

    Also, for the created date - is there anyway to modify the output?

    You would use the Date Tool's format method to format the date. For example:

    $_DateTool.format("EEE, MMM d, ''yy", $video.get("date"))
    

    would result in something like Mon, Feb 8, '16. For more information about available formatting options, see this page.

    Please let me know if you have any questions.

    Thanks!

  17. 17 Posted by Nando on 08 Feb, 2016 05:22 PM

    Nando's Avatar

    hmmmm...

    $blocks.size() = 10 and $videoArr.size() = 2

  18. 18 Posted by Nando on 08 Feb, 2016 05:25 PM

    Nando's Avatar

    I see whats happening... the query is only showing 10 results before my parent folder check... can I can my parent folder check in the query?

  19. 19 Posted by Nando on 08 Feb, 2016 06:13 PM

    Nando's Avatar

    got it! I limit it by count on the video foreach...

    #set($query = $_.query())
    #set($query = $query.byMetadataSet("Bootstrap Block Default"))
    #set($query = $query.includeBlocks(true).includeFiles(false).includeFolders(false).includeSymlinks(false).siteName($currentPageSiteName))
    #set($blocks = $query.maxResults(1000).execute())
    #set($videoArr = [])
    ##
    #if ($blocks.size() > 0)
    $blocks.size()
    ##
    #foreach ($block in $blocks)
    #set ($vpath = $block.path)
    ##$vpath
    #if ($vpath.indexOf($vlocation1) > -1)
    #set ($void = $videoArr.add({
    
    "id": $block.identifier.id,
    "name": $block.name,
    "date": $block.createdOn,
    "path": $block.path,
    "title": $block.getStructuredDataNode("title").textValue,
    "description": $block.getStructuredDataNode("description").textValue,
    "thumbnail": $block.getStructuredDataNode("thumbnail").asset.link,
    "Block": $block
    }))
    #end
    #end
    ##
    $videoArr.size()
    
    #foreach ($video in $_SortTool.sort($videoArr, "date:desc"))
    #set ($vcount = $foreach.index) 
    #if($vcount < 3) 
    ------------
    $video.get("name") 
    $_EscapeTool.xml($video.get("path"))
    ##$video.description
    $video.get("title")
    $video.get("thumbnail")
    ##$video.date
    ##
    #end
    #end
    ##
    #end
    

    thoughts? issues with 1000 max results?

    thanks again!

  20. 20 Posted by Ryan Griffith on 08 Feb, 2016 06:18 PM

    Ryan Griffith's Avatar

    Ah, that makes sense.

    Another way to accomplish this would be to #break out of the loop when $videoArr.size() reaches 10 blocks:

    #foreach ($block in $blocks)
      #set ($vpath = $block.path)
      #if ($vpath.indexOf($vlocation1) > -1)
        #set ($void = $videoArr.add({
    
        "id": $block.identifier.id,
        "name": $block.name,
        "date": $block.createdOn,
        "path": $block.path,
        "title": $block.getStructuredDataNode("title").textValue,
        "description": $block.getStructuredDataNode("description").textValue,
        "thumbnail": $block.getStructuredDataNode("thumbnail").asset.link,
        "Block": $block
        }))
      #end
    
      #if (videoArr.size() > 10)
        #break
      #end
    #end
    

    Note: the query tool will trim results to 500 items, so that 1000 value won't do anything.

    I'm going to go ahead and close this discussion, please feel free to comment or reply to re-open if you have any additional questions.

    Have a great day!

  21. Ryan Griffith closed this discussion on 08 Feb, 2016 06:18 PM.

  22. Nando re-opened this discussion on 11 Feb, 2016 04:53 PM

  23. 21 Posted by Nando on 11 Feb, 2016 04:53 PM

    Nando's Avatar

    Sorry to reopen but I just wanted to mention that querying by folder would have been WAY easier and less load heavy so I suggested it :)

    http://ideas.hannonhill.com/forums/52559-cascade-cms-ideas/suggesti...

  24. 22 Posted by Ryan Griffith on 11 Feb, 2016 06:36 PM

    Ryan Griffith's Avatar

    Not a problem at all, thank you for contributing to our Idea Exchange!

    We actually have an existing suggestion that mentions filtering by folder as an option. To help keep things tidy, I am going to merge the two suggestions.

    Again, thank you for contributing.

    Have a great day!

  25. Ryan Griffith closed this discussion on 11 Feb, 2016 06:36 PM.

Discussions are closed to public comments.
If you need help with Cascade CMS please start a new discussion.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac

 

26 Aug, 2016 01:19 PM
25 Aug, 2016 03:02 PM
25 Aug, 2016 12:50 PM
24 Aug, 2016 08:43 PM
24 Aug, 2016 07:20 PM
21 Aug, 2016 01:20 PM