New Permissions Explorer in smartUI

Have you seen the new permissions explorer in smartUI? Open up the permissions on an object and you’ll see the new selection.

Permission Selection
Permission Selection
The Permissions Explorer
The Permissions Explorer

The permissions explorer is opened with a click on the “Permissions Explorer” Button on the upper right.

Inside the Permissions Explorer
Inside the Permissions Explorer

This will give you the option to edit all permissions of the objects in this folder at once.

Improved smartUI Webreport Usability

The usability of Webreports in smartUI has been improved. Now, you can, after starting a Webreport, edit the parameters of that report and receive feedbacks from the running Webreport. This makes a lot of fun!

Lets see, how this is done.

First a table.report widget can be used to list all data.

Click on a Webreport to start it

Then a Parameter Window opens. The Webreport can be startet by pressing the button “Run Webreport”

Webreport Parameters can be edited
Webreport Parameters can be edited

A feedback can be given from the Webreport like this

Running webreports can give Feedbacks to SmartUI
Running webreports can give Feedbacks to SmartUI

The table.report shows a Smart UI table based on the output of WebReports data. The WebReport used by this widget must be based on either the widget_table_report_process_data_in_webreport or widget_table_report_process_data_in_datasource default reportviews which use the INSERTJSON @TABLEREPORT directive.

   // Create the data managing context
      var context = new PageContext(),
      sampleTableReportView = new TableReportView({
          context: context,
          data: {
            id: 24024,
            sortBy: "SubType",
            SortOrder: "ASC",
            columnsWithSearch: "SubType",
            titleBarIcon: 'mime_audio',
            title: 'Sample WebReports Table',
            header: true,
            swrLaunchCell: {
                id: 12345,
                iconClass: 'my-icon-class',
                hoverText: 'Some hover text for my icon.'
            },
 parameters: [
                {
                    name: 'myparm1',
                    value: 'val1'
                },
                {
                    name: 'myparm2',
                    value: 'val2'
                }
            ]
          }
      }),
      // Create helpers to show the views on the page
      region = new Marionette.Region({
        el: "#content"
      });

      // Show the views on the page
      region.show(sampleTableReportView);

      // Fetch the WebReport output from the server to populate the tile with
      context.fetch();

The parameter window can be implemented like this (the xxxxxx is the node number for the webreport)

  var promptView,
        promptModel,
        contentRegion = new Marionette.Region({el: "#content"}),
        pageContext = new PageContext(),
        currentNode = pageContext.getModel(NodeModelFactory, {attributes: {id: xxxxxx}}),
        runWRModel = pageContext.getModel(PromptModelFactory, {
            attributes: {
                node: currentNode
            }
        }),
        runWRController = new RunWRController();
pageContext.fetch()
            .done(function () {

                // We've got the page context, now get the runWRModel to see if there are parameters:
                runWRController.getRunWRPreModel({
                    node: currentNode,
                    context: pageContext
                }).done( function(){

                    // Build the prompt view and show it:
                    promptView = new PromptView({
                        context: pageContext,
                        model: currentNode,
                        promptModel: runWRController.runWRPreModel,
                        showBackIcon: false
                    });

                    contentRegion.show(promptView);
                });
            })

A feedback is implemented by the status.screen control.

  require(['csui/lib/underscore', 'csui/lib/marionette', 'csui/utils/contexts/page/page.context',  'csui/utils/contexts/factories/connector',
  'csui/controls/globalmessage/globalmessage',
  'webreports/controls/status.screen/status.screen.view',
  'webreports/models/run.webreport.pre/run.webreport.pre.model',
  'webreports/models/run.webreport/run.webreport.model',
  './status.screen.mock.js'
  ], function (_, Marionette, PageContext, ConnectorFactory, GlobalMessage, StatusScreenView, WebReportRunModelPre, WebReportRunModel, WRMock) {

  var statusView,
  context = new PageContext(),
  connector = context.getObject(ConnectorFactory),
  region = new Marionette.Region({el: "#webreport-status-screen-demo"}),
  attributes = { id: xxxxxx },
  options = { connector: connector },
  WRRunPreModel = new WebReportRunModelPre(attributes, options),
  WRRunModel = new WebReportRunModel(attributes, options);
  WRMock.enable(); // Mockup for local tests
WRRunPreModel
  .fetch()
  .done( function(){

WRRunModel
  .fetch()
  .done( function(){
statusView = new StatusScreenView({
  destinationModel: WRRunPreModel.destinationModel,
  executeModel: WRRunModel});
  region.show(statusView);
  })
  })

});

Working with WebReports and SmartUI now makes a lot of fun!

New RulesMatchingMixin in smartUI

Have you seen the new Rules matching Mixin in the smartUI? Its a great mixin, allowing you to implement a colloection of rule models which are supposed one model, which rules match the input object. This is a quite powerful functionality

The following example implements the selection collection

  • Container = true
  • Subtype = 144, 749
  • and is type = 144 is one of the mimetypes listed
  • and is type = 144 or mimetype startswith “image/” of equals “pdf/x-pdf”
  • and is type = 144 and mimetype = “text/plain”

If run, then the action of the appripriate node is returned. Only on the base of a rules Model!!

Can be implemented like this

  var NodeActionSelectingModel = Backbone.Model.extend({
  idAttribute: 'signature',
  defaults: {
    sequence: 100,
    signature: null
  },
  constructor: function NodeActionSelectingModel(attributes, options) {
    Backbone.Model.prototype.constructor.apply(this, arguments);
    this.makeRulesMatching(options);
  },
  enabled: function (node) {
    return this.matchRules(node, this.attributes);
  }
});

RulesMatchingMixin.mixin(NodeActionSelectingModel.prototype);
var NodeActionSelectingCollection = Backbone.Collection.extend({
  model: NodeActionSelectingModel,
  comparator: 'sequence',
  constructor: function NodeActionSelectingCollection(models, options) {
    Backbone.Collection.prototype.constructor.apply(this, arguments);
  },
  findByNode: function (node) {
    return this.find(function (model) {
      return model.enabled(node);
    });
  }
});
var nodeActions = new NodeActionSelectingCollection([
  {
    equals: {
      container: true
    },
    signature: 'Browse'
  },
  {
    equals: {
      type: [144, 749]
    },
    signature: 'Open'
  },
  {
    and: [
      equals: {
        type: 144
      },
containsNoCase: {
        mime_type: [
          "application/msword",
          "application/vnd.ms-word",
          "application/vnd.msword",
          "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
          "application/vnd.wordprocessing-openxml",
          "application/vnd.ces-quickword",
          "application/vnd.ms-word.document.macroEnabled.12",
          "application/vnd.ms-word.document.12",
          "application/mspowerpoint",
          "application/vnd.ms-powerpoint",
          "application/vnd.openxmlformats-officedocument.presentationml.presentation",
          "application/vnd.ces-quickpoint",
          "application/vnd.presentation-openxml",
          "application/vnd.presentation-openxmlm",
          "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
          "application/msexcel",
          "application/vnd.ms-excel",
          "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
          "application/vnd.ces-quicksheet",
          "application/vnd.spreadsheet-openxml",
          "application/vnd.ms-excel.sheet.macroEnabled.12",
        ]
      }
    },
    signature: 'Edit',
    sequence: 50
  },
{
    and: {
      equals: {
        type: 144
      },
      or: {
        startsWithNoCase: {
          mime_type: 'image/'
        },
        equalsNoCase: {
          mime_type: ['application/pdf', 'application/x-pdf']
        }       }     },
    signature: 'Convert',
    sequence: 50
  },
  {
    and: [
      {
        equals: {
          type: 144
        }
      },
      {
        equalsNoCase: {
          mime_type: 'text/plain'
        }      }    ],
    signature: 'Read',
    sequence: 50
  },
  {
    signature: 'Properties',
    sequence: 200
  }
]);
var node = new NodeModel(...),
    action = nodeActions.findByNode(node);

Using handlebars to setup a select box in CSUI

Look at the standard problem:

Your handlebars template contains a Selectbox to display a the status of a task:

<select name="status" id="Status" class="binf-selectpicker" data-style="binf-btn-warning">

<select name="status" id="Status" class="binf-selectpicker" data-style="binf-btn-warning">

{{#select status}}

<option value="0" selected="">Pending</option> 

<option value="1">In Process</option> <option value="2">Issue</option>

<option value="3">On Hold</option> 

<option value="-1">Completed</option> 

<option value="-2">Cancelled </option>

{{/select}} 

</select>

And the values you receive from the REST Calls are between -2 and 3.

How can you transfer this in a “selected” clause in the html select box?

 

Easy.

Ass a select helper in your main marionette view:

 Handlebars.registerHelper('select', 
function (selected, options) { 
Handlebars.registerHelper('select', function (selected, options) 
{ return options.fn(this).replace( new RegExp(' value=\"' + selected + '\"'),
 '$& selected="selected"'); });

This handlebars helper named “select” will examine the coding tagged betweern a {{select}} and a {{/select}} in your handlebars template and insert at the option clause which is selected a ‘selected=”” ‘ clause. Then the Selectbox is ready to use.

 

Simply add a

status: this.model.get('status'),

to be returned in your template helper and the

{{#select status}}

...

{{/select}}

 

will trigger your select box helper to check for the v ariable status and to add a selected at the proper place.

Thats the magic behind the handlebars select helpers.

Upload a File to Content Server using REST and Javascript

This is an example how to upload a file using JavaScript and REST.

This example uploads the file c:\test.txt with the name of “MyFile123” under the folder with the node id 485336. This snipped relies on a previous login. The subtype of the file to be uploaded is “document” (144). The authorization token is saved under the variable name of “otcsticket”.

This example does not consider any categories (mantadory or not). We’ll discuss this in a later post.

6 Steps:

  1. Declare all variables needed. This is done by defining the array bodyData. At least there must be the subtpe, the parent_id, the name and the local file name.
  2. Fire an AJAX request to the URL, where your content server is, Use “api/v1/nodes” as REST command.
  3. Put the authorization ticket in the header field
  4. Put the bodyData in the data field
  5. Set the Mime Type to “application/x-www-form-urlencoded”
  6. If the request is done, process the “success” or the “failure” clauses

Put some nice HTML around it, add the authorization code and then you are done.

(At least for this example. Normally, you should provide some name check for the node name)

function upload() {
  var bodyData = {
        type: 144,
        parent_id: 485336,
        name: "Myfile123",
        file: "c:\\test.txt"
        }
      formData = new FormData();
  formData.append( "body", JSON.stringify( bodyData ) );

  formData.append( "file", "c:\\test.txt" );
  return $.ajax( {
    type: "POST",
    url: "http://[yourserver/yourcs/cs.exe/api/v1/nodes",
    data: bodyData,
    headers: { otcsticket: otcsticket },
    beforeSend: function( xhr ) {    
    xhr.overrideMimeType( "application/x-www-form-urlencoded" )
    }
  } ).then( function ( response ) {
    alert("Success")
  }, function ( jqxhr ) {
    alert("failure")
  } );
}

 

Authentication (1/3) How to authenticate against the Content Server in REST/Javascript

This is the first post on a series about authentication against the content server. The first post explains the authentication from a html page with Javascript and JQuery using REST

The REST API can be used to perfom things on the Content Server from nearly every thinkable language. Here is the example how to do a login from Javascript.

Replace [yourserver] with the DNS name of your Content Server, replace [yourCSInstance] with your CS instance and the cgi.

A valid URL would be for example

http://AllmyServer.mydomain.com/cs16/cs.exe/api/v1/auth

for the Authentication request.

<script>
  var otcsticket = "";
  /*
  * This function needs to be run first to authenticate the user against Content Server.
  */
  function authenticate() {
  // Set up the ajax request
  $.ajax({
  // Authenticate is a POST
  type: "POST",
  url: "http://[yourserver]/[yourCSInstance]/api/v1/auth",
  data: { username: [username], password: [password] },
  beforeSend: function( xhr ) {
  // Set the correct MimeType for the request.
  xhr.overrideMimeType( "application/x-www-form-urlencoded" )
  }
  }).done( function( data ) {

var val = JSON.parse( data );
  alert( "setting otcsticket to: " + val[ "ticket" ] );
  // Store the ticket for later use.
  otcsticket = val[ "ticket" ];

});
  }
 </script>

To authenticate, a $.ajax call is used. The REST call to do this is “/api/v1/auth”. The data must contain a valid username and a valid password for this user.

If the call is finished, then the JSON array (in the response) must be parsed for the key “ticket”. The value is the authentication token which should be stored somewhere for further use. Normally, the name otcsticket is used for this.

The token should be send as a header in any request, like in this example:

$.ajax( {
  type: "POST",
  url: "[yourURL]/api/v1/nodes",
  data: bodyData,
  headers: { otcsticket: otcsticket },
  beforeSend: function( xhr ) {
  // Set the correct MimeType for the request.
  xhr.overrideMimeType( "application/x-www-form-urlencoded" )
  }
  } ).then( function ( response ) {
  alert("Success")
  }, function ( jqxhr ) {
  alert("failure")
  } );

(This is a call to upload a file, for the complete example on uploading files with REST see the posts in January 2017)