Add customized publisher form for a custom RXT

In the previous post I have discussed how to add a custom asset type (Registry Extension) to wso2 governance registry. There can be situations, you need to customize these publisher forms in a way that your organizations requires. Probably adding more labels, changing colours and adding a captcha. Thanks to the maximum extendibility of wso2 governance center, you can do whatever the change your organizations requires. This article will elaborate on changing a particular area of a text field of Governance Publisher related to your custom RXT.

First you need to add your own custom RXT in order to add your own asset type. Read how to add a custome rxt here. For the consistency, you can use following RXT template as the extension.

After adding the rxt, move to the publisher (https://localhost:9443/publisher) and you will see the asset type “Widget” there. Once you click on “add new widget”, you will be redirected to a form like following.

You can do the customization to the form in two versa.

  • Add a custom.css file for modifying sizes and colours of existing fields.
  • Write a new template for the form with its own fields.

I will first go through the easy first way and then will jump into the more useful second scenario.

Adding a custom CSS

<custom_rxt_type> should be replaced with the short name of the asset type. (Here it should be “widget”)

  • Create a new css file such as custom-rxt.css in wso2greg-5.1.0/repository/deployment/server/jaggeryapps/publisher/extensions/assets/<custom_rxt_type>/themes/default/css
  • Every text-area in create page has its own id. Therefore it can be used to bind a new css rule to the element. Find the id of the text area that needs to be customized. (i.e.: overview_name). Then add your new style for the particular element using css id selector.
    e.g.:

     #overview_name {
        background-color: green;
        height: 340px;
    }
  • Create the following directory structure in wso2greg-5.1.0/repository/deployment/server/jaggeryapps/publisher/extensions/assets/<custom_rxt_type>/themes/default/helpers
  • Create a new helper file named create_asset.js and add the following content. Add the name of the custom css file to be pushed.
    e.g.: o.css.push(‘custom-rxt.css’);

  • Reload the page. Next time you move to “Add widget” form on publisher you will see the changes have taken place.

 Write a new template for the form

Suppose, there is a scenario where you want your organization wants to fill out some details on the form on behalf of the registrants. Or else, you want to check the inputs for a bot using a captcha. The extensible governance center platform provides you the maximum extensibility by adding your own .hbs (handlebars) template to be populated.

Assume that compared to the large palette of input fields in the “Add widget” page, you only need to show the required fields to the end user. The carbon-store platform allows you to override the default form with your own HTML/CSS/JS files.

  • Create the wso2greg-5.1.0/repository/deployment/server/jaggeryapps/publisher/extensions/assets/widget/themes/default directory structure. This is where we are going to place all the files needs to be used by the particular asset type.
  • Add 3 directories namely, “css”, “helpers”, “partials” in the path.
  • Create a file named “create_form.hbs” inside partials folder and enter following snippet there.

If you refer to the source of existing “Add Widget” form, you will notice that elements have been wrapped in such a hierarchy. Input fields for each entry contains the prefix of “overview_” in it’s id and you need to preserve the hierarchy, as we need these input fields to be serialized and sent to the server. ./css and ./js can be used to add more complicated verifications. Also note the form action as well.

On the .hbs context, input fields needs to be identified and mapped to the rxt entries. Therefore, use “overview_<fieldname>” pattern for input names and identifiers.
E.g.:

<input type='text' name='overview_version' id='overview_version' class="form-control validate-required" placeholder="Enter your version here!"/>

Once, you refresh the page you will see your new form in action instead of the default form.

Cheers!

[js-disqus]

Understanding asynchronous JavaScript – Callbacks

Recall Jquery click() function.

Have you ever wondered, why would you want to write the block of the code that needs to be executed after the clicking on the button inside another function?

Welcome to the world of asynchronous programming, callbacks!

Callback is a programming convention rather than a special feature of a language. They are useful when you want your program not to be blocked by a time consuming operation. In this case, finding the exact html element by the id might consume time. Once it is found, the function we pass to the click() function is called back.

See the following code.

Here, the find function takes 2 seconds to finish its operation.  It accepts a function as its parameter to be executed once the time consuming operation is done. (Don’t worry about the setTimeout() function. Yes, this too is a calling back function, but for the time being lets assume, all what it does is calling the passed function after 2 seconds). “callback” is just a variable that is used to pass the callback function back and forth. You can change it to whatever the name you want to call it. Even though it’s a time consuming operation, the alert in the main routine “meanwhile I show up” is displayed, regardless the synchronization.

Find function could be something that was defined in the API or somewhere in the program that performs IO operations or network calls. It promises to the main program routine that “I will call you back, once my time consuming operation is done”.

Callbacks with parameters

JS is too awesome to be around that we don’t explicitly need to mention what is being passed to the find function is another function. Be it another function with or without arguments and variables, it treats them the way they like to be treated. We can pass any function alongside any type of variable and a function signature. Inside the caller function (find() function) all we have to do is passing the arguments to the callback properly.

Here, we pass an array of 2 elements to find() function. It takes 2 seconds to find other elements and push them to the elements array. Then the resulting array is passed to the callback function as another parameter and from the major program routine it is caught and displayed.

Rolling in the deep

Here we pass the callback function by reference to the 2nd caller function, process().

Once the results are returned to the firstFunctionCall it sends the results to the process() function to add more elements to the array. The callback function for process() is passed by the reference onMethodsDone.

How to make sure passed function is actually a function?

Once your genius code is behind an API you need to throw proper messages to the user that he has not quit got the idea of callbacks or he has mixed up the function signature. You can use Js typeof operator to make sure the retrieved parameter is a reference to an actual function within the caller function. Try the following code passing a simple integer instead of a function at the firstFunctionCall.

Dealing with states

Your caller function behind the API may be operating a network call and might have gotten a null result. For the sake of modularity you need to treat the failure in a different way so then the user can handle the failure situation inside another function separately. Try following code by passing null instead of [1,2] to the find() function.

Will call you back! 🙂

Cheers!

[js-disqus]