mirror of
https://github.com/openwrt/luci.git
synced 2025-12-26 11:16:38 +04:00
luci-app-example: Update with more documentation, more examples (#6503)
* luci-app-example: Update with more documentation, examples * Update translations file * Move more YAML support to .md file, improve README * luci-app-example: Update with more documentation, examples * luci-app-example: Fix missed call to load_sample_yaml * Format with tabs by using jsbeautify
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
'use strict';
|
||||
'require form';
|
||||
'require rpc';
|
||||
'require view';
|
||||
|
||||
/*
|
||||
Declare the RPC calls that are needed. The object value maps to the name
|
||||
listed by the shell command
|
||||
|
||||
$ ubus list
|
||||
|
||||
Custom scripts can be placed in /usr/libexec/rpcd, and must emit JSON. The name of the file
|
||||
in that directory will be the value for the object key in the declared map.
|
||||
|
||||
Permissions to make these calls must be granted in /usr/share/rpcd/acl.d
|
||||
via a file named the same as the application package name (luci-app-example)
|
||||
*/
|
||||
var load_sample1 = rpc.declare({
|
||||
object: 'luci.example',
|
||||
method: 'get_sample1'
|
||||
});
|
||||
// Out of the box, this one will be blocked by the framework because there is
|
||||
// no ACL granting permission.
|
||||
var load_sample3 = rpc.declare({
|
||||
object: 'luci.example',
|
||||
method: 'get_sample3'
|
||||
});
|
||||
|
||||
|
||||
return view.extend({
|
||||
generic_failure: function (message) {
|
||||
// Map an error message into a div for rendering
|
||||
return E('div', {
|
||||
'class': 'error'
|
||||
}, [_('RPC call failure: '), message])
|
||||
},
|
||||
render_sample1_using_array: function (sample) {
|
||||
console.log('render_sample1_using_array()');
|
||||
console.log(sample);
|
||||
/*
|
||||
Some simple error handling. If the RPC APIs return a JSON structure of the
|
||||
form {"error": "Some error message"} when there's a failure, then the UI
|
||||
can check for the presence of the error attribute, and render a failure
|
||||
widget instead of breaking completely.
|
||||
*/
|
||||
if (sample.error) {
|
||||
return this.generic_failure(sample.error)
|
||||
}
|
||||
|
||||
/*
|
||||
Approach 1 for mapping JSON data to a simple table for display. The listing looks
|
||||
a bit like key/value pairs, but is actually just an array. The loop logic later
|
||||
on must iterate by 2 to get the labels.
|
||||
*/
|
||||
const fields = [
|
||||
_('Cats'), sample.num_cats,
|
||||
_('Dogs'), sample.num_dogs,
|
||||
_('Parakeets'), sample.num_parakeets,
|
||||
_('Should be "Not found"'), sample.not_found,
|
||||
_('Is this real?'), sample.is_this_real ? _('Yes') : _('No'),
|
||||
];
|
||||
|
||||
/*
|
||||
Declare a table element using an automatically available function - E(). E()
|
||||
produces a DOM node, where the first argument is the type of node to produce,
|
||||
the second argument is an object of attributes for that node, and the third
|
||||
argument is an array of child nodes (which can also be E() calls).
|
||||
*/
|
||||
var table = E('table', {
|
||||
'class': 'table',
|
||||
'id': 'approach-1'
|
||||
});
|
||||
|
||||
// Loop over the array, starting from index 0. Every even-indexed second element is
|
||||
// the label (left column) and the odd-indexed elements are the value (right column)
|
||||
for (var i = 0; i < fields.length; i += 2) {
|
||||
table.appendChild(
|
||||
E('tr', {
|
||||
'class': 'tr'
|
||||
}, [
|
||||
E('td', {
|
||||
'class': 'td left',
|
||||
'width': '33%'
|
||||
}, [fields[i]]),
|
||||
E('td', {
|
||||
'class': 'td left'
|
||||
}, [(fields[i + 1] != null) ? fields[i + 1] : _('Not found')])
|
||||
]));
|
||||
}
|
||||
return table;
|
||||
},
|
||||
|
||||
/*
|
||||
load() is called on first page load, and the results of each promise are
|
||||
placed in an array in the call order. This array is passed to the render()
|
||||
function as the first argument.
|
||||
*/
|
||||
load: function () {
|
||||
return Promise.all([
|
||||
load_sample1()
|
||||
]);
|
||||
},
|
||||
// render() is called by the LuCI framework to do any data manipulation, and the
|
||||
// return is used to modify the DOM that the browser shows.
|
||||
render: function (data) {
|
||||
// data[0] will be the result from load_sample1
|
||||
var sample1 = data[0] || {};
|
||||
// data[1] will be the result from load_sample_yaml
|
||||
var sample_yaml = data[1] || {};
|
||||
|
||||
// Render the tables as individual sections.
|
||||
return E('div', {}, [
|
||||
E('div', {
|
||||
'class': 'cbi-section warning'
|
||||
}, _('See browser console for raw data')),
|
||||
E('div', {
|
||||
'class': 'cbi-map',
|
||||
'id': 'map'
|
||||
}, [
|
||||
E('div', {
|
||||
'class': 'cbi-section',
|
||||
'id': 'cbi-sample-js'
|
||||
}, [
|
||||
E('div', {
|
||||
'class': 'left'
|
||||
}, [
|
||||
// _() notation on strings is used for translation detection
|
||||
E('h3', _('Sample JS via RPC')),
|
||||
E('div', {}), _(
|
||||
"JSON converted to table via array building and loop"
|
||||
),
|
||||
this.render_sample1_using_array(sample1)
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]);
|
||||
},
|
||||
/*
|
||||
Since this is a view-only screen, the handlers are disabled
|
||||
Normally, when using something like Map or JSONMap, you would
|
||||
not null out these handlers, so that the form can be saved/applied.
|
||||
|
||||
With a RPC data source, you would need to define custom handlers
|
||||
that verify the changes, and make RPC calls to a backend that can
|
||||
process the request.
|
||||
*/
|
||||
handleSave: null,
|
||||
handleSaveApply: null,
|
||||
handleReset: null
|
||||
})
|
||||
Reference in New Issue
Block a user