Snippets

Piotr Szrajber Smart M.App - add custom computation results to Custom Container Widget

Created by Piotr Szrajber

File customization.js Added

  • Ignore whitespace
  • Hide word diff
+let GLOBALS = {},
+    TIMEOUTS = {};
+
+// recompute values using aggregation mechanisms and custom statistics on raw data
+function recomputeAggregations(callback, errback) {
+    const attribute1 = "WAGES_TOTAL",
+        attribute2 = "POPULATION_TOTAL";
+
+    gsp.bi.stage.findStage(null, function(stage) {
+        if (!stage) return;
+
+        // use BI aggregation mechanism. Here I'm using a weighted average of attribute1 by attribute2
+        let aggregationResult = stage.tryAggregation(`round($sum(${attribute1}*${attribute2})/$sum(${attribute2}))`);
+
+        if (!aggregationResult.success) return;
+
+        let value = aggregationResult.value.test;
+
+        // custom statistical operations on raw rows. I am using Array.prototype.reduce function
+        // but feel free to use plain for loop or whatever
+
+        let customAcc = stage.rows().reduce(function(accumulated, current) {
+            accumulated.min = Math.min(accumulated.min, current[attribute1]);
+            accumulated.max = Math.max(accumulated.max, current[attribute1]);
+            return accumulated;
+        }, {
+            min: Infinity,
+            max: -Infinity
+        });
+
+        let output = `Weighted average of ${attribute1} by ${attribute2} is ${value} while min=${customAcc.min} and max=${customAcc.max}`;
+        if (typeof callback === "function")
+            callback(output);
+
+    }, function(err) {
+        if (typeof errback === "function")
+            errback(err);
+    });
+}
+
+
+// recompute statistics and update the custom chart
+function update() {
+    recomputeAggregations(updateCustomChart);
+}
+
+
+// update the custom chart
+function updateCustomChart(html) {
+    document.querySelector(".custom-chart > div.widget-chart > div.widget-content").innerHTML = html;
+}
+
+function onRenderlet(chart, filter) {
+    update();
+}
+
+// wait for the pointmap layer, store reference to it and apply customizations
+waitFor("choropleth", function(widget) {
+    let geochart = widget.chart;
+    GLOBALS.geochart = geochart;
+    // attach an event to the choropleth so each time it is refreshed our onRenderlet function will execute
+    geochart.on("renderlet", onRenderlet);
+    // initial values
+    update();
+});
+
+// waits until the widget of particular type is on stage
+// this is simplified and it should be used just once for particular chartType
+// @param {String} chartType - "choropleth", "pointmap", "table", "row", "bar", "pie", etc.
+// @param {Function} callback callback function
+// @param {Object} callback.widget first widget of particular type
+// @return {void}
+function waitFor(chartType, callback) {
+    gsp.bi.stage.findWidgets({
+        descriptors: [{
+            chartM: {
+                chart: chartType
+            }
+        }]
+    }, function(widgets) {
+        if (!widgets || !widgets[0]) {
+            TIMEOUTS[chartType] = setTimeout(function() {
+                waitFor(chartType, callback);
+            }, 500);
+        } else {
+            clearTimeout(TIMEOUTS[chartType]);
+            callback(widgets[0]);
+        }
+    });
+}
HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.