Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

notification ui node enhancements #932

Merged
merged 17 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions docs/nodes/widgets/ui-notification.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,52 @@ description: Notify users of important updates and alerts with ui-notification i
props:
UI: Unlike most widgets, notifications are owned by a "UI", not Group. This allows for notifications to be displayed across all pages.
Position: The position on the screen whethere the notification will appear.
Color: The color that should be used for the notification border.
Timeout: Number of seconds before the notification will automatically close.
Show Countdown Bar: Whether or not to show a reducing progfress bar to indicate the time remaining before the notification will close.
Show Countdown Bar: Whether or not to show a reducing progress bar to indicate the time remaining before the notification will close.
Allow Manual Dismissal: Whether or not to show a button that will allow the user to dismiss the notification. Otherwise, will only close after Timeout.
Button Label: If "Allow Manual Dismissal" is enabled, this is the label for the button.
Allow Manual Confirmation: Whether or not to show a button that will allow the user to confirm the notification. Otherwise, will only close after Timeout.
Button Label: If "Allow Manual Confirmation" is enabled, this is the label for the button.
Accept Raw: Whether you're passing in raw HTML that should be processed client-side.
Class: Appends CSS classes to the widget
dynamic:
Disabled State:
payload: msg.enabled
structure: ["Boolean"]
Allow confirmation:
payload: msg.ui_update.allowConfirm
structure: ["Boolean"]
Allow dismissal:
payload: msg.ui_update.allowDismiss
structure: ["Boolean"]
Color:
payload: msg.ui_update.color
structure: ["String"]
Confirmation button text:
payload: msg.ui_update.confirmText
structure: ["String"]
Dismissal button text:
payload: msg.ui_update.dismissText
structure: ["String"]
Display time(out):
payload: msg.ui_update.displayTime
structure: ["Number"]
Position:
payload: msg.ui_update.position
structure: ["top right", "top center", "top left", "bottom right", "bottom center", "bottom left", "center center"]
Progress bar color:
payload: msg.ui_update.progressColor
structure: ["String"]
Accept raw html:
payload: msg.ui_update.raw
structure: ["Boolean"]
Show:
payload: msg.ui_update.show
structure: ["Boolean"]
Show countdown bar:
payload: msg.ui_update.showCountdown
structure: ["Boolean"]
---

<script setup>
Expand All @@ -22,12 +62,16 @@ props:

Known in Dashboard 1.0 as a "Toast", this widget displays text/HTML in a small window that will appear on the screen for a defined duration of time (`timeout`) and at a defined location on the screen (`position`).

If you want to have the notification show indefinitely, you can set `timeout` to `0`. It will not be possible to close the notification manually unless you also set `allowDismiss` to `true`.
If you want to have the notification show indefinitely, you can set `timeout` to `0`. It will not be possible to close the notification manually unless you also set `allowDismiss` or `allowConfirm` to `true`.

## Properties

<PropsTable/>

## Dynamic Properties

<DynamicPropsTable/>

## Example

![Example of rendered Notification](/images/node-examples/ui-notification.png "Example of rendered Notification"){data-zoomable}
Expand All @@ -37,4 +81,4 @@ This notification was created using a `msg.payload` of:

```html
<h3>Generated Notification</h3><p>This is custom HTML injected into <b>Node-RED</b></p>
```
```
80 changes: 80 additions & 0 deletions nodes/widgets/locales/en-US/ui_notification.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<script type="text/html" data-help-name="ui-notification">
<p>
Displays text/HTML in a small window, that will appear on the screen
a defined duration of time(out) at a defined location.
</p>
<p>
Each received <code>msg.payload</code> will update the value shown
inside the notification dialog (and the notification will be displayed).
</p>
<h3>Properties</h3>
<dl class="message-properties">
<dt>Position <span class="property-type">list</span></dt>
<dd>The position on the screen whethere the notification will appear.</dd>
<dt>Color <span class="property-type">color</span></dt>
<dd>The color that should be used for the notification border.</dd>
<dt>Timeout <span class="property-type">number</span></dt>
<dd>Number of seconds before the notification will automatically close.</dd>
<dt>Show Countdown Bar <span class="property-type">boolean</span></dt>
<dd>Whether or not to show a reducing progress bar to indicate the time remaining.</dd>
<dt>Allow Manual Dismissal <span class="property-type">boolean</span></dt>
<dd>Whether or not to show a button that will allow the user to dismiss the notification.</dd>
<dt>Allow Manual Confirmation <span class="property-type">boolean</span></dt>
<dd>Whether or not to show a button that will allow the user to confirm the notification.</dd>
<dt>Accept Raw <span class="property-type">boolean</span></dt>
<dd>Whether you're passing in raw HTML that should be processed client-side.</dd>
</dl>
<h3>Dynamic Properties (Inputs)</h3>
<p>Any of the following can be appended to a <code>msg.ui_update</code> in order to override or set properties on this node at runtime.</p>
<dl class="message-properties">
<dt class="optional">allowConfirm<span class="property-type">boolean</span></dt>
<dd>Whether or not to show a button that will allow the user to confirm the notification.</dd>
</dl>
<dl class="message-properties">
<dt class="optional">allowDismiss<span class="property-type">boolean</span></dt>
<dd>Whether or not to show a button that will allow the user to dismiss the notification.</dd>
</dl>
<dl class="message-properties">
<dt class="optional">color<span class="property-type">string</span></dt>
<dd>The color that should be used for the notification border.</dd>
</dl>
<dl class="message-properties">
<dt class="optional">confirmText<span class="property-type">string</span></dt>
<dd>The text that will displayed on the confirmation button.</dd>
</dl>
<dl class="message-properties">
<dt class="optional">dismissText<span class="property-type">string</span></dt>
<dd>The text that will displayed on the dismiss button.</dd>
</dl>
<dl class="message-properties">
<dt class="optional">displayTime<span class="property-type">number</span></dt>
<dd>Number of seconds before the notification will automatically close. Note: this needs to be overridden before the notification becomes visible!</dd>
</dl>
<dl class="message-properties">
<dt class="optional">position<span class="property-type">string</span></dt>
<dd>
The position on the screen whethere the notification will appear.
<ul>
<li><code>top right</code></li>
<li><code>top center</code></li>
<li><code>top left</code></li>
<li><code>bottom right</code></li>
<li><code>bottom center</code></li>
<li><code>bottom left</code></li>
<li><code>center center</code></li>
</ul>
</dd>
</dl>
<dl class="message-properties">
<dt class="optional">raw<span class="property-type">boolean</span></dt>
<dd>Whether you're passing in raw HTML that should be processed client-side.</dd>
</dl>
<dl class="message-properties">
<dt class="optional">show<span class="property-type">boolean</span></dt>
<dd>Whether you want to show (even when no <code>msg.payload</code> available) or hide the notification.</dd>
</dl>
<dl class="message-properties">
<dt class="optional">showCountdown<span class="property-type">boolean</span></dt>
<dd>Whether or not to show a reducing progress bar to indicate the time remaining.</dd>
</dl>
</script>
21 changes: 20 additions & 1 deletion nodes/widgets/ui_notification.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
displayTime: { value: '3' },
showCountdown: { value: true },
outputs: { value: 1 },
allowDismiss: { value: 'OK' },
allowDismiss: { value: true },
dismissText: { value: 'Close' },
allowConfirm: { value: false },
confirmText: { value: 'Confirm' },
raw: { value: false },
className: { value: '' },
name: { value: '' }
Expand Down Expand Up @@ -50,6 +52,15 @@
}
})

$('#node-input-allowConfirm').on('change', function () {
const allowConfirm = $('#node-input-allowConfirm').is(':checked')
if (allowConfirm) {
$('#node-notification-confirmText').show()
} else {
$('#node-notification-confirmText').hide()
}
})

$('#node-input-colorDefault').on('change', function () {
const defaultColor = $('#node-input-colorDefault').is(':checked')
if (defaultColor) {
Expand Down Expand Up @@ -116,6 +127,14 @@
<label for="node-input-dismissText"><i class="fa fa-check"></i> Button Label</label>
<input type="text" id="node-input-dismissText" placeholder="Close">
</div>
<div class="form-row form-row-flex" id="node-notification-allowConfirm">
<input type="checkbox" id="node-input-allowConfirm">
<label for="node-input-allowConfirm"> Allow Manual Confirmation</label>
</div>
<div class="form-row form-row-flex" style="margin-left: 32px;" id="node-notification-confirmText">
<label for="node-input-confirmText"><i class="fa fa-check"></i> Button Label</label>
<input type="text" id="node-input-confirmText" placeholder="Confirm">
</div>
<div class="form-row form-row-flex" id="node-toast-raw">
<input type="checkbox" id="node-input-raw" style="display:inline-block; width:auto; vertical-align:baseline;">
<label style="width:auto" for="node-input-raw"> Accept raw HTML/JavaScript input in msg.payload to format popup.</label>
Expand Down
60 changes: 58 additions & 2 deletions nodes/widgets/ui_notification.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,70 @@
const statestore = require('../store/state.js')

module.exports = function (RED) {
function NotificationNode (config) {
const node = this

RED.nodes.createNode(this, config)

// which group are we rendering this widget
// Which ui are we rendering this widget.
// In contradiction to other ui nodes (which belong to a group), the notification node belongs to a ui instead.
const ui = RED.nodes.getNode(config.ui)

const evts = {
onAction: true,
beforeSend: function (msg) {
if (msg.ui_update) {
const updates = msg.ui_update

const allowedPositions = ['top right', 'top center', 'top left', 'bottom right', 'bottom center', 'bottom left', 'center center']

if (updates) {
if (typeof updates.allowConfirm !== 'undefined') {
// dynamically set "allowConfirm" property
statestore.set(ui, node, msg, 'allowConfirm', updates.allowConfirm)
}
if (typeof updates.allowDismiss !== 'undefined') {
// dynamically set "allowDismiss" property
statestore.set(ui, node, msg, 'allowDismiss', updates.allowDismiss)
}
if (typeof updates.color !== 'undefined') {
// dynamically set "color" property
statestore.set(ui, node, msg, 'color', updates.color)
}
if (typeof updates.confirmText !== 'undefined') {
// dynamically set "confirmText" property
statestore.set(ui, node, msg, 'confirmText', updates.confirmText)
}
if (typeof updates.dismissText !== 'undefined') {
// dynamically set "dismissText" property
statestore.set(ui, node, msg, 'dismissText', updates.dismissText)
}
if (typeof updates.displayTime !== 'undefined') {
// dynamically set "displayTime" property
statestore.set(ui, node, msg, 'displayTime', updates.displayTime)
}
if (typeof updates.position !== 'undefined' && allowedPositions.includes(updates.position)) {
// dynamically set "position" property
statestore.set(ui, node, msg, 'position', updates.position)
}
if (typeof updates.raw !== 'undefined') {
// dynamically set "raw" property
statestore.set(ui, node, msg, 'raw', updates.raw)
}
if (typeof updates.showCountdown !== 'undefined') {
// dynamically set "showCountdown" property
statestore.set(ui, node, msg, 'showCountdown', updates.showCountdown)
}
// Note that update.close will NOT be stored in the data store,
// since it does not need to be remembered
}
}
return msg
}
}

// inform the dashboard UI that we are adding this node
ui.register(null, null, node, config)
ui.register(null, null, node, config, evts)
}
RED.nodes.registerType('ui-notification', NotificationNode)
}
Loading
Loading