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

Dynamic ui-template #1475

Merged
merged 6 commits into from
Dec 6, 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
9 changes: 9 additions & 0 deletions docs/nodes/widgets/ui-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ props:
Scope: "Template nodes can be used for 3 purposes/scopes: <ul><li><b>Widget (Group-Scoped):</b>A standard HTML/Vue widget rendered in a group in the Dashboard.</li><li><b>Widget (Page-Scoped):</b>A HTML/Vue widget that will render on a page, outside of any existing groups. Note that these widgets will render after any Groups. An example use case for this would be if you wanted to have a fixed footer on a given page.</li><li><b>Widget (UI-Scoped):</b>A HTML/Vue widget rendered on every page of the Dashboard. Most commonly used in conjunction with <a href=\"#teleports\">Teleports</a></li><li><b>CSS (All Pages):</b>Define custom CSS classes/styling that applies to the entire Dashboard.</li><li><b>CSS (Single Page):</b>Define custom CSS classes/styling that applies just a single page of your Dashboard.</li></ul>"
Class: Appends CSS classes to the widget
Template: The content of the widget or CSS &lt;style&gt;. If using this for CSS, you do not need to include any &lt;style&gt; tags, as these will be automatically added.
dynamic:
Format:
payload: msg.ui_update.format
structure: ["String"]
---

<script setup>
Expand All @@ -30,6 +34,10 @@ Provide custom JS and HTML (including any [Vuetify components](https://vuetifyjs

<PropsTable/>

## Dynamic Properties

<DynamicPropsTable/>

## Writing Custom Widgets

UI Template will parse different tags and render them into Dashboard. The available tags are:
Expand Down Expand Up @@ -476,3 +484,4 @@ Some example widgets that you may find useful are:
### Articles & Tutorials

- [Building a Custom Video Player with UI Template](https://flowfuse.com/blog/2023/12/dashboard-0-10-0/)

3 changes: 1 addition & 2 deletions nodes/widgets/locales/en-US/ui_template.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

<script type="text/markdown" data-help-name="ui-template">
(see [full docs](https://dashboard.flowfuse.com/nodes/widgets/ui-template.html))

Expand Down Expand Up @@ -150,4 +149,4 @@
}
```

</script>
</script>
43 changes: 30 additions & 13 deletions nodes/widgets/ui_template.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
const statestore = require('../store/state.js')

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

// create node in Node-RED
RED.nodes.createNode(this, config)

const evts = {
onAction: true // TODO: think we need an onSend event for template nodes that matches up with a `widget-send` message
}

if (config.templateScope === 'local') {
config.page = ''
config.ui = ''
Expand All @@ -31,18 +29,37 @@ module.exports = function (RED) {
config.passthru = true
}

// which group are we rendering this widget
// determine which group/page/ui are we rendering this widget
let group, page, ui
if (config.group) {
const group = RED.nodes.getNode(config.group)
// inform the dashboard UI that we are adding this node
group.register(node, config, evts)
group = RED.nodes.getNode(config.group)
} else if (config.page) {
const page = RED.nodes.getNode(config.page)
// inform the dashboard UI that we are adding this node
page.register(null, node, config, evts)
page = RED.nodes.getNode(config.page)
} else if (config.ui) {
const ui = RED.nodes.getNode(config.ui)
// inform the dashboard UI that we are adding this node
ui = RED.nodes.getNode(config.ui)
}

const evts = {
onAction: true, // TODO: think we need an onSend event for template nodes that matches up with a `widget-send` message
beforeSend: function (msg) {
if (msg.ui_update) {
const update = msg.ui_update
if (typeof update.format !== 'undefined') {
// dynamically set "format" property
const parent = group || page || ui
statestore.set(parent.getBase(), node, msg, 'format', update.format)
}
}
return msg
}
}

// inform the dashboard group/page/ui that we are adding this node
if (group) {
group.register(node, config, evts)
} else if (page) {
page.register(null, node, config, evts)
} else if (ui) {
ui.register(null, null, node, config, evts)
}
}
Expand Down
Loading
Loading