In this document, we will define a license editor that enables the provider to edit an existing license.
In this document:
When editing a license APS resource, the provider must be able to 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-edit
view will be called from the licenses
view when a user clicks on a license name.
From the navigation variable license
declared in the metadata, the view must get the JSON representation
of the license to edit .
A JavaScript code in ui/license-edit.html
must perform the following operations:
Presents all allowed scopes stored in the ui/newlicense.json
file as a list of checkboxes.
Boxes with already selected scopes in the license must be checked. The user can check and clean the boxes
as required.
When a user clicks Cancel, the view directs the user back to the licenses
view. On Submit click, the
editor saves the edited license and then directs the user to the licenses
view.
The development of this view is similar to the development of the license creation wizard. With some modifications, you can even combine both views in one HTML file.
When creating the ui/license-edit.html
file from the project template (as in our case),
keep in mind the Typical Structure of View File and follow these steps.
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 ..
});
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:
/* Declare data sources */
var licenseStore = new Store({
apsType: "http://aps-standard.org/samples/github/license/1.0",
target: "/aps/2/resources/"
});
/* Get the current license from the navigation variable declared in metadata */
var licenseModel = getStateful(aps.context.vars.license);
Key:
We will need the license store to save the new license on commit.
The license model is created with the properties pre-filled from the license opened for editing.
Split the view into two widget groups: one presents 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: "licenseEdit_general", title: true}, [
["aps/TextBox", {
id: "licenseEdit_licenseName",
label: "License Name",
value: at(licenseModel, "name"),
required: true
}],
["aps/TextBox", {
id: "licenseEdit_description",
label: "Description",
value: at(licenseModel, "description")
}]
]]
]],
["aps/Panel", [
["aps/FieldSet", {id: "licenseEdit_props", title: true}]
]]
]];
Key:
The general properties are displayed by text boxes synced with the license model.
The second widget group will be filled out dynamically in the next step after the whole widget structure is loaded.
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 = newLicense.scopes;
var fieldSet = registry.byId("licenseEdit_props");
scopes.forEach(function(scope) {
var checked = licenseModel.get("scopes").includes(scope);
fieldSet.addChild( new CheckBox({
checked: checked,
value: scope,
label: scope
}));
});
/* Create here handlers for the navigation buttons in the next steps*/
// ... handlers ...
}).otherwise(displayError);
The navigation buttons “Cancel” and “Submit” for the view are declared in APP-meta.xml
.
Continue development 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("licenseEdit_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 returns the user to the main service view.
The onSubmit
handler firstly validates the entered values, then collects the selected checkboxes (scopes)
in the license model, and finally sends a request to the APS controller to save the license model
as a new license APS resource. After that is done, the user is returned back to the main service view.
Following the instructions in this document you have created a simple resource editor that the provider can use to fix or update a license.
The view source HTML file you have created should be similar
to the sample license-edit.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
) {
/* Declare data sources */
var licenseStore = new Store({
apsType: "http://aps-standard.org/samples/github/license/1.0",
target: "/aps/2/resources/"
});
/* Get the current license from the navigation variable declared in metadata */
var licenseModel = getStateful(aps.context.vars.license);
/* Define and load the widgets */
var widgets = ["aps/PageContainer", {id: "page"}, [
["aps/Panel", [
["aps/FieldSet", {id: "licenseEdit_general", title: true}, [
["aps/TextBox", {
id: "licenseEdit_licenseName",
label: "License Name",
value: at(licenseModel, "name"),
required: true
}],
["aps/TextBox", {
id: "licenseEdit_description",
label: "Description",
value: at(licenseModel, "description")
}]
]]
]],
["aps/Panel", [
["aps/FieldSet", {id: "licenseEdit_props", title: true}]
]]
]];
load(widgets).then(function() {
/* Add checkboxes, one per each scope defined in the newLicense default model */
var scopes = newLicense.scopes;
var fieldSet = registry.byId("licenseEdit_props");
scopes.forEach(function(scope) {
var checked = licenseModel.get("scopes").includes(scope);
fieldSet.addChild( new CheckBox({
checked: checked,
value: scope,
label: scope
}));
});
/* Create here handlers for the 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("licenseEdit_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>