Not sure how this is going to come out, but here goes.. (If you want me to resend that document with the suggested changes I can, however you've pretty much implemented many of them now anyway!)
This was for an older release of DMX and the Editor so some of the DMX function calls I used may have been updated by now.
*************************************************************
Function to return nested list of Documents
Summary
We had a requirement to offer a list of existing website (DNN) pages in a dropdown list integrated into the Rich Text Editor we use (
http://www.cutesoft.net/A...BWYSIWYG%2BEditor/).The idea is that when selected from the dropdown list, a hyperlink to that page is added to the editor’s content, rather than users having to navigate to the page they wish, and then copy and paste the link. I was able to easily add this using built in methods of DNN which retrieve this ‘nested’ list quite easily (since they use this type of list predominantly in admin controls throughout DNN). I’m going to document this change here: (
http://www.trymy.net/Default.aspx?tabid=82)Anyway, we then believed it would be great to be offer a similar dropdown list containing a list of DMX documents, which when selected would provide a direct link to download that file.
To be able to provide an ordered nested list required sorting the list of documents into their collection, and additionally calculating its ‘depth’ level in order to graphically indent the entry.
Having to go back to my Uni days (yuk!), I worked out a Recursive function which performed this. I first did it in a stored proc in the DB as I felt this would aid performance, however this would then require associated provider and controller calls and I didn’t want to touch the core DMX code.
So I ended up doing it in a class and placing it in (CuteEditor’s) HTMLEditor provider file, so it didn’t impact on your code. The GetCollectionContents and GetEntries controller methods were sufficient retrieve the necessary information.
Basically, the initialise event of the HTMLEditor provider adds a toolbar to the editor and populates it with a list of DMX entries, along with their associated link to download the document. Obviously within the link you need to provide a tabid and moduleID of an existing DMX instance that gives permissions to all users, so I placed these variables in web.config for easy access.
(*** A problem then exists because that particular instance needs to point to the correct repository to download the document, otherwise a ‘file not found’ error will result, however this would be negated if the proposed changes are made to DMX ;=)) )
Code Summary
Anyway, a quick overview of the methods provided below:
Initialise (snippet)
• Declares an instance of an array to hold the final list of sorted documents (an array of DMXEntryTree structures)
• Calls function which populates the array
• Iterates through the array and adds graphical nesting, and adds URL link to download each entry
• Adds updated item to the editors dropdownlist.
DMXEntryTree Structure
• Holds the contents of each DMX entry to be added to the dropdown list
• Adds a ‘Depth’ property to each entry indicating the graphical indent that needs to be applied.
CheckDMXConfigSettings Function
• Runs a quick check to ensure that the moduleID and tabid variables are set. If not dropdown box is not added.
DMXRecursiveTree Sub
• Accepts a parameter holding the current Entry ID and recursively searches for its children.
• Increments and decrements the ‘depth’ variable as it travels down and up the tree.
• For each entry found in its children, it creates a DMXEntryTree structure and populates its contents, filtering out deleted, hidden or private entries.
Conclusion
The functions obviously need to be cleaned up and optimised, however they currently do the job and work without any alteration to the core. We currently have about 500 entries in our portal and there’s no noticeable delay in load times. A few issues that come to mind:
• Continually calling the GetEntries method is probably un-necessary as all objects in the collection have previously been retrieved through the GetCollectionContents call, although it needs to remain in scope to be accessed.
• The Recursive function could be overloaded to accept variables affecting filter options, such as Deleted, Hidden, GetCollectionsOnly etc.
• A permission check could be performed against each entry and not added if the user doesn’t have view permissions on the entry
These are all possibilities that could be used should you wish to extend its functionality. Feel free to use the code as part of future DMX releases.
One immediate use that comes to mind, would be to restrict the entries to returned to ‘Collections Only’ (by using an overload method as described above) which could then be used in existing dropdown lists in DMX, such as the ‘Move Entry’, and ‘Specify root Collection’ dropdown lists. These are currently cumbersome to use with larger lists, especially when collections have identical names!
Code Listing
Public Overrides Sub Initialize() - SNIPPET ONLY
.
.
Me._arrDMXEntryTree = New ArrayList
'Load items into ArrayList (_arrDMXEntryTree)
Me.DMXRecursiveTree(0, 0)
Dim objEntry As DMXEntryTree
Dim DMXRootTabID As Integer
Dim DMXRootModuleID As Integer
'Get module location of DMX Root with all user access
DMXRootTabID = Integer.Parse(System.Configuration.ConfigurationSettings.AppSettings("DMX_RTEProvider_RootTabID"))
DMXRootModuleID = Integer.Parse(System.Configuration.ConfigurationSettings.AppSettings("DMX_RTEProvider_RootModuleID"))
For Each objEntry In Me._arrDMXEntryTree
Dim sDisplay As String
Dim sPath As String
If LCase(objEntry.EntryType) = "collection" Then
sDisplay = "
" & objEntry.Description & ""
'Just display the linked entry for a collection
sPath = NavigateURL(DMXRootTabID, "", "DMXModule=" & DMXRootModuleID, "EntryID=" & objEntry.EntryID.ToString)
Else
sDisplay = objEntry.OriginalFileName
'Perform Download Command
sPath = NavigateURL(DMXRootTabID, "", "DMXModule=" & DMXRootModuleID, "EntryID=" & objEntry.EntryID.ToString, "Command=Core.Download")
End If
'Perform nesting
Dim strIndent As String = ""
For intCounter As Integer = 1 To objEntry.Depth
strIndent += "..."
Next
sDisplay = strIndent & sDisplay
dropdown.Items.Add(sDisplay, sdisplay, sPath)
Next
container.Controls.Add(dropdown)
.
End Sub
#Region "DMXDocLink Methods"
Private _arrDMXEntryTree As ArrayList
Private Structure DMXEntryTree
Friend EntryID As Integer
Friend EntryType As String
Friend Depth As Integer
Friend OriginalFileName As String
Friend Description As String
End Structure
Private Function CheckDMXConfigSettings() As Boolean
Dim bRet As Boolean = False
'Check TabID
If (Not System.Configuration.ConfigurationSettings.AppSettings("DMX_RTEProvider_RootTabID") Is Nothing) And _
(IsNumeric(System.Configuration.ConfigurationSettings.AppSettings("DMX_RTEProvider_RootTabID"))) Then
'Check ModID
If (Not System.Configuration.ConfigurationSettings.AppSettings("DMX_RTEProvider_RootModuleID") Is Nothing) And _
(IsNumeric(System.Configuration.ConfigurationSettings.AppSettings("DMX_RTEProvider_RootModuleID"))) Then
bRet = True
End If
End If
Return bRet
End Function
Private Sub DMXRecursiveTree(ByVal EntryID As Integer, ByVal Depth As Integer)
Dim CollectionID As Integer = EntryID
Dim objDMX As New DMX.business.EntriesController
'Retrieve all entries in this collection
Dim arr As ArrayList
Dim EntryInfo As DMX.Business.EntriesInfo
arr = objDMX.GetCollectionContents(False, EntryID, PortalSettings.PortalId, Nothing)
'Iterate through all entries in this collection, calling function for each child
For Each EntryInfo In arr
'Retrieve details of this entry
Dim objEntry As DMX.Business.EntriesInfo
objEntry = objDMX.GetEntries(EntryInfo.EntryId, PortalSettings.PortalId)
'Add this entry to the final list (if approved and not deleted)
If objEntry.IsApproved And (Not objEntry.IsPrivate) And (Not objEntry.Deleted) Then
Dim DET As New DMXEntryTree
DET.EntryID = objEntry.EntryId
DET.EntryType = objEntry.EntryType
DET.Depth = Depth
DET.OriginalFileName = objEntry.OriginalFileName
DET.Description = objEntry.Description
Me._arrDMXEntryTree.Add(DET)
End If
'Add one to depth before recursive call
Depth += 1
'Call function recursively
Call DMXRecursiveTree(EntryInfo.EntryId, Depth)
'Substract one from deptth after recursive call
Depth -= 1
Next
End Sub
#End Region