UNPKG

node-red-contrib-snap4city-d3-dashboard-widgets

Version:

Nodes for Snap4city project for D3 Dashboard Widgets

498 lines (471 loc) 21.4 kB
<!--/* NODE-RED-CONTRIB-SNAP4CITY-D3-DASHBOARD-WIDGETS Copyright (C) 2022 DISIT Lab http://www.disit.org - University of Florence This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Please note that the usage of this module is subjected to the D3.JS license that can be recovered from https://github.com/d3/d3 */--> <style type="text/css"> .dashboardBtn { background: #AD1625; border: none; color: #eee !important; padding-top: 5px; padding-bottom: 5px; padding-left: 10px; padding-right: 10px; } </style> <script type="text/javascript"> RED.nodes.registerType('dashboard-calendar', { category: 'S4CDashboard', color: '#00a2d3', defaults: { selectedDashboardId: { value: "", }, flowName: { value: "" }, authentication: { type: "snap4city-authentication-d3", required: false }, username: { value: "" }, name: { value: "", required: true }, dashboardId: { value: "", required: true }, metricType: { value: "Series" }, startValue: { value: 0 }, metricShortDesc: { value: "" }, metricFullDesc: { value: "" } }, inputs: 1, outputs: 0, icon: "abc.png", label: function () { return this.name || "calendar"; }, paletteLabel: function () { return this.name || "calendar"; }, align: 'right', oneditprepare: function () { $("#node-input-currentNodeId").val(this.id); var accessToken = getDashboardUserInfoAndCreateSelectionD3(); $("#node-input-authentication").change(function () { getDashboardUserInfoAndCreateSelectionD3(); }); $('#node-input-flowName').val($("li.red-ui-tab.ui-draggable.active a").attr("title")); $('#node-dashboard-edit').click(function () { if ($('#node-input-dashboardId').val() != null && $('#node-input-dashboardId') .val() != "") { $.ajax({ url: "dashboardManagerBaseUrl", type: "GET", async: true, success: function (_data) { var domain = (RED.nodes.node($("#node-input-authentication").val()) != null ? RED.nodes.node($("#node-input-authentication").val()).domain: ""); if (domain != "") { _data.dashboardManagerBaseUrl = domain + "/dashboardSmartCity"; } window.open(_data.dashboardManagerBaseUrl + "/controllers/openNRDashboardEditor.php?dashboardId=" + $('#node-input-dashboardId').val(), '_blank'); } }); } else { alert("Select a dashboard or enter the name of a new one"); } }); $('#node-dashboard-view').click(function () { if ($('#node-input-dashboardId').val() != null && $( '#node-input-dashboardId') .val() != "") { $.ajax({ url: "dashboardManagerBaseUrl", type: "GET", async: true, success: function (_data) { var domain = (RED.nodes.node($("#node-input-authentication").val()) != null ? RED.nodes.node($("#node-input-authentication").val()).domain: ""); if (domain != "") { _data.dashboardManagerBaseUrl = domain + "/dashboardSmartCity"; } window.open(_data.dashboardManagerBaseUrl + "/controllers/openNRDashboardViewer.php?dashboardId=" + $('#node-input-dashboardId').val(), '_blank' ); } }); } else { alert("Select a dashboard or enter the name of a new one"); } }); $("#createNewDashboardTitle").click(function () { $("#node-input-dashboardId").hide(); $("#node-input-dashboardId").val(""); $("#createNewDashboardTitle").hide(); $("#node-input-dashboardTitle").show(); $("#createNewDashboardButton").show(); $("#backDashboardTitle").show(); $("#node-dashboard-view").hide(); $("#node-dashboard-edit").hide(); $("#node-input-tip").show(); $("#node-input-dashboardTitle").val($("#node-input-dashboardTitleInserted").val()); $('#node-input-dashboardTitle').keypress(function (e) { var txt = String.fromCharCode(e.which); if (!txt.match(/[A-Za-z0-9&. ]/)) { return false; } }); }); $("#backDashboardTitle").click(function () { $("#node-input-dashboardTitle").val(""); $("#node-input-dashboardTitle").hide(); $("#node-input-dashboardId").show(); $("#createNewDashboardTitle").show(); $("#createNewDashboardButton").hide(); $("#backDashboardTitle").hide(); $("#node-dashboard-view").show(); $("#node-dashboard-edit").show(); $("#node-input-tip").hide(); }); $("#createNewDashboardButton").click(function () { if ($("#node-input-dashboardTitle").val() != "") { if (accessToken != "") { $.ajax({ url: "dashboardManagerBaseUrl", type: "GET", async: true, success: function (_data) { var domain = (RED.nodes.node($("#node-input-authentication").val()) != null ? RED.nodes.node($("#node-input-authentication").val()).domain: ""); if (domain != ""){ _data.dashboardManagerBaseUrl = domain + "/dashboardSmartCity"; } $.ajax({ url: _data.dashboardManagerBaseUrl + "/controllers/createDashboardFromNR.php?dashboardTitle=" + encodeURIComponent($("#node-input-dashboardTitle").val()) + "&accessToken=" + accessToken, type: "GET", async: true, success: function (_data) { try { _data = JSON.parse(_data) } catch (e) { console.log(e); } if (_data.result) { if (_data.result.toLowerCase() == "ok") { $("#node-input-selectedDashboardId").val(_data.dashboardId); getDashboardUserInfoAndCreateSelectionD3(); } else { alert(_data.errormsg); } } }, error: function (_error) { console.log(_error); } }); }, error: function (_error) { console.log(_error); } }); } else { $.ajax({ url: "createDashboard/", type: "POST", async: true, dataType: "json",data: { "dashboardTitle": $("#node-input-dashboardTitle").val(), "authenticationNodeId": $("#node-input-authentication").val(), "authenticationNodeDomain": RED.nodes.node($("#node-input-authentication").val()).domain }, success: function (_data) { try { _data = JSON.parse(_data) } catch (e) { console.log(e); } if (_data.result) { if (_data.result.toLowerCase() == "ok") { $("#node-input-selectedDashboardId").val(_data.dashboardId); getDashboardUserInfoAndCreateSelectionD3(); } else { alert(_data.errormsg); } } }, error: function (_error) { console.log(_error); } }); } } else { alert("To create a new dashboard you must insert the name of the dashboard"); } }); }, oneditsave: function () { $("#node-input-selectedDashboardId").val($("#node-input-dashboardId").val()); } }); var getDashboardUserInfoAndCreateSelectionD3 = function () { var accessToken = ""; var username = ""; var dashboardList = ""; $.ajax({ url: "retrieveAccessTokenAuthenticationD3", type: "POST", async: false, dataType: "json", data: { "authenticationNodeId": $("#node-input-authentication").val(), "nodeId": $("#node-input-currentNodeId").val() }, success: function (_data) { if (_data.accessToken == "") { $("#selectDashboardContainer").hide(); $("#selectWidgetName").hide(); $('#node-dashboard-view').hide(); $('#node-dashboard-edit').hide(); $('#tipAuthenticationWrong').show(); $('#tipAuthentication').hide(); } else { $("#selectDashboardContainer").show(); $("#selectWidgetName").show(); $('#node-dashboard-view').show(); $('#node-dashboard-edit').show(); $('#tipAuthenticationWrong').hide(); $('#tipAuthentication').show(); username = _data.username; accessToken = _data.accessToken; }; } }); $("#node-input-username").val(username); refreshDashboardSelectionD3(username, accessToken, dashboardList); return accessToken; }; var refreshDashboardSelectionD3 = function (username, accessToken, dashboardList) { $("#node-input-dashboardId").empty(); if (dashboardList != "") { createDashboardSelectionD3(dashboardList); } else if (username != "" && accessToken != "" && dashboardList == "") { $.ajax({ url: "dashboardManagerBaseUrl", type: "GET", async: false, success: function (_data) { var domain = (RED.nodes.node($("#node-input-authentication").val()) != null ? RED.nodes.node($("#node-input-authentication").val()).domain: ""); if (domain != ""){ _data.dashboardManagerBaseUrl = domain + "/dashboardSmartCity"; } $.ajax({ url: _data.dashboardManagerBaseUrl + "/api/nodeRedDashboardsApi.php?v3&username=" + username + "&accessToken=" + accessToken, type: "GET", async: true, dataType: "json", success: function (_data) { createDashboardSelectionD3(_data); }, error: function (err) { $("#createNewDashboardTitle").click(); console.log(err); } }); } }); } } var createDashboardSelectionD3 = function (currentDashboardList) { console.log(currentDashboardList); if (currentDashboardList.length != 0) { $('#node-dashboard-view').show(); $('#node-dashboard-edit').show(); $("#node-input-dashboardId").empty(); var currentValue = $("#node-input-selectedDashboardId").val(); for (var i = 0; i < currentDashboardList.length; i++) { $("<option value='" + currentDashboardList[i].id + "'>" + decodeURI(currentDashboardList[i].title.replace( /\+/g, " ")) + "</option>") .appendTo($("#node-input-dashboardId")); } $("#node-input-dashboardId").val(currentValue); $("#backDashboardTitle").click(); } else { $("#createNewDashboardTitle").click(); } } </script> <script type="text/x-red" data-template-name="dashboard-calendar"> <input type="hidden" id="node-input-username"> <input type="hidden" id="node-input-flowName"> <input type="hidden" id="node-input-currentNodeId"> <input type="hidden" id="node-input-selectedDashboardId"> <div class="form-row" id="rowAuthentication"> <label for="node-input-authentication">Authentication</label> <input type="text" id="node-input-authentication"> </div> <div class="form-row" id="selectDashboardContainer"> <label for="node-input-dashboardTitle"> <i class="fa fa-dashboard"></i>Dashboard Name</label> <input type="text" autocomplete="off" id="node-input-dashboardTitle" placeholder="Dashboard Name" style="display:none; width: 55%;"> <select id="node-input-dashboardId" style="width: 55%;"> </select> <button id="createNewDashboardTitle" >New Dashboard</button> <button id="createNewDashboardButton" style="display:none">Create</button> <button id="backDashboardTitle" style="display:none">Show list</button> </div> <div class="form-row" id="selectWidgetName"> <label for="node-input-name"> <i class="icon-tag"></i> Widget Name</label> <input type="text" autocomplete="off" id="node-input-name" placeholder="Widget Name"> </div> <div class="form-row"> <button class="dashboardBtn" click="openDashboardEditor" role="button" aria-disabled="false" id="node-dashboard-edit"> Edit Dashboard </button> <button class="dashboardBtn" click="openDashboardViewer" role="button" aria-disabled="false" id="node-dashboard-view"> View Dashboard </button> </div> <div id="node-input-tip" class="form-tips" style="display:none">The new dashboard is created entering the title andclicking on create </div> <div class="form-tips" id="tipAuthentication" style="max-width: none"> You must have an account with Snap4city to use this node. You can register for one <a href="https://www.snap4city.org" target="_blank">here</a>. </div> <div class="form-tips" id="tipAuthenticationWrong" style="display:none; max-width: none"> Maybe the authentication data are wrong. Check them and redeploy the node. </div> <div class="form-tips" id="tipAuthenticationRedeploy" style="display:none; max-width: none"> Deploy the node to retrieve the updated list of dashboards. </div> <div class="form-tips" id="tipAuthenticationDeployFirstTime" style="display:none; max-width: none"> Insert the authentication data and deploy the node to retrieve the updated list of dashboards. </div> </script> <script type="text/x-red" data-help-name="dashboard-calendar"> <p>With this node you can add a calendar to an existing dashboard or a new one created by the node to show a calendar. </p> <h3>Configurations</h3> <dl class="message-properties"> <dt>dashboard <span class="property-type">string</span> </dt> <dd>Dashboard title to which the calendar will be added</dd> <dt>widget <span class="property-type">string</span> </dt> <dd> Title that will have the widget containing the calendar.</dd> </dl> <h3>Inputs</h3> <dl class="message-properties"> A JSON array like the following: <pre> [ { "metricId": [Service Uri Of A Sensor], "metricHighLevelType": "Sensor", "metricName": [The name of the Sensor], "smField": [A measure recorded by the sensor], "serviceUri": [Service Uri Of A Sensor] }, { "metricId": [The ID of a KPI], "metricHighLevelType": "MyKPI", "metricName": [The name of the MyKPI], "smField": [The type of the measure saved in the KPI], "serviceUri": [The ID of a KPI] }, { "metricId": "", "metricHighLevelType": "Dynamic", "metricName": [The name of the dynamic data], "smField": [The type of the dynamic data], "metricValueUnit": [The unit of the dynamic data], "value": [An array of array of timestamp and value] } ] </pre> <p>You can insert an arbitrary number of MyKPI and Sensor element inside the array. An example of the JSON array filled with correct data:</p> <pre> [ { "metricId": "serviceUri=http://www.disit.org/km4city/resource/IBIMET_SMART17", "metricHighLevelType": "Sensor", "metricName": "IBIMET_SMART12", "smField": "PM10", "serviceUri": "http://www.disit.org/km4city/resource/IBIMET_SMART17" }, { "metricId": "https://servicemap.disit.org/WebAppGrafo/api/v1/?serviceUri=http://www.disit.org/km4city/resource/IBIMET_SMART12&format=json", "metricHighLevelType": "Sensor", "metricName": "IBIMET_SMART12", "smField": "PM10", "serviceUri": "http://www.disit.org/km4city/resource/IBIMET_SMART12" }, { "metricId": "17056191", "metricHighLevelType": "MyKPI", "metricName": "S4CTuscanyTrackerLocation", "smField": "GPS Information Saved From The App", "serviceUri": "17056191" }, { "metricId": "", "metricHighLevelType": "Dynamic", "metricName": "BatteryTemperatureGalaxyNote", "smField": "Gradi Centigradi", "metricValueUnit": "°C", "values": [ [1580305500000, 19.5], [1580301900000, 20.0], [1580298300000, 20.5], [1580294700000, 18.5], [1580291100000, 19], [1580287500000, 18.5], [1580283900000, 21.5], [1580280300000, 22.0], [1580276700000, 19], [1580273100000, 17.5], [1580269500000, 16.5], [1580265900000, 17.0], [1580262300000, 18.5], [1580258700000, 20.0], [1580255100000, 19.5], [1580251500000, 21.5], [1580247900000, 21] ] } ] </pre> </dl> </script>