Skip to content
PDF

Working with Smart Pages

This guide introduces the basic functionalities related to the Module Suite Smart Pages.

Basic concepts

The Module Suite Smart Pages is an optional extension to Module Suite that introduces new features for those users that need an extra level of flexibility when creating customized SmartUI perspectives, and, more broadly, for those who prefer using the SmartUI in place of the Classic UI for their Content Server applications.

The extension includes the following components:

  • A new set of SmartUI tiles, available within the Perspective Builder Widget Library
  • A set of Content Script snippets that showcase how to create datasources for the SmartUI tiles
  • A collection of Beautiful WebForms templates and related resources that enable embedding of Beautiful WebForms views within a SmartUI perspective

Module Suite Tiles in the Widget Library

Widget Library

The following tiles are available in AnswerModules Module Suite section:

  • Content Script Result
  • Content Script Tile Chart
  • Content Script Tile Links
  • Content Script Tile Tree
  • Content Script Node Table
  • Content Script Tile News
  • Content Script Tile Tiles

Tile Configuration

Module Suite tiles share some common configuration options, while other options are specific to single tiles.

Common options include the configuration of the external frame (header, scrolling content, title, icon) and the configuration of the tile's Data Source. All Module Suite tiles require to specify a Content Script object that will be executed when the tile content is created. This script acts as a Data Source for the tile, and allows to make its content dynamic.

Through the configuration, it is also possible to pass additional parameters to the script. The parameter will be available to the developer within the params variable.

When configuring the tile's icon, two different approaches are possible:

  • specify a CSS style class to apply to the icon element. This should define the rules needed to apply the desired icon.
  • specify the name (and color scheme) of the desired icon among the ones available in the Module Suite icon set. See the icon reference cheat sheet for a full list of options.

Content Script Tile configuration

Tile: Content Script Result

The Content Script Result is a general-purpose tile that can be used to inject any output generated by a Content Script Data source into a SmartUI perspective.

Content Script Result

Tile: Content Script Tile Chart

The Content Script Tile Chart is a tile who's purpose is to create interactive charts within the SmartUI. The data shown in the charts will be provided by a Content Script data source.

Tile Chart

Chart tiles leverage two different javascript libraries:

  • Chartist (supported for backward compatibility)
  • Chart.js (suggested)

Depending on the selected chart type, the appropriate configuration has to be provided in JSON format. The following sample configuration produces the pie chart in the image above.

def rand = new Random()

if(params.widgetConfig){

    json(widgetConfig:[
        reloadCommands:["updateChart"],
        html:"""


<small>Move the mouse over the chart for triggering data-reload</small>
<script>
    csui.onReady2([ 
        "csui/lib/jquery", 
        "csui/lib/underscore", 
        "csui/lib/radio"], 
                  function(jQ, _, Radio){

                      //Get the page message bus
                      var amChannel  = Radio.channel('ampagenotify');

                      //Get the chart
                      var chart = amChannel.request("ampages:myChart");

                      var canvas = jQ("#myChart");
                      canvas.unbind("click");
                      canvas.on("click", function (evt) {
                        var activePoints = chart.getElementsAtEvent(evt);
                        var vals = _.map(_.pluck(_.filter(chart.legend.legendItems, function(it){ return it.hidden==false}), "text"), function(value){ return value;}).join("|");
                        if(!_.isUndefined(activePoints[0])){
                           var chartData = activePoints[0]['_chart'].config.data;
                           var idx = activePoints[0]['_index'];

                           var label = chartData.labels[idx];
                           var value = chartData.datasets[0].data[idx];     
                           amChannel.trigger("updateChart", [ {name:"where_type", value:label} ]);

                       } else {
                           amChannel.trigger("updateChart", [ {name:"where_type", value:vals} ]);
                       }
                      });


                      canvas.hover(function(){
                         var self = jQ(this);
                         //jQ(".myChartLoader").removeClass("binf-hidden");
                         amChannel.trigger("updateChart", [{name:"filter", value:"first"}]);
                      });
                  });
</script>"""
    ])
}else{

    json([

        type:"bar",
        data: 
        [

            labels: ["red", "green"],
            datasets: [

                [
                    label: "My First dataset",
                    backgroundColor: "${AMBWFWidgetsLib.getBehaviour("ambwf","generateRandomHTMLColor", this)(rand)}",
                    borderColor: "${AMBWFWidgetsLib.getBehaviour("ambwf","generateRandomHTMLColor", this)(rand)}",
                    data: [rand.nextInt(100), rand.nextInt(100)],

                ],
                [
                    label: "My Second dataset",
                    borderColor: "${AMBWFWidgetsLib.getBehaviour("ambwf","generateRandomHTMLColor", this)(rand)}",
                    backgroundColor: "${AMBWFWidgetsLib.getBehaviour("ambwf","generateRandomHTMLColor", this)(rand)}",
                    data: [ rand.nextInt(100), rand.nextInt(100)],

                ]
            ]
        ],
        options: [
            maintainAspectRatio: false,
            title: [
                display: true,
                text: 'myChart',
                position: 'left'
            ],
            legend: [
                display: true,
                position: 'top'
            ],
            scales: [
                yAxes: [
                    [
                        ticks: [
                            beginAtZero:true
                        ]
                    ]
                ]
            ]
        ]
    ])
}

Tile: Content Script Tile Tiles

The Content Script Tile Tiles is a tile meant to create a customizable list of clickable links and HTML Tiles. The data controlling the links is provided by the backing Content Script data source.

Tile Links

The following Content Script sample configuration produces the Links tile shown above.

if( params.widgetConfig ){

    json( widgetConfig : [
            reloadCommands : ["updateTiles"], // The widget will be refreshed when this command is executed
            html : """

<div style="padding:20px; background-color:white;margin-bottom:10px" >
Move the mouse over the tiles for triggering data-reload, or try to change the value of the first tile using the input box below.
<br/>
<input class="customField" name="customField" value="Open" type="text">
</div>

<script>
    csui.onReady2([ 
        "csui/lib/jquery", 
        "csui/lib/underscore", 
        "csui/lib/radio"], 
                  function(jQ, _, Radio){

                      // Get the page message bus

                      var amChannel  = Radio.channel('ampagenotify');

                      amChannel.on("smartPage_action", function(action,param){
                          console.log("GOT Page Action request. Action: "+action+ " parameter: "+param);
                      });

                      jQ(".am-tile-linkstiles-cell").hover(function(){
                         var self = jQ(this);
                         amChannel.trigger("updateTiles", [{name:"customValue", value:"Test"}]); //(1)
                      });

                      jQ(".customField").change(function(){
                         var self = jQ(this);
                         amChannel.trigger("updateTiles", [{name:"customValue", value:self.val()}]); //(1)
                      });
                  });
</script>"""
    ])
} else {

json(
    data : [
        styleclass : "myStyleClass",
        rows : [
            [   // First row
                styleclass : "myStyleClass",
                size : 0, // The relative height of this row compared to other rows (default : 1)
                tiles : [
                    [ // First Tile
                        size       : 1, // The relative size of this tile compared to others in the row (default : 1)
                        styleclass : "myStyleClass",

                        html : """<div style="height: 100%;
                                              text-align: center;
                                              font-weight: lighter;
                                              padding: 5px;
                                              font-size: 150%;
                                              color: #fff;
                                              background-color: #090e2c;"> Sample Tiles Widget </div>"""
                    ]
                ]
            ],
            [   // Second row
                styleclass : "myStyleClass",
                size : 1, // The relative height of this row compared to other rows (default : 1)
                tiles : [
                    [ // First Tile
                        //type       : 'red',
                        size       : 2, // The relative size of this tile compared to others in the row (default : 1)
                        styleclass : "myStyleClass",
                        action     : "navigate", // Will trigger a browse action of the current view
                        params     : "2000", // The DataID of the node you wanto to navigate to 

                        front : [
                            //style           : 'color:#b20000;background-color:#fff;',
                            icon : "${img}csui/themes/carbonfiber/image/icons/header-folder.svg", //Icons to be displayed in the tile
                            body : params.customValue ?: "Enterprise Workspace",
                            body_text_align : 'right', // left, center, right (default)
                            body_text_size : 'small' // small (90%), normal (100%), large (200%), jumbo (300%)

                        ],

                        back : [
                            icon  : "${img}csui/themes/carbonfiber/image/icons/circle_arrow_right.svg",
                            body  : "Open",
                        ]
                    ],
                    [ // Second Tile
                        //type       : 'red',
                        size       : 2, // The relative size of this tile compared to others in the row (default : 1)
                        styleclass : "myStyleClass",
                        action     : "navigate", // Will trigger a browse action of the current view
                        params     : docman.getPersonalWS().ID, // The DataID of the node you wanto to navigate to 

                        front : [
                            //style : 'color:#b20000;background-color:#fff;',
                            icon : "${img}csui/themes/carbonfiber/image/icons/header-folder.svg", //Icons to be displayed in the tile
                            body : "Personal Workspace",
                            body_text_align : 'right', // left, center, right (default)
                            body_text_size : 'small' // small (90%), normal (100%), large (200%), jumbo (300%)

                        ],

                        back : [
                            style : 'color:#b20000; background-color:#fff;', // Custom stiling for this card
                            icon  : "${img}csui/themes/carbonfiber/image/icons/circle_arrow_right.svg",
                            body  : "Open",
                        ]
                    ],
                    [ // Third Tile
                        type       : 'gold',
                        size       : 1, // The relative size of this tile compared to others in the row (default : 1)
                        styleclass : "myStyleClass",
                        action : "link", //Just a standard link
                        params : "http://www.answermodules.com", //The URL where to redirect the user
                        newtab : true, //True if the URL should be opened in a new browser tab
                        front : [
                            //style : 'color:#b20000;background-color:#fff;',
                            //icon : "${img}csui/themes/carbonfiber/image/icons/header-folder.svg", //Icons to be displayed in the tile
                            body : "AM Website",
                            body_text_align : 'center', // left, center, right (default)
                            body_text_size : 'small' // small (90%), normal (100%), large (200%), jumbo (300%)

                        ],

                        back : [
                            style : 'color:#b20000; background-color:#fff;', // Custom stiling for this card
                            icon  : "${img}csui/themes/carbonfiber/image/icons/circle_arrow_right.svg",
                            //body  : "Go",
                        ]
                    ]
                ]
            ],

            [
                tiles : [

                    [   size : 2,
                        newtab : true, //True if the URL should be opened in a new browser tab
                        type : 'orange', // Available types: red, green, blue, orange, teal, gold, purple
                        front : [
                            icon : "${img}anscontentsmartui/app/image/icons/windows10/white/task.svg",
                            body : """25 <span style="font-size:1rem;padding-left:5px;">open<br>tasks</span>""",
                            body_text_align : 'right', // left, center, right (default)
                            body_text_size : 'jumbo' // small (90%), normal (100%), large (200%), jumbo (300%)
                        ],
                        back : [
                            icon : "${img}anscontentsmartui/app/image/icons/windows10/white/task.svg",
                            title : "Open Tasks"
                        ]
                    ],
                    [
                        size : 1,
                        type : 'red',
                        html : """ <p style="padding:5px;background-color:#fff; color:#666; height:100%;"> Some custom <span style="color:red">html</span> with no actions</p>"""
                    ],
                ]
            ],


            [
                tiles : [

                    [   size : 2,
                        type : 'blue',
                        front : [
                            icon : "${img}anscontentsmartui/app/image/icons/windows10/white/stats_column_chart.svg",
                            body : '$ 670 K',
                            body_text_size : 'large' // small (90%), normal (100%), large (200%), jumbo (300%)
                        ],
                        back : [
                            icon : "${img}anscontentsmartui/app/image/icons/windows10/white/stats_column_chart.svg",
                            body : "Total sales last quarter",
                        ]

                    ],
                    [
                        size : 1,
                        command : "smartPage", //The SmartPage(s) to notify
                        action : "updatePage", //The action to execute
                        params : "2000",//The action's parameter
                        newtab : false,
                        type : 'green',
                        front : [
                            icon : "${img}anscontentsmartui/app/image/icons/windows10/white/stock_market.svg",
                            body : "Stock",
                            title : "No Back Card"
                        ]
                    ],
                ]
            ],


            [
                tiles : [

                    [   size : 2,
                        type : 'purple',
                        front : [
                            icon : "${img}anscontentsmartui/app/image/icons/windows10/white/profit.svg",
                            body : '+ 253%',
                            body_text_size : 'large' // small (90%), normal (100%), large (200%), jumbo (300%)
                        ],
                        back : [
                            icon : "${img}anscontentsmartui/app/image/icons/windows10/white/profit.svg",
                            body : "Total sales last quarter",
                        ]

                    ],
                    [
                        size : 1,
                        command : "smartPage", //The SmartPage(s) to notify
                        action : "updatePage", //The action to execute
                        params : "2000",//The action's parameter
                        newtab : false,
                        type : 'red',
                        front : [
                            icon : "${img}anscontentsmartui/app/image/icons/windows10/white/risk_assesment.svg",
                            body : "25",
                            body_text_size : 'large', // small (90%), normal (100%), large (200%), jumbo (300%)
                            title : "Incidents"
                        ],
                        back : [
                            icon : "${img}anscontentsmartui/app/image/icons/windows10/white/risk_assesment.svg",
                            body : "Delete",
                            title : "More Actions"
                        ]
                    ],
                ]
            ]
        ]
    ]
)
}

The Content Script Tile Links is a tile meant to create a customizable list of clickable links. The data controlling the links is provided by the backing Content Script data source.

Tile Links

The following Content Script sample configuration produces the Links tile shown above.

if(params.widgetConfig){

    json(widgetConfig:[
        reloadCommands:["updateLinks"],
        html:"""

<style>
div.ans-tile-content-linkstiles{
    background: linear-gradient(180deg, #122c69 0%, #078db3 100% );
    color:#fff;
    height:100%;
}

div.ans-tile-content-linkstiles > div.binf-list-group > a:nth-child(2),
div.ans-tile-content-linkstiles > div.binf-list-group > a:nth-child(6),
div.ans-tile-content-linkstiles > div.binf-list-group > a:nth-child(10){
    background:#00639b;
    color:#fff;
    border-radius:0px;
}
div.ans-tile-content-linkstiles > div.binf-list-group > a:nth-child(3),
div.ans-tile-content-linkstiles > div.binf-list-group > a:nth-child(7),
div.ans-tile-content-linkstiles > div.binf-list-group > a:nth-child(11){
    background:#df3324;
    color:#fff;
    border-radius:0px;
}
div.ans-tile-content-linkstiles > div.binf-list-group > a:nth-child(4),
div.ans-tile-content-linkstiles > div.binf-list-group > a:nth-child(8),
div.ans-tile-content-linkstiles > div.binf-list-group > a:nth-child(12){
    background:#008485;
    color:#fff;
    border-radius:0px;
}

</style>
<div style="padding:20px; background-color:white;margin-bottom:10px;color:#333" >
Click on the differnt links to see them in action.
</div>
<script>
    csui.onReady2([    'csui/lib/underscore',
        'csui/lib/backbone',
        'csui/lib/jquery',
        'csui/lib/radio'], 
        function(_,Backbone, jQ, Radio){
            var amChannel = Radio.channel("ampagenotify");
            amChannel.on("smartPage_action", function(action,param){
                console.log("GOT Page Action request. Action: "+action+ " parameter: "+param);
            });

        });
</script>
"""
    ])
}else{

    retVal = 
        [
            data:[
                links:[
                    [
                        issection:true,
                        name:"First Section",
                    ],
                    [
                        issection:false,
                        icon:"csui-icon-home",
                        name:"First Link (Navigate)",
                        desc:"More information for this link",

                        url:"#", //If action != null url must be set equal to #
                        action:"navigate", //Will trigger a browse action of the current view
                        params:"2000", //The DataID of the node you wanto to navigate to 

                    ],
                    [
                        issection:false,
                        icon:"icon-tileExpand icon-perspective-open",
                        name:"Duplicate (Action)",

                        url:"#", //If action != null url must be set equal to #
                        action:"notify", //Will trigger the execution of the command below
                        command:"updateLinks", //The action to execute
                        params:"duplicate", //The action's parameter, this value will be passed to the script in a parameter named "tile"

                    ],
                    [
                        issection:false,
                        icon:"icon-socialFavOpen",
                        name:"Notify Smart Page (Page Action)",

                        url:"#", //If action != null url must be set equal to #
                        command:"smartPage", //The SmartPage(s) to notify
                        action:"updatePage",   //The action to execute
                        params:"2000" //The action's parameter

                    ],
                    [
                        issection:false,
                        am_icon:"am_icon_link",
                        am_icon_schema:"am_icon_green",
                        name:"Simple link",

                        url:"http://www.answermodules.com",
                        newtab:true

                    ]

                ]
            ]
        ]

    if(params.tile == "duplicate"){
        retVal.data.links += retVal.data.links[-5].clone()
        retVal.data.links += retVal.data.links[-5]
        retVal.data.links += retVal.data.links[-5]
        retVal.data.links += retVal.data.links[-5]

        retVal.data.links[-4].name = "Second Section"
    }else if(params.tile == "triple"){
        retVal.data.links += retVal.data.links[-5].clone()
        retVal.data.links += retVal.data.links[-5]
        retVal.data.links += retVal.data.links[-5]
        retVal.data.links += retVal.data.links[-5]

        retVal.data.links[-4].name = "Second Section"

        retVal.data.links += retVal.data.links[-4].clone()
        retVal.data.links += retVal.data.links[-4]
        retVal.data.links += retVal.data.links[-4]
        retVal.data.links += retVal.data.links[-4]

        retVal.data.links[-4].name = "Third Section"
    }

    json(
        retVal
    )


}

Tile: Content Script Tile Tree

The Content Script Tile Tree creates an interactive tree structure with nodes that can be expanded and collapsed. The tree structure uses a Content Script data source for the initial data and for subsequent ajax data load calls.

Tile Tree

The following sample configuration generates the tree in the image above.

if(params.widgetConfig){
    json( [ id           : 2,
           widgetConfig : [
               tileLayoutClasses  : "", 
               tileContentClasses : "", 
               reloadCommands     : ["updateTree"],
               root               : 2000, 
               plugins            : [ "wholerow" ],
               theme              : [ 'name': 'proton',
                                     'responsive': true ],
               html               : """
<style>
div.ans-tile-tree{
  background: linear-gradient(180deg, #122c69 0%, #078db3 100% );
  color:#fff;
  height:calc(100vh - 222px);
  font-size:13px !important;
}
.binf-widgets .jstree-proton .jstree-icon.csui-icon-node-task {
  background-image:url('${img}csui/themes/carbonfiber/image/icons/mime_task.svg')
}
.binf-widgets .jstree-proton .jstree-icon.mime_pdf{
  background-image:url('${img}csui/themes/carbonfiber/image/icons/mime_pdf.svg')
}
.jstree-anchor small{
  font-size:.9em;
  font-style:italic;
}
</style>
<div class="am-form-text-input" style="margin-top: 1px;padding: 5px 0px;">
    <label class=" control-label col-form-label am-form-text-input-label   am-form-label-top" style="padding: 5px;">Filter tree</label>
    <div class="am-form-input-wrap" style="padding: 0 5px;">
        <input id="filter" type="text" placeholder="" class="form-control" style="border-radius: 0px;box-shadow: none;">
    </div>
</div>

<script>
    csui.onReady2([    'csui/lib/underscore',
        'csui/lib/backbone',
        'csui/lib/jquery',
        'csui/lib/radio'], 
        function(_,Backbone, jQ, Radio){
            var amChannel = Radio.channel("ampagenotify");
            amChannel.on("printConsole", function(params){
                console.log("GOT request "+JSON.stringify(params));
            });
            amChannel.on("smartPage_action", function(action,param){
                console.log("GOT Page Action request. Action: "+action+ " parameter: "+param);
            });
            jQ("#filter").on("blur", function(){
                amChannel.trigger("updateTree",{'term':jQ(this).val()})
            })  

        });
</script>"""
           ]
          ] )
    return
}

data =

    [
        [

            icon     : "csui-icon cs_vfolder", //mime_folder, cs_folder_root, cs_vfolder, cs_folder_open...
            id       : 1,
            text     : "Roots",
            children :  [
                [
                    action   : "navigate", //Trigger a Smart View navigation
                    icon     : "csui-icon cs_folder_root", //cs_folder_root, cs_vfolder, cs_folder_open
                    id       : 2000, //The node will be used as the action's parameter
                    text     : "Home",
                    children : false
                ]

            ],
            state       : [
                opened    : true
            ] 
        ],
        [

            action   : "printConsole", //Trigger a Tile action
            params   : "3", //This value will be passed to the script in a parameter named 'tile'
            icon     : "csui-icon mime_folder",
            id       : 3,
            text     : "Folder (Lazy Loaded)",
            children : true,
            state       : [
                opened    : false
            ] 
        ]
    ]


if(params.uiParentID == "3"){
    data[1].children = [
        [

            icon     : "csui-icon mime_folder",
            id       : 4,
            text     : "Sub Folder",
            children : [
                [
                    notify   : "smartPage",    //Triggers a Smart Page action noifying the provided page(s) (CSV)
                    action   : "customAction", //The action to execute
                    params   : "2000",         //The action's parameter
                    icon     : "csui-icon mime_pdf",
                    id       : 5,
                    text     : "Notify Smart Page",
                    children : false
                ],
                [
                    action   : "printConsole",
                    params   : "2000",
                    icon     : "csui-icon mime_pdf",
                    id       : 6,
                    text     : "Execute Action",
                    children : false
                ]

            ]
        ]

    ]
}
if(params.term){
    data = data.findAll{it.text.startsWith(params.term)}
}
json(data)

Tile: Content Script Node Table

The Content Script Node Table is an enhancement of the standard Node Table tile. The tile uses a Content Script as data source, allowing to set up any custom business logic to generate the list of nodes to be shown.

Tile Node Table

def targetSpaceFilter = 2000

def subtypeFilter = 144

def paging = [actual_count:0, 
              limit:((params.limit?:"30") as int), 
              page:((params.page?:"1") as int), 
              page_total:0, 
              range_max:0, 
              range_min:0, 
              total_count:0, 
              total_row_count:0, 
              total_source_count:0]

def pageSize = paging.limit
def offset = (paging.limit * (paging.page - 1))
def firstRow = offset + 1
def lastRow = firstRow + paging.limit

nodes = []

def nameFilter = null
if( params.where_name ){
    nameFilter = "%${params.where_name}%"
}

def ownerFilter = null
if( params.where_owner ){a
    ownerFilter = "%${params.where_owner}%"
}

def sortingOrderParam     = 'desc'
def sortingColumnParam     = 'name'

def sortingOrder     = 'DESC'
def sortingColumn     = 'DTree.Name'


if( params.sort && params.sort.contains('_') ){

    def sorting = params.sort.split('_')

    sortingOrderParam     = sorting[0]
    sortingColumnParam     = sorting[1]

    sortingOrder = ( sortingOrderParam == 'asc' ) ? 'ASC' : 'DESC'


    switch( sortingColumnParam?.trim() ){

        case 'name' :
        sortingColumn = 'DTree.Name'
        break

        case 'owner' :
        sortingColumn = 'KUAF.ID'
        break

        default :
        sortingColumn = 'DTree.Name'
        break
    }

}


try{


    def queryParams = [targetSpaceFilter as String]
    def queryIndex = 1

    def permExpr = "(exists (select DataID from DTreeACL aclT where aclT.DataID=DTree.DataID and ${users.getRightsStringForSQL("RightID", false)} and See >1 ))"


    sqlCode = """ select DTree.DataID DID, 
                         DTree.Name NAME, 
                         overall_count = COUNT(*) OVER()

                    from DTree 
                    LEFT JOIN KUAF ON DTree.UserID = KUAF.ID

                    where DTree.ParentID = %1 """

    if(subtypeFilter){
        sqlCode += " and DTree.SubType LIKE %${++queryIndex} "
        queryParams << (subtypeFilter as String)
    }

    if(nameFilter){
        sqlCode += " and DTree.Name LIKE %${++queryIndex} "
        queryParams << (nameFilter as String)
    }

    if(ownerFilter){
        sqlCode += " and (KUAF.Name LIKE %${++queryIndex} OR KUAF.LastName LIKE %${queryIndex} ) "
        queryParams << (ownerFilter as String)
    }

    if(!users.current.canAdministerSystem){
        sqlCode += " and ${permExpr} "
    }

    sqlCode += """
                   ORDER BY ${sortingColumn} ${sortingOrder}
                    OFFSET ${offset} ROWS
                    FETCH NEXT ${pageSize} ROWS ONLY

                """



    def queryResults

    if(queryParams){
        queryResults =  sql.runSQL(sqlCode, true, true, 100, *queryParams).rows
    } else {
        queryResults =  sql.runSQL(sqlCode, true, true, 100 ).rows
    }   

    def totalCount = (queryResults) ? queryResults[0].overall_count : 0

    nodes = queryResults?.collect{it.DID as Long}



    paging << [
        actual_count:totalCount, 
        page_total:((totalCount%paging.limit)+1),
        range_min:paging.page*paging.limit-paging.limit+1,
        range_max:(paging.limit*(paging.page+1)-totalCount)>0?(paging.limit*(paging.page+1)-totalCount):paging.limit*(paging.page+1),
        total_count:totalCount, 
        total_row_count:totalCount, 
        total_source_count:totalCount]

}catch(e){
    log.error("Error loading nodes table data",e)
    printError(e)
}



def drawStatusBar = { node ->

    def statusList = ['Draft', 'Under Revision', 'Approved', 'Published']
    def numSteps = statusList.size()
    def currStep = new Random().nextInt(statusList.size())
    def currStepName = statusList[currStep]


    def stepStyle = "height:100%; width:calc(100% / ${numSteps}); float:left; background-color:#F0AD4E; box-sizing:border-box;"

    def stepsHtml = ""

    (currStep + 1).times{
        stepsHtml += """<span style="${stepStyle}"></span>"""
    }


    return """ 
    <div style="text-align:center; font-size:.75em">${currStepName}</div>
    <div style="margin:3px 0; padding:0; height:5px; background-color:#eee;">${stepsHtml}</div>"""
}



def slurper = new JsonSlurper()

def processNode = { node->

    /* Add your custom node post-processing here */

    def myNode = asCSNode(node?.data.properties.id as long)

    def owner = myNode.createdBy
    def ownerBox = "<span><img src='/otcs/cs.exe/pulse/photos/userphoto/${owner.ID}/2000' style='max-height: 3em; border-radius: 50%; margin-right: 5px; vertical-align: middle;' /> ${owner.displayName}</span>"
    node.data.properties.owner = ownerBox

    node.data.properties.comment = myNode.comment 
    node.data.properties.statusBar = drawStatusBar( myNode ) 

    return node
}

results = []

if( nodes.size() > 1 ){

    temp = slurper.parseText( docman.getNodesRestV2JSon(nodes, null, '{"properties":{"fields":["parent_id"]}}', true, true, []) )

    nodes.each{ node ->

        def jsonNode = temp.find{ it.data.properties.id == node }
        results << processNode(jsonNode)
    }


} else if (nodes.size() == 1 ){

    it = slurper.parseText(docman.getNodesRestV2JSon(nodes, null, '{"properties":{"fields":["parent_id"]}}', true, true, []))

    processNode(it)

    results = [it]
}




def columns = [

    type: [
        key:"type",
        name:"Type",
        type:2,
        type_name:"Integer",
        sort:false
    ]

    ,name: [
        key:"name",
        name:"Name",
        type:-1,
        type_name:"String",
        sort:true,
        align:"left"
    ]

    ,owner: [
        key:"owner",
        name:"Owner",
        type:43200,
        type_name:"String",
        sort:true,
        align:"left"
    ]

    ,statusBar: [
        key:"statusBar",
        name:"Doc. Status",
        type:43200,
        type_name:"String",
        sort:false,
        align:"left"
    ]

    ,comment: [
        key:"comment",
        name:"Comment",
        type:-1,
        type_name:"String",
        sort:false,
        align:"left"
    ]
]

json([paging:paging,
      columnsWithSearch:[ "name" , "owner" ], 
      results:results, 
      columns:columns, 
      tableColumns:columns,
      widgetConfig:[
          reloadCommands:[ "updateData" ]
      ]
     ])

Embedding Beautiful WebForms views in SmartUI

In order to embed a Beautiful WebForms form in a SmartUI tile, it is possible to use a Content Script Result Tile with the following minimal configuration:

def formID = 123456 // the dataID of the form to embed
def viewID = 234567 // the dataID of the SmartUI form view, within the Form Template

form = forms.getFormInfo(formID)
view = asCSNode(viewID)

json([ output : view.renderView(binding, form),     
       widgetConfig :[ 
           reloadCommands:[], // any SmartUI commands that will trigger a reload of the form
           tileContentClasses:"am-nobckg",
           tileLayoutClasses:"am-nobckg"
       ]
     ])   

Form View Template

In order for the form to load resources compatible with usage within the SmartUI, you should use the "SmartView Embeddable" form template, available within the SmartUI extension libraries.

For additional details, see the dedicated section in the Beautiful WebForms documentation.

Icon reference cheat sheet

Iconset Color codes

Module Suite icons are available in the following colors:

Icons colors

All icons

A complete list of the currently available icons is shown below: Icons reference