summaryrefslogtreecommitdiffhomepage
path: root/applications/luci-app-example/htdocs/luci-static/resources/view/example/rpc.js
diff options
context:
space:
mode:
authorDuncan Hill <github.com@cricalix.net>2023-12-04 21:12:28 +0000
committerGitHub <noreply@github.com>2023-12-04 22:12:28 +0100
commit28f805b2e5f95e04515bd7d045a103cc3a366c2c (patch)
tree4c52498b38b97efdc3660c404a0341027d391518 /applications/luci-app-example/htdocs/luci-static/resources/view/example/rpc.js
parenta5786b5f2f68596b2ea8441fc8ad8ad7cf2ce2a9 (diff)
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
Diffstat (limited to 'applications/luci-app-example/htdocs/luci-static/resources/view/example/rpc.js')
-rw-r--r--applications/luci-app-example/htdocs/luci-static/resources/view/example/rpc.js150
1 files changed, 150 insertions, 0 deletions
diff --git a/applications/luci-app-example/htdocs/luci-static/resources/view/example/rpc.js b/applications/luci-app-example/htdocs/luci-static/resources/view/example/rpc.js
new file mode 100644
index 0000000000..cf5885b5a2
--- /dev/null
+++ b/applications/luci-app-example/htdocs/luci-static/resources/view/example/rpc.js
@@ -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
+}) \ No newline at end of file