From 8790e149b8e85903376463426011f8386eacf83f Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" Date: Thu, 16 May 2024 14:48:38 +0530 Subject: [PATCH] update blog --- .../exploring-node-red-dashboard-2-widgets.md | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/blog/2024/05/exploring-node-red-dashboard-2-widgets.md b/src/blog/2024/05/exploring-node-red-dashboard-2-widgets.md index 227b681731..8f32ccb184 100644 --- a/src/blog/2024/05/exploring-node-red-dashboard-2-widgets.md +++ b/src/blog/2024/05/exploring-node-red-dashboard-2-widgets.md @@ -14,11 +14,11 @@ This guide delves into Node-RED Dashboard 2.0 widgets, teaching you how to build -If you're new to Dashboard 2.0, I recommend starting with the [Getting Started with Dashboard 2.0](/blog/2024/03/dashboard-getting-started/) guide and installing it. +If you're new to Dashboard 2.0, we recommend starting with the [Getting Started with Dashboard 2.0](/blog/2024/03/dashboard-getting-started/) guide and make sure to install it. ## What Are Widgets? -Widgets in Node-RED are like building blocks for creating the user interface. They're made of front-end pieces of code and work on the client's side. In Dashboard 2.0, you get a variety of widgets like forms, templates, buttons, and others to make different parts of your interface. +Widgets in Node-RED Dashboard 2.0 are like building blocks for creating the user interface. They're made of front-end pieces of code and work on the client's side. In Dashboard 2.0, you get a variety of widgets like forms, templates, buttons, and others to make different parts of your interface. ## Building Applications with Dashboard 2.0 Widgets @@ -45,7 +45,7 @@ Once you've added the income submission form, repeat the process to add an expen The **ui-form** widget emits a payload object with key-value pairs of form elements upon submission. We'll store this data in a global context. -1. Drag a **function** node onto the canvas and use the following code which also contain notification message set to payload: +1. Drag a **function** node onto the canvas and use the following code which also contains a notification message set to payload: ```javascript let income = global.get('income') || []; @@ -73,9 +73,9 @@ For displaying notifications on the dashboard, we'll utilize the **ui-notificati ### Listening events -In Dashboard 2.0, the **ui-event** widget allows you to listen for user behavior or events. It does not render any content or components on the dashboard. Currently, this widget only listens for page view and leave events. +In Dashboard 2.0, the **ui-event** widget allows you to listen to user behavior or events. It does not render any content or components on the dashboard. Currently, this widget only listens for page views and leaves events. -With this, we can listen for a page view and page leave event and trigger tasks based on those events. For instance, in our application, we will be displaying a table containing income-expense data and a chart that we will gets update when we visit a new page or leave a page. +With this, we can listen for a page view and page leave event and trigger tasks based on those events. For instance, in our application, we will be displaying a table containing income-expense data and a chart. that we will update when we visit a new page or leave a page. 1. Drag an **ui-event** widget onto the canvas. 2. Double-click on it and select the correct **ui-base** of your application. @@ -87,7 +87,7 @@ For more information on ui-event refer to [ui-event docs](https://dashboard.flow In our income-expense application, we will display the income and expenses in a single table. 1. Drag a **change** node onto the canvas. -2. Set `msg.payload` to the JSON expression below, which merges two icome and expense array. +2. Set `msg.payload` to the JSON expression below, which merges two income and expense array. 3. Connect the output of the **ui-event** widget to the input of the **change** node. ```javascript @@ -109,7 +109,7 @@ For more information on ui-table refer to [ui-table docs](https://dashboard.flow ### Calculating total category-wise -In our application, we will display data on the chart with the total income and total expenses for analysis. For that in this section we will calculate the total expense and income using the function node. +In our application, we will display data on the chart with the total income and total expenses for analysis. For that in this section, we will calculate the total expense and income using the function node. 1. Drag an **function** node onto canvas. 2. Paste the following code in it, we have added comments in the code for your better understanding. @@ -122,7 +122,7 @@ let expense = global.get('expense') || []; // Initialize an empty result array let result = []; -// Send an empty payload to reset chart +// Send an empty payload to reset the chart node.send({ payload: [] }); // Calculate total income by summing up amounts in the income array @@ -153,23 +153,23 @@ To display charts on the dashboard, we have to use the ui-chart widget which all ### Adding custom footer with ui-template -With ui-template widget, we can add a custom component to our app using Vue.js. It also allows adding custom CSS for dashboar and more. For more information refer to [ui-template docs](https://dashboard.flowfuse.com/nodes/widgets/ui-template.html). +With the ui-template widget, we can add a custom component to our app using Vue.js. It also allows adding custom CSS for the dashboard and more. For more information refer to [ui-template docs](https://dashboard.flowfuse.com/nodes/widgets/ui-template.html). Using this widget, we will add a footer to our application. 1. Drag an ui-template widget onto the canvas. -2. Set the type widget( ui scoped ) which will render this widget on entire dashboard so that we will not need to add seprate footers for each page of the dashboard. +2. Set the type widget( ui scoped ) that will render this widget on the entire dashboard so that we will not need to add separate footers for each page of the dashboard. 3. Insert the following vue.js code in the ui-template widget. ```javascript -// Get income and expense arrays from global context, or set them as empty arrays if not found +// Get income and expense arrays from a global context, or set them as empty arrays if not found let income = global.get('income') || []; let expense = global.get('expense') || []; // Initialize an empty result array let result = []; -// Send an empty payload to reset chart +// Send an empty payload to reset the chart node.send({ payload: [] }); // Calculate total income by summing up amounts in the income array @@ -191,6 +191,11 @@ return msg; ### Deploying your application flow +{% renderFlow %} +[{"id":"7ac3890dfa74703b","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"342f3ee215d32fdc","type":"group","z":"7ac3890dfa74703b","name":"New Icome page","style":{"label":true},"nodes":["d028c878350d19e1","43e79bb77d718c95","5ba5d8bff1a77bea"],"x":274,"y":159,"w":752,"h":82},{"id":"4afb4814be56a9a8","type":"group","z":"7ac3890dfa74703b","name":"New Expense page","style":{"label":true},"nodes":["e82b719d899cbf73","3457848652ad75e1","bd90a9ad612408d3"],"x":274,"y":279,"w":752,"h":82},{"id":"e6ee60438b20dc44","type":"group","z":"7ac3890dfa74703b","name":"Overview chart","style":{"label":true},"nodes":["424b35900722e740","f21a87c5c5aec0b2"],"x":274,"y":519,"w":592,"h":82},{"id":"77217e256ef75328","type":"group","z":"7ac3890dfa74703b","name":"Your icome and expense table","style":{"label":true},"nodes":["452d561bf79727cb","0c64567c81dd6a8d"],"x":274,"y":399,"w":572,"h":82},{"id":"1b78769d6d27d102","type":"group","z":"7ac3890dfa74703b","name":"Event lister","style":{"label":true},"nodes":["9ce6db04b2c9d7b2"],"x":54,"y":459,"w":152,"h":82},{"id":"e82b719d899cbf73","type":"ui-form","z":"7ac3890dfa74703b","g":"4afb4814be56a9a8","name":"Expense Submission Form","group":"854706651cd8a8f2","label":"","order":1,"width":"12","height":"1","options":[{"label":"Date","key":"date","type":"date","required":true,"rows":null},{"label":"Description","key":"description","type":"text","required":true,"rows":null},{"label":"Category","key":"category","type":"text","required":true,"rows":null},{"label":"Amount","key":"amount","type":"number","required":true,"rows":null},{"label":"Note","key":"note","type":"text","required":false,"rows":null}],"formValue":{"date":"","description":"","category":"","amount":"","note":""},"payload":"","submit":"submit","cancel":"clear","resetOnSubmit":true,"topic":"topic","topicType":"msg","splitLayout":"","className":"","x":410,"y":320,"wires":[["bd90a9ad612408d3"]]},{"id":"3457848652ad75e1","type":"ui-notification","z":"7ac3890dfa74703b","g":"4afb4814be56a9a8","ui":"a0a85a5f4c29af50","position":"center center","colorDefault":true,"color":"#000000","displayTime":"3","showCountdown":true,"outputs":0,"allowDismiss":true,"dismissText":"Close","raw":false,"className":"","name":"","x":910,"y":320,"wires":[]},{"id":"d028c878350d19e1","type":"ui-form","z":"7ac3890dfa74703b","g":"342f3ee215d32fdc","name":"Income Submission Form","group":"961528943e1bb698","label":"","order":1,"width":"0","height":"0","options":[{"label":"Date","key":"date","type":"date","required":true,"rows":null},{"label":"Description","key":"description","type":"text","required":true,"rows":null},{"label":"Amount","key":"amount","type":"number","required":true,"rows":null},{"label":"Note","key":"note","type":"text","required":false,"rows":null}],"formValue":{"date":"","description":"","amount":"","note":""},"payload":"","submit":"submit","cancel":"clear","resetOnSubmit":true,"topic":"topic","topicType":"msg","splitLayout":"","className":"","x":410,"y":200,"wires":[["5ba5d8bff1a77bea"]]},{"id":"43e79bb77d718c95","type":"ui-notification","z":"7ac3890dfa74703b","g":"342f3ee215d32fdc","ui":"a0a85a5f4c29af50","position":"center center","colorDefault":true,"color":"#000000","displayTime":"3","showCountdown":true,"outputs":0,"allowDismiss":true,"dismissText":"Close","raw":false,"className":"","name":"","x":910,"y":200,"wires":[]},{"id":"5ba5d8bff1a77bea","type":"function","z":"7ac3890dfa74703b","g":"342f3ee215d32fdc","name":"Store income","func":"let income = global.get('income') || [];\n\nincome.push({\n ...msg.payload,\n type:\"income\",\n});\n\nglobal.set('income', income);\n\nmsg.payload = \"Thank you for submitting income!\"\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":200,"wires":[["43e79bb77d718c95"]]},{"id":"424b35900722e740","type":"ui-chart","z":"7ac3890dfa74703b","g":"e6ee60438b20dc44","group":"54eca83feb7c1479","name":"Overview Chart","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"amount","ymin":"","ymax":"","action":"append","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1eb33c","#aec7e8","#ff7f0e","#5f2ed1","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"12","height":"6","className":"","x":760,"y":560,"wires":[[]]},{"id":"f21a87c5c5aec0b2","type":"function","z":"7ac3890dfa74703b","g":"e6ee60438b20dc44","name":"Calculate the total income and expenses.","func":"// Get income and expense arrays from global context, or set them as empty arrays if not found\nlet income = global.get('income') || [];\nlet expense = global.get('expense') || [];\n\n// Initialize an empty result array\nlet result = [];\n\n// Send an empty payload to reset chart\nnode.send({ payload: [] });\n\n// Calculate total income by summing up amounts in the income array\nlet totalIncome = income.reduce((sum, item) => sum + parseFloat(item.amount), 0);\nresult.push({ category: \"Income\", amount: totalIncome });\n\n// Calculate total expense by summing up amounts in the expense array\nlet totalExpense = expense.reduce((sum, item) => sum + parseFloat(item.amount), 0);\nresult.push({ category: \"Expense\", amount: totalExpense });\n\n// Set the result array as the payload of the message\nmsg.payload = result;\n\n// Return the message\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":560,"wires":[["424b35900722e740"]]},{"id":"452d561bf79727cb","type":"ui-table","z":"7ac3890dfa74703b","g":"77217e256ef75328","group":"e848a5e48a6549c9","name":"","label":"text","order":2,"width":0,"height":0,"maxrows":0,"passthru":false,"autocols":true,"selectionType":"click","columns":[],"x":770,"y":440,"wires":[[]]},{"id":"301c1fd8e29c3aae","type":"ui-template","z":"7ac3890dfa74703b","group":"","page":"","ui":"a0a85a5f4c29af50","name":"Footer","order":0,"width":0,"height":0,"head":"","format":"\n\n","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"widget:ui","className":"","x":530,"y":660,"wires":[[]]},{"id":"0c64567c81dd6a8d","type":"change","z":"7ac3890dfa74703b","g":"77217e256ef75328","name":"Merge income and expense data","rules":[{"t":"set","p":"payload","pt":"msg","to":"[ $globalContext(\"income\"),\t $globalContext(\"expense\")\t]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":440,"wires":[["452d561bf79727cb"]]},{"id":"bd90a9ad612408d3","type":"function","z":"7ac3890dfa74703b","g":"4afb4814be56a9a8","name":"Store expense","func":"let expense = global.get('expense') || [];\n\nexpense.push({\n ...msg.payload,\n type: \"expense\",\n});\n\nglobal.set('expense', expense);\n\nmsg.payload = \"Thank you for submitting expense!\"\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":640,"y":320,"wires":[["3457848652ad75e1"]]},{"id":"9ce6db04b2c9d7b2","type":"ui-event","z":"7ac3890dfa74703b","g":"1b78769d6d27d102","ui":"a0a85a5f4c29af50","name":"","x":130,"y":500,"wires":[["0c64567c81dd6a8d","f21a87c5c5aec0b2"]]},{"id":"854706651cd8a8f2","type":"ui-group","name":"Expense Submission Form","page":"97bf3e87f4bdddc1","width":"12","height":"1","order":2,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"a0a85a5f4c29af50","type":"ui-base","name":"Dashboard","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control","ui-chart","ui-table"],"showPathInSidebar":false,"navigationStyle":"icon"},{"id":"961528943e1bb698","type":"ui-group","name":"Income Submission Form","page":"d954d73f9dcd1472","width":"12","height":"1","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"54eca83feb7c1479","type":"ui-group","name":"Overview","page":"47bde79e946933d2","width":"12","height":"4","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"e848a5e48a6549c9","type":"ui-group","name":"Your Income and Expense","page":"7abf0b3cb6f38ca3","width":"12","height":"5","order":2,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"97bf3e87f4bdddc1","type":"ui-page","name":"New Expense","ui":"a0a85a5f4c29af50","path":"/new-expense","icon":"bank-transfer-out","layout":"notebook","theme":"aeeec3fc1077eb1c","order":2,"className":"","visible":"true","disabled":"false"},{"id":"d954d73f9dcd1472","type":"ui-page","name":"New Income","ui":"a0a85a5f4c29af50","path":"/new-Icome","icon":"bank-transfer-in","layout":"notebook","theme":"aeeec3fc1077eb1c","order":1,"className":"","visible":"true","disabled":"false"},{"id":"47bde79e946933d2","type":"ui-page","name":"Overview","ui":"a0a85a5f4c29af50","path":"/overview","icon":"google-analytics","layout":"notebook","theme":"aeeec3fc1077eb1c","order":-1,"className":"","visible":"true","disabled":"false"},{"id":"7abf0b3cb6f38ca3","type":"ui-page","name":"Your Income and expense","ui":"a0a85a5f4c29af50","path":"/your-icome-expense","icon":"calendar-multiple-check","layout":"grid","theme":"aeeec3fc1077eb1c","order":3,"className":"","visible":"true","disabled":"false"},{"id":"aeeec3fc1077eb1c","type":"ui-theme","name":"dashboard","colors":{"surface":"#1a1a1a","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}] +{% endrenderFlow %} + + 1. Deploy the flow by clicking the top right **Deploy** button. 2. Locate the ***Open Dashboard** button at the top-right corner of the Dashboard 2.0 sidebar and click on it to navigate to the dashboard.