Source: DataController.js

/**
 * Data controller module
 * @module app/DataController
 * @author David Kristiansen <david.kristiansen@nscc.ca>
 * @copyright Nova Scotia Community College 2017
 */
define([
        "dojo/_base/declare",
        "dojo/_base/lang",
        "dojo/on",
        "dojo/topic",
        "dojo/Evented",
        "dojo/promise/all",
           "dojo/request/xhr",

        "esri/tasks/QueryTask",
        "esri/tasks/query",

        "dstore/Memory",
        "dstore/Trackable",
        "dojo/_base/array"
    ],
    function (
        declare,
        lang,
        on,
        topic,
        Evented,
        all,
        xhr,

        QueryTask,
        Query,

        Memory,
        Trackable,
        arrayUtils
    ) {
        return declare([Evented, Memory, Trackable], {
            memDStore: {},
            chartTrack: {},
            stationList: {},
            lcaList: {},
            stationsIds: {},

            /**
             * Starts the module
             */
            startup: function () {
                //                console.log("DataController::startup");
                this._init();
            },
            /**
             * Executes QueryTask https://developers.arcgis.com/javascript/3/jsapi/querytask-amd.html
             * Need to use on("complete") and/or on("error") to get access to the response
             * @param {string} urlQ URL of rest end point to be queried
             * @param {array} outFieldsQ An optional array of fields to be returned (defaults to ["*"])
             * @param {array} orderByQ An optional array of fields to order the results by (defaults to "")
             * @param {boolean} geoQ Optional return geometry (defaults to false)
             * @param {string} whereQ Optional where clause for a query (defaults to "1=1")
             * @private
             *
             */
            _query: function (urlQ, outFieldsQ, orderByQ, geoQ, whereQ) {
                if (outFieldsQ === undefined) {
                    outFieldsQ = ["*"];
                }
                if (orderByQ === undefined) {
                    orderByQ = "";
                }
                if (geoQ === undefined) {
                    geoQ = false;
                }
                if (whereQ === undefined) {
                    whereQ = "1=1";
                }

                var QT = new QueryTask(urlQ);
                var Q = new Query();
                Q.returnGeometry = geoQ;
                Q.outFields = outFieldsQ;
                Q.orderByFields = orderByQ;
                Q.where = whereQ;
                return QT.execute(Q);

            },
            /**
             * Converts initial query task results of tide stations and lidar coverage areas into
             * dstore memory stores
             * @param {obj} fs feature set results from query task
             * @private
             *
             **/
            _getStarted: function (fs) {
                /** @function mapStnIds
                 * @description Swaps keys and values of tide station
                 * @param {obj} query task results
                 **/
                function mapStnIds(result) {
                    var swappedResults = {};

                    var stns = result.tables;
                    for (var i = 0; i < stns.length; i++) {
                        swappedResults[stns[i].name] = stns[i].id;
                    }
                    return swappedResults;
                }
                /**
                 * @function toTitleCase
                 * @description Converts strings to title case.
                 * Modified from http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript
                 * @param {string} str The text to be converted to titleCase.
                 **/
                function toTitleCase(str) {
                    return str.replace(/\w\S*/g, function (txt) {
                        return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
                    });
                }

                var tideResults, stnResults, lcaResults;

                // make sure both queries finished successfully
                if (!fs[0].hasOwnProperty("features")) {
                    console.error("One query failed.");
                }
                if (!fs[1].hasOwnProperty("features")) {
                    console.error("Two query failed.");
                }
                if (!fs[2].hasOwnProperty("tables")) {
                    console.error("Three query failed.");
                }

                lcaResults = fs[0].features;
                stnResults = fs[1].features;
                tideResults = fs[2];

                this.stationList = new Memory({
                    data: arrayUtils.map(stnResults, function (f) {
                        return {
                            "site_id": f.attributes.site_id,
                            "stn_id": f.attributes.stn_id,
                            "name": toTitleCase(f.attributes.stn_name)
                        };
                    }),
                    idProperty: "site_id"
                });

                this.lcaList = new Memory({
                    data: arrayUtils.map(lcaResults, function (f) {
                        return {
                            "said": f.attributes.said,
                            "default_site_id": f.attributes.default_site_id,
                            "name": f.attributes.name
                        };
                    }),
                    idProperty: "said"
                });

                this.stationsIds = mapStnIds(tideResults);

                this.emit("load", {});
            },
            /**
             * Processes feature set from query task of storm surge and tide data for a particular tide station.
             * Creates/overwrites a dstore memory stores used with the tide and storm surge chart.
             * @param {obj} fs feature set results from query task
             * @private
             *
             **/
            _prepData: function (fs) {
                //                console.log("Tide queries finished: ", fs);
                var tideResults;

                // make sure both queries finished successfully
                if (!fs.hasOwnProperty("features")) {
                    console.error("Tide query failed.");
                    return;
                }

                tideResults = fs.features;

                this.memDStore = new(declare([Memory, Trackable]))({
                    data: arrayUtils.map(tideResults, function (f) {
                        return {
                            "fulldate": f.attributes.dt,
                            "tide": f.attributes.tide,
                            "surge": f.attributes.surge,
                            "twl": f.attributes.twl
                        };
                    }),
                    idProperty: "fulldate"
                });

                this.chartTrack = new(declare([Memory, Trackable]))({
                    data: arrayUtils.map(tideResults, function (f) {
                        return {
                            "dt": f.attributes.dt,
                            "now": 0,
                            "sel": 0,
                            "clk": 1
                        };
                    }),
                    idProperty: "dt"
                });
                //                console.log("DataController::tideData_ready");
                this.emit("tideData_ready", {});
            },
            /**
             * Private method that initializes the module by querying for the lidar coverage areas and tide stations.
             * Waits both queries to complete before continuing.
             * @private
             *
             */
            _init: function () {
                var lca = this._query("//agrgims.cogs.nscc.ca/arcgis/rest/services/mcfm_pro/sa_flood/MapServer/0", ["said", "default_site_id", "default_site_id", "name"], ["name"]);
                var stations = this._query("//agrgims.cogs.nscc.ca/arcgis/rest/services/mcfm_pro/tide_stns/MapServer/0", ["site_id", "stn_id", "stn_name"], ["stn_name"]);
                var stationIds = this._getStationsIds();
                var promises = all([lca, stations, stationIds]);
                promises.then(lang.hitch(this, this._getStarted));
                //                console.log("Created dd list");
            },
             /**
             * Queries url for tide and storm surge data for a particular tide station.
             * Passes results to _prepData method to format data into a dstore memory store
             * @param {string} dataURL URL of rest end point to be queried
             * @public
             *
             **/
            getTideData: function (dataURL) {
                var data = this._query(dataURL, ["dt", "tide", "surge", "twl"], ["dt"]); //need to add order by to get the data into order!!
                data.then(lang.hitch(this, this._prepData));
            },
            /**
             * Json request to get the list of tide stations
             * @private
             *
             **/
            _getStationsIds: function () {
                return xhr("//agrgims.cogs.nscc.ca/arcgis/rest/services/mcfm_pro/tide_stns/MapServer?f=pjson", {
                    handleAs: "json",
                    headers: {
                        "X-Requested-With": null
                    }
                });
            }
        });
    });