Visual Report Writer and The Web (I)¶
At the recently concluded Synergy 2013 conference held in Nashville, Tennessee, we demonstrated how easy it is to create Web-Based Applications using the DataFlex Web Application Framework. Reporting is a crucial part of a Web Application, and Data Access recommends two reporting solutions: Dynamic AI and Visual Report Writer. During the Synergy sessions (symposium and training), we showcased how relatively easy it is to integrate these two reporting solutions into a Web Application built with the DataFlex Web Application Framework. To illustrate this, we created two demonstration websites that showcase the capabilities of Dynamic AI and Visual Report Writer in real-time. You can experience the speed and output solutions, and in this blog and the following ones, I will explain what is behind the website and how it is constructed.
Before continuing with this blog, I recommend visiting the demonstration websites. You can explore the Dynamic AI demo website to experience its power. Additionally, you can access the Visual Report Writer websites hosted on either a USA-based server or a European-based server.
The Start Page¶
The links provided above lead to a start page named "The Solution." Accessing this page is controlled by setting the phoDefaultView property to this cWebView object. This page is a cWebView class-based component containing two cWebPanel objects. The left panel has a fixed width and can be resized by the visitor using the splitter between the two panels. The splitter is enabled by setting the pbResizable property of the left panel to true. The right panel does not have a fixed width; its size is determined by the browser size. The left panel contains a treeview control (cWebTreeView) for navigation purposes. The contents are read from a DataFlex embedded database table, allowing us to modify the contents without recompiling the application. The first level of the tree is automatically expanded. Clicking on a node sends a find request to the server, resulting in the documentation text being displayed in the right panel, which contains a cWebHTMLBox control. The text is stored as HTML in a TEXT-based column in the documentation table and includes special instructions that allow the server to open an integration web view when the user clicks on a link.
While the Dynamic AI and Visual Report Writer demo websites are similar, they are not identical, as they represent two different reporting solutions. The next part of this blog and the subsequent blogs will focus on what you see on the Visual Report Writer live demo website.
Now, let's examine some code used to populate the page.
In the OnLoad event of the cWebTreeView control, the data is loaded automatically, and the event sends a message OnLoadChildNodes to retrieve its data. In the treeview coded here, the data is read from a table named Documentation. The code for this is:
Function OnLoadChildNodes String sId String sValue Integer iLevel Returns tWebTreeItem[]
tWebTreeItem[] TreeItems
Get CollectTreeData sId to TreeItems
Function_Return TreeItems
End_Function
Function AppendTreeData tWebTreeItem[] ByRef DestinationTreeItems tWebTreeItem[] ByRef SourceTreeItems Returns Integer
Integer iElements iElement iDestinationElement
Move (SizeOfArray (DestinationTreeItems)) to iDestinationElement
Move (SizeOfArray (SourceTreeItems)) to iElements
For iElement from 0 to (iElements - 1)
Move SourceTreeItems[iElement] to DestinationTreeItems[iDestinationElement]
Increment iDestinationElement
Loop
Function_Return iElements
End_Function
Function CollectTreeData String sId Returns tWebTreeItem[]
tWebTreeItem[] TreeItems ChildTreeItems
Integer iElement iAddedItems iSet
RowID riDocumentation
Move (sId + 1) to iSet
Constraint_Set iSet Clear
Constrain Documentation.ParentID eq sId
Constrained_Find First Documentation by 1
While (Found)
Move Documentation.ID to TreeItems[iElement].sId
Move Documentation.ParentID to TreeItems[iElement].sParentId
Move (Trim (Documentation.Name)) to TreeItems[iElement].sName
Move Documentation.LoadChildren to TreeItems[iElement].bLoadChildren
Move Documentation.Folder to TreeItems[iElement].bFolder
Move Documentation.Expanded to TreeItems[iElement].bExpanded
Move Documentation.Icon to TreeItems[iElement].sIcon
Move (Trim (Documentation.CSSClass)) to TreeItems[iElement].sCSSClass
Move (Trim (Documentation.AltText)) to TreeItems[iElement].sAltText
Increment iElement
If (Documentation.Expanded) Begin
Move (GetRowID (Documentation.File_Number)) to riDocumentation
Get CollectTreeData Documentation.ID to ChildTreeItems
Get AppendTreeData (&TreeItems) (&ChildTreeItems) to iAddedItems
Move (iElement + iAddedItems) to iElement
Move (FindByRowID (Documentation.File_Number, riDocumentation)) to Found
End
Constraint_Set iSet
Constrained_Find Next
Loop
Constraint_Set iSet Delete
Function_Return TreeItems
End_Function
The OnLoadChildNodes event sends a message to read the data from the table. If none of the rows has the Expanded column set to true, the routine will only load the data at the first level, requiring the user to expand each tree item.
To ensure the first item is selected, the OnLoad event is enhanced to select the item corresponding to the first row in the table.
Procedure OnLoad
Forward Send OnLoad
Clear Documentation
Find Gt Documentation by 1
Send Select Documentation.ID
End_Procedure
The table layout is simple yet complex, as it uses a self-referential relationship through an ALIAS table and allows NULL parent support. The table structure is:
NUM FIELD NAME TYPE SIZE OFFST IX
--- --------------- ---- ----- ----- --
1 ID NUM 4.0 1 1
2 ParentID NUM 4.0 3
3 Name ASC 255 5
4 LoadChildren NUM 2.0 260
5 Folder NUM 2.0 261
6 Icon ASC 255 262
7 CSSClass ASC 100 517
8 AltText ASC 150 617
9 Value TEX 14752 767
10 Expanded NUM 2.0 15519
11 ViewName ASC 250 15520 2
The column ParentID links to the ALIAS table for Documentation from within the DataDictionary object used when entering or altering the documentation. As noted, the DataDictionary object is not utilized for reading data into the treeview. While it could have been used, there is no necessity for it. The DataDictionary class used for DDOs when entering documentation is as follows:
Use DataDict.pkg
Open Documentation
Open DocumentationParent
Register_Object oDocumentationWebLookup
Class cDocumentationDataDictionary is a DataDictionary
Procedure Construct_Object
Forward Send Construct_Object
Set Main_File to Documentation.File_Number
Set Add_Server_File to DocumentationParent.File_Number
Set ParentNullAllowed DocumentationParent.File_Number to True
Set Foreign_Field_Option DD_KEYFIELD DD_NOPUT to True
Set Foreign_Field_Option DD_KEYFIELD DD_FINDREQ to True
Set Foreign_Field_Option DD_INDEXFIELD DD_NOPUT to True
Set Foreign_Field_Option DD_DEFAULT DD_DISPLAYONLY to True
Set Field_WebPrompt_Object Field Documentation.ID to oDocumentationWebLookup
Set Field_Option Field Documentation.ID DD_AUTOFIND to True
Set Field_Class_Name Field Documentation.LoadChildren to "Checkbox"
Set Field_Class_Name Field Documentation.Folder to "Checkbox"
Set pbUseDDRelates to True
Set Field_Related_FileField Field Documentation.ParentID to File_Field DocumentationParent.ID
End_Procedure
End_Class
#IFDEF Is$WebApp
Use Lookups\DocumentationWebLookup.wo
#ELSE
#ENDIF
Clicking a node in the treeview sends the OnSelect event to the server. In the OnSelect, the row linked to the tree item is found, and its documentation data is sent to the cWebHtmlBox control via an UpdateHtml message.
Procedure OnSelect String sId String sValue Integer iLevel
Forward Send OnSelect sId sValue iLevel
Clear Documentation
Move sId to Documentation.ID
Find Eq Documentation.ID
Move (Trim (Documentation.Value)) to sValue
If (sValue = "") Begin
Move " " to sValue
End
Send UpdateHtml of oWebDocumentationBox sValue
End_Procedure
The right panel contains a cWebHTMLBox object used to display the contents.
Object oExplanationPanel is a cWebPanel
Object oWebDocumentationBox is a cWebHtmlBox
Set psHtmlId to "SolutionText"
Set pbServerOnClick to True
Set pbFillHeight to True
Procedure OnClick String sId String sParam
Handle hoView
Case Begin
Case (sId = "openview")
Get WebObjectByName sParam to hoView
Send Show of hoView
Case Break
Case (sId = "navigate")
Send NavigateToPage of oWebApp sParam btNewTab
Case Break
Case End
End_Procedure
End_Object
End_Object
Notably, in the oWebDocumentationBox object, the psHtmlId setting and the OnClick event implementation are significant. The psHtmlId is set to allow web designers to style the content of the HTML text stored in the Documentation table. The OnClick event is triggered when the user clicks an anchor element in the HTML text that contains a data-serveronclick attribute. Refer to the documentation for this setting within the DataFlex Web Application Framework documentation.
Finally, this solution page includes two buttons below the treeview that direct the user to the websites for Visual Report Writer and Visual DataFlex.