Presentation Logic

The application UI must allow the subscribers to discover the registered domains and select one of them for a new VPS when creating the latter.

../../../../_images/dns-step-model.png ../../../../_images/dns-step-meta.png ../../../../_images/dns-step-provision.png ../../../../_images/dns-step-presentation-b.png ../../../../_images/dns-step-deploy.png ../../../../_images/dns-step-provisioning.png

Requirements

The following details clarify the application behavior at the presentation level mostly when creating a VPS:

  • The UI must find all domains registered by the subscriber. The recommended way is to use the paDomains collection linking the context resource with the registered domains.

  • The customers must be able to assign one of available domains to a VPS when creating one.

  • The UI must prompt customers to assign an IP address for the new domain. The UI code must create a respective A record automatically.

Continue Your Demo Project

Continue the demo project started in the previous step. Update the provisioning logic of the context and vps APS types as required.

Auxiliary File

The only auxiliary file you need to update is ui/wizard/newvps.json. This file brings default values for a newly created VPS.

Add the following components:

  • The domain relation from the implemented Domain APS type

  • The domainName and ipAddress properties declared in the vps APS type directly

{ ...
   "domain": {
      "aps": {
         "id": ""
      }
   },
   "domainName": "",
   "ipAddress": ""
}

New VPS

First Step

When creating a new VPS, the /ui/wizard/server-new-1.js script must identify the domain zones bound to the subscription. It must prompt a customer to select a domain and enter the VPS name and IP address. Then it must pass the collected VPS properties to the next step of the wizard.

The vps-new-1 view receives the context navigation variable that represents the management context resource including the paDomains collection of links.

  1. In the field set containing the domain selection list and the CNAME checkbox, replace the latter with a text box to enter an IP address, so the filed set must look similar to the following:

    ["aps/FieldSet", { id: this.genId("srvNew1_domains") }, [
       ["aps/Select", {
          id: this.genId("srvNew1_domainSelect"),
          label: "Domain",
          gridSize: 'md-3 xs-12',
          store: this.domainStore,
          labelAttr: "name",
          value: at(this.vpsModel.data.domain.aps, "id"),
          required: true
       }],
       ["aps/TextBox", {
          id: this.genId("srvNew1_ipAddress"),
          label: "IP Address",
          gridSize: "md-3 xs-12",
          value: at(this.vpsModel.data, "ipAddress"),
          required: true
       }]
    ]]
    
  2. In the onContext method, replace the existing definition of the domain list with new one that includes only those domains that are bound to the management context. Among those domains, define a domain (first from the list) selected by default in the selection list. Sync the domain selection list with the list of domain zones bound to the management context:

    onContext: function(context) {
       if (!aps.context.wizardData["http://aps-standard.org/samples/bind2domain#server-new-1"])
          this.vpsModel.set("data", newVPS);
    
       /* Refresh the store */
       var domains = context.vars.context.paDomains;
       this.domainStore.setData(domains);
       var domainSelection = this.byId("srvNew1_domainSelect");
       domainSelection.set("store", this.domainStore);
    
       /* Define the selected domain */
       if (aps.context.wizardData["http://aps-standard.org/samples/bind2domain#vps-wizard"]) {
          this.vpsModel.data.domain.aps.set(
             "id",
             aps.context.wizardData["http://aps-standard.org/samples/bind2domain#vps-wizard"]
          );
       }
       else domainSelection.set("value", domains[0].aps.id);
    
       aps.apsc.hideLoading();
     },
    
  3. In the onNext handler, define the VPS domain name consisting of the VPS name and the name of the selected domain. Then send the collected VPS representation to the next step.

    onNext: function() {
    
       var form = this.byId("srvNew_form");
    
       /* Validate the values assigned to widgets */
       if (!form.validate()) {
          aps.apsc.cancelProcessing();
          return;
       }
    
       /* Figure out the VPS domain name */
       var selectWidget = this.byId("srvNew1_domainSelect");
       var domainId = selectWidget.get("value");
       this.vpsModel.data.set(
          "domainName",
          this.vpsModel.data.vpsname + "." + selectWidget.getOption(domainId)[0].label
       );
    
       /* Proceed to the next step */
       aps.apsc.next(this.vpsModel.data);
    },
    

Last Step

In the last step view, implemented by the ui/wizard/server-new-last.js script, ensure the VPS domain name and IP address are displayed.

For this effect, update the file as follows.

  1. In the init method, replace the definition of the aps/Status widget with the following output widget:

["aps/Output", {
   id: this.genId("srvNew_ipaddress"),
   label: "IP Address",
   value: at(this.vpsModel.data, "ipAddress")
}],
  1. In the onContext method, remove the code that processes the CNAME property.

VPS Creation Wizard

The application UI must request the APS controller to create sequentially two resources:

  • VPS based on the http://aps-standard.org/samples/bind2domain/vps/1.0 type

  • DNS A record based on the http://aps-standard.org/types/dns/record/a/1.0 type and linked with the new VPS created at the previous step

Update the ui/vps-wizard.js script as follows.

  1. In the main call-back function, replace the function that creates a CNAME with a function that creates a DNS A record for the VPS:

    function createDnsRecord(vps) {
       var jsonData = {
          "aps": {
             "type": "http://aps-standard.org/types/dns/record/a/1.0"
          },
          "RRState": "active",
          "TTL": 3600,
          "source": vps.domainName + ".",
          "address": vps.ipAddress,
          "zone": {
             "aps": {
                "id": vps.domain.aps.id
             }
          }
       };
       return xhr("/aps/2/resources/" + vps.aps.id + "/records", {
          method: "POST",
          data: JSON.stringify(jsonData)
       });
    }
    

    The jsonData structure complies with the DNS A record type and its parent core DNS record type. The xhr method sends this structure in the body of the POST request for creating an A record.

  2. Ensure the onSubmit handler calls the createDnsRecord method to create a DNS A record after the VPS resource is created in the APS controller:

    var newVPS =
       aps.context.wizardData["http://aps-standard.org/samples/bind2domain#server-new-1"];
    store.put(newVPS)
    .then(function(vps) {
       return createDnsRecord(vps);
    })
    .then(function() {
          aps.apsc.gotoView("servers");
       }, displayError
    );
    

Project Improvement

You should also modify on your own the ui/servers.js and ui/server-edit.js scripts to present the new properties in the list of VPSes and to edit the new properties respectively.

Conclusion

You have designed and updated the presentation logic for the demo application. The updated UI source code completes the implementation of the planed scenario.

The files you have updated are similar to the respective files in the sample package.