New License

../../../../_images/step-project1.png ../../../../_images/step-meta1.png ../../../../_images/step-provision1.png ../../../../_images/step-presentation-b.png ../../../../_images/step-deploy1.png ../../../../_images/step-provisioning1.png

In this document, we will define a license creation editor that allows the provider to create a license offering for customers.

../../../../_images/step-presentation-licenses.png ../../../../_images/step-presentation-license-new-b.png ../../../../_images/step-presentation-license-edit.png ../../../../_images/step-presentation-services.png

In this document:

Overview

When creating a license APS resource, the provider should select one or more scopes to be assigned to that license. All possible scopes are specified in the ui/newlicense.json file created earlier.

The license-new view will be called from the licenses view when a user clicks the New button. The view controls the license creation process. A JavaScript code in ui/license-new.html must perform the following operations:

  • It represents the scopes stored in the ui/newlicense.json file as a full list of all scopes available in this APS application.

  • When a user clicks Cancel, it directs the user back to the licenses view. On Submit click, it saves the new license and then proceeds to the licenses view.

Development

When creating the ui/license-new.html file from the project template (as in our case), keep in mind the Typical Structure of View File and follow these steps.

  1. Ensure the require list contains all JavaScript modules that the main callback function will need:

    require([
          "dijit/registry",
          "dojo/when",
          "dojox/mvc/getPlainValue",
          "dojox/mvc/at",
          "dojox/mvc/getStateful",
          "aps/ResourceStore",
          "aps/load",
          "aps/CheckBox",
          "aps/json!./newlicense.json",
          "./displayError.js",
          "aps/ready!"
       ], function (
          registry,
          when,
          getPlainValue,
          at,
          getStateful,
          Store,
          load,
          CheckBox,
          newLicense,
          displayError
       ) {
       // .. To be continued in the next steps ..
    
    });
    
  2. In the main callback function, declare the license store that will interact with the APS controller and the license model that will interact with the widgets:

    // License store to interact with licenses stored in the APS DB:
    var licenseStore = new Store({
       apsType:    "http://aps-standard.org/samples/github/license/1.0",
       target:     "/aps/2/resources/"
       });
    
    // License model to interact with UI widgets when configuring a new license:
    var licenseModel = new getStateful(newLicense);
    

    Key:

    • We will need the license store to save the new license after the user submits the editing.

    • The license model is created with the properties pre-filled from the ui/newlicense file.

  3. Split the view into two widget groups: one contains the license name and description, and the other dynamically builds a list of scopes to be chosen for the new license:

    var widgets = ["aps/PageContainer", {id: "page"}, [
       ["aps/Panel", [
           ["aps/FieldSet", {id: "licenseNew_general", title: true}, [
               ["aps/TextBox", {
                   id: "licenseNew_licenseName",
                   label: "License Name",
                   value: at(licenseModel, "name"),
                   required: true
               }],
               ["aps/TextBox", {
                   id: "licenseNew_description",
                   label: "Description",
                   value: at(licenseModel, "description")
               }]
           ]]
       ]],
       ["aps/Panel", [
           ["aps/FieldSet", {id: "licenseNew_props", title: true}]
       ]]
    ]];
    

    Key:

    • The general properties are displayed by text boxes synced with the license model. The at() function implements the synchronization with the model.

    • The second widget group will be filled out dynamically in the next step after the whole widget structure is loaded.

  4. Use the asynchronous load->then->otherwise chain to load the widgets and then fill out the second widget group dynamically with checkboxes, each corresponding to a scope specified in the license model.

    load(widgets).then(function() {
       /* Add checkboxes, one per each scope defined in the newLicense default model */
       var scopes = licenseModel.get("scopes");
       var fieldSet = registry.byId("licenseNew_props");
       scopes.forEach(function(scope) {
           fieldSet.addChild( new CheckBox({
               checked: true,
               value: scope,
               label: scope
           }));
    
       });
    
       /* Create here handlers for the navigation buttons .. in the next steps*/
       // ... handlers ...
    
    }).otherwise(displayError);
    
  5. The navigation buttons “Cancel” and “Submit” for the view are declared in APP-meta.xml. Continue the definition of the load->then->otherwise chain with the definition of the handlers of those navigation buttons:

    aps.app.onCancel = function() {
       aps.apsc.gotoView("licenses");
    });
    
    aps.app.onSubmit = function() {
        var page = registry.byId("page");
        if (!page.validate()) {
           aps.apsc.cancelProcessing();
           return;
        }
           var boxes = registry.byId("licenseNew_props").getChildren();
           var scopes = [];
           boxes.forEach(function(box) {
               if (box.checked) scopes.push(box.value);
           });
           licenseModel.set("scopes", scopes);
           var payload = getPlainValue(licenseModel);
        when(licenseStore.put(payload),
           function() {
                aps.apsc.gotoView("licenses");
               },
           displayError
        );
    };
    

    Key:

    • The onCancel handler simply redirects the user back to the license landing page.

    • The onSubmit handler first validates the entered values, then collects the selected checkboxes (scopes) in the license model, and finally sends a request to save the license model as a new license APS resource. At the end, the user is returned to the license landing page.

Conclusion

Following the instructions in this document you have created a simple resource creation editor, that the provider can use to create a list of licenses with every license presenting a list of scopes.

The view source HTML file you have created should be similar to the sample license-new.html file:

<!DOCTYPE html>
<html>
<head>
<script src="/aps/2/ui/runtime/client/aps/aps.js"></script>
<script>
require([
       "dijit/registry",
       "dojo/when",
       "dojox/mvc/getPlainValue",
       "dojox/mvc/at",
       "dojox/mvc/getStateful",
       "aps/ResourceStore",
       "aps/load",
       "aps/CheckBox",
       "aps/json!./newlicense.json",
       "./displayError.js",
       "aps/ready!"
	], function (
       registry,
       when,
       getPlainValue,
       at,
       GetStateful,
       Store,
       load,
       CheckBox,
       newLicense,
       displayError
    ) {
        /* Define data source */
        // License store to interact with licenses stored in the APS DB:
        var licenseStore = new Store({
            apsType:    "http://aps-standard.org/samples/github/license/1.0",
            target:     "/aps/2/resources/"
        });

        // License model to interact with UI widgets to configure a new license:
        var licenseModel = new GetStateful(newLicense);

		/* Define and load the widgets */
       var widgets = ["aps/PageContainer", {id: "page"}, [
          ["aps/Panel", [
             ["aps/FieldSet", {id: "licenseNew_general", title: true}, [
                ["aps/TextBox", {
                   id: "licenseNew_licenseName",
                   label: "License Name",
                   value: at(licenseModel, "name"),
                   required: true
                }],
                ["aps/TextBox", {
                   id: "licenseNew_description",
                   label: "Description",
                   value: at(licenseModel, "description")
                }]
             ]]
          ]],
          ["aps/Panel", [
             ["aps/FieldSet", {id: "licenseNew_props", title: true}]
          ]]
       ]];

       load(widgets).then(function() {
          /* Add checkboxes, one per each scope defined in the newLicense default model */
          var scopes = licenseModel.get("scopes");
          var fieldSet = registry.byId("licenseNew_props");
          scopes.forEach(function(scope) {
             fieldSet.addChild(new CheckBox({
                checked: true,
                value: scope,
                label: scope
             }));
          });

          aps.app.onCancel = function() {
             aps.apsc.gotoView("licenses");
          };

           aps.app.onSubmit = function() {
              var page = registry.byId("page");
              if (!page.validate()) {
                 aps.apsc.cancelProcessing();
                 return;
              }
              var boxes = registry.byId("licenseNew_props").getChildren();
              var scopes = [];
              boxes.forEach(function(box) {
                 if (box.checked) scopes.push(box.value);
              });
              licenseModel.set("scopes", scopes);
              var payload = getPlainValue(licenseModel);
              when(licenseStore.put(payload),
                 function() {
                    aps.apsc.gotoView("licenses");
                 },
                 displayError
              );
           };
       }).otherwise(displayError);
});
</script>
</head>
<body>
</body>
</html>