@flowfuse/node-red-dashboard 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +53 -0
- package/dist/css/app.d047b42b.css +1 -0
- package/dist/css/chunk-vendors.2378ce49.css +24 -0
- package/dist/fonts/materialdesignicons-webfont.3de8526e.woff +0 -0
- package/dist/fonts/materialdesignicons-webfont.477c6ab0.woff2 +0 -0
- package/dist/fonts/materialdesignicons-webfont.48a1ce0c.eot +0 -0
- package/dist/fonts/materialdesignicons-webfont.dfd403cf.ttf +0 -0
- package/dist/index.html +1 -0
- package/dist/js/app.854a8cd5.js +2 -0
- package/dist/js/app.854a8cd5.js.map +1 -0
- package/dist/js/chunk-vendors.174e8921.js +43 -0
- package/dist/js/chunk-vendors.174e8921.js.map +1 -0
- package/nodes/config/locales/en-US/ui_base.json +19 -0
- package/nodes/config/locales/en-US/ui_group.html +4 -0
- package/nodes/config/locales/en-US/ui_group.json +16 -0
- package/nodes/config/ui_base.html +807 -0
- package/nodes/config/ui_base.js +678 -0
- package/nodes/config/ui_group.html +55 -0
- package/nodes/config/ui_group.js +34 -0
- package/nodes/config/ui_page.html +84 -0
- package/nodes/config/ui_page.js +33 -0
- package/nodes/config/ui_theme.html +101 -0
- package/nodes/config/ui_theme.js +15 -0
- package/nodes/store/index.js +34 -0
- package/nodes/utils/index.js +35 -0
- package/nodes/widgets/locales/en-US/ui_button.html +7 -0
- package/nodes/widgets/locales/en-US/ui_button.json +24 -0
- package/nodes/widgets/locales/en-US/ui_chart.html +41 -0
- package/nodes/widgets/locales/en-US/ui_chart.json +17 -0
- package/nodes/widgets/locales/en-US/ui_dropdown.html +24 -0
- package/nodes/widgets/locales/en-US/ui_form.html +16 -0
- package/nodes/widgets/locales/en-US/ui_form.json +36 -0
- package/nodes/widgets/locales/en-US/ui_markdown.html +10 -0
- package/nodes/widgets/locales/en-US/ui_slider.html +9 -0
- package/nodes/widgets/locales/en-US/ui_switch.html +32 -0
- package/nodes/widgets/locales/en-US/ui_template.html +59 -0
- package/nodes/widgets/locales/en-US/ui_template.json +18 -0
- package/nodes/widgets/locales/en-US/ui_text.html +16 -0
- package/nodes/widgets/locales/en-US/ui_text_input.html +19 -0
- package/nodes/widgets/ui_button.html +146 -0
- package/nodes/widgets/ui_button.js +65 -0
- package/nodes/widgets/ui_chart.html +314 -0
- package/nodes/widgets/ui_chart.js +195 -0
- package/nodes/widgets/ui_dropdown.html +199 -0
- package/nodes/widgets/ui_dropdown.js +19 -0
- package/nodes/widgets/ui_form.html +368 -0
- package/nodes/widgets/ui_form.js +18 -0
- package/nodes/widgets/ui_markdown.html +134 -0
- package/nodes/widgets/ui_markdown.js +14 -0
- package/nodes/widgets/ui_notification.html +139 -0
- package/nodes/widgets/ui_notification.js +14 -0
- package/nodes/widgets/ui_radio_group.html +186 -0
- package/nodes/widgets/ui_radio_group.js +20 -0
- package/nodes/widgets/ui_slider.html +162 -0
- package/nodes/widgets/ui_slider.js +31 -0
- package/nodes/widgets/ui_switch.html +194 -0
- package/nodes/widgets/ui_switch.js +98 -0
- package/nodes/widgets/ui_table.html +149 -0
- package/nodes/widgets/ui_table.js +16 -0
- package/nodes/widgets/ui_template.html +283 -0
- package/nodes/widgets/ui_template.js +19 -0
- package/nodes/widgets/ui_text.html +358 -0
- package/nodes/widgets/ui_text.js +98 -0
- package/nodes/widgets/ui_text_input.html +141 -0
- package/nodes/widgets/ui_text_input.js +37 -0
- package/package.json +114 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('ui-group', {
|
|
3
|
+
category: 'config',
|
|
4
|
+
defaults: {
|
|
5
|
+
name: {
|
|
6
|
+
value: 'Group Name',
|
|
7
|
+
required: true
|
|
8
|
+
},
|
|
9
|
+
page: { type: 'ui-page', required: true },
|
|
10
|
+
width: { value: 6 },
|
|
11
|
+
height: { value: 1 },
|
|
12
|
+
order: { value: -1 },
|
|
13
|
+
disp: { value: true }, // show title on group card
|
|
14
|
+
className: { value: '' }
|
|
15
|
+
},
|
|
16
|
+
label: function () {
|
|
17
|
+
const page = RED.nodes.node(this.page)?.name || ''
|
|
18
|
+
return `${this.name} [${page}]` || 'UI Group'
|
|
19
|
+
},
|
|
20
|
+
oneditprepare: function () {
|
|
21
|
+
$('#node-config-input-size').elementSizer({
|
|
22
|
+
width: '#node-config-input-width',
|
|
23
|
+
height: '#node-config-input-height',
|
|
24
|
+
auto: false
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<script type="text/html" data-template-name="ui-group">
|
|
31
|
+
<div class="form-row">
|
|
32
|
+
<label for="node-config-input-name"><i class="fa fa-bookmark"></i> Name</label>
|
|
33
|
+
<input type="text" id="node-config-input-name">
|
|
34
|
+
</div>
|
|
35
|
+
<div class="form-row">
|
|
36
|
+
<label for="node-config-input-page"><i class="fa fa-bookmark"></i> Page</label>
|
|
37
|
+
<input type="text" id="node-config-input-page">
|
|
38
|
+
</div>
|
|
39
|
+
<div class="form-row">
|
|
40
|
+
<label for="node-config-input-size"><i class="fa fa-arrows-h"></i> Size</label>
|
|
41
|
+
<input type="hidden" id="node-config-input-width">
|
|
42
|
+
<input type="hidden" id="node-config-input-height">
|
|
43
|
+
<button class="editor-button" id="node-config-input-size"></button>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="form-row">
|
|
46
|
+
<input style="margin:8px 0 10px 102px; width:20px;" type="checkbox" checked id="node-config-input-disp"> <label style="width:auto" for="node-config-input-disp"><span data-i18n="ui-group.display-name"></span></label>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="form-row" id="text-row-class">
|
|
49
|
+
<label for="node-config-input-className"><i class="fa fa-code"></i> Class</label>
|
|
50
|
+
<input type="text" id="node-config-input-className" placeholder="Optional CSS class name(s) for group"/>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="form-row">
|
|
53
|
+
<button onclick="RED.sidebar.show('dashboard-2.0')" class="editor-button editor-button-small">Open Dashboard 2.0 Sidebar</button>
|
|
54
|
+
</div>
|
|
55
|
+
</script>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {*} config
|
|
5
|
+
*/
|
|
6
|
+
function UIGroupNode (config) {
|
|
7
|
+
RED.nodes.createNode(this, config)
|
|
8
|
+
const node = this
|
|
9
|
+
|
|
10
|
+
node.on('close', function (removed, done) {
|
|
11
|
+
node.deregister() // deregister self
|
|
12
|
+
done()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Function for widgets to register themselves with this page
|
|
17
|
+
* Calls the parent UI Base "register" function and registers this page,
|
|
18
|
+
* along with the widget
|
|
19
|
+
* @param {*} widget
|
|
20
|
+
*/
|
|
21
|
+
node.register = function (widgetNode, widgetConfig, widgetEvents) {
|
|
22
|
+
const page = RED.nodes.getNode(config.page)
|
|
23
|
+
const group = config
|
|
24
|
+
page.register(group, widgetNode, widgetConfig, widgetEvents)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
node.deregister = function (widgetNode) {
|
|
28
|
+
const page = RED.nodes.getNode(config.page)
|
|
29
|
+
const group = config
|
|
30
|
+
page.deregister(group, widgetNode)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
RED.nodes.registerType('ui-group', UIGroupNode)
|
|
34
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('ui-page', {
|
|
3
|
+
category: 'config',
|
|
4
|
+
defaults: {
|
|
5
|
+
name: {
|
|
6
|
+
value: 'Page Name',
|
|
7
|
+
required: true
|
|
8
|
+
},
|
|
9
|
+
ui: {
|
|
10
|
+
type: 'ui-base',
|
|
11
|
+
value: '',
|
|
12
|
+
required: true
|
|
13
|
+
},
|
|
14
|
+
path: {
|
|
15
|
+
value: '/',
|
|
16
|
+
required: false
|
|
17
|
+
},
|
|
18
|
+
layout: {
|
|
19
|
+
value: '',
|
|
20
|
+
required: true
|
|
21
|
+
},
|
|
22
|
+
theme: {
|
|
23
|
+
type: 'ui-theme',
|
|
24
|
+
value: 'default',
|
|
25
|
+
required: true
|
|
26
|
+
},
|
|
27
|
+
order: {
|
|
28
|
+
value: -1
|
|
29
|
+
},
|
|
30
|
+
className: { value: '' }
|
|
31
|
+
},
|
|
32
|
+
oneditprepare: function () {
|
|
33
|
+
$('#node-config-input-layout').typedInput({
|
|
34
|
+
type: 'layout',
|
|
35
|
+
types: [{
|
|
36
|
+
value: 'layout',
|
|
37
|
+
options: [
|
|
38
|
+
{ value: 'grid', label: 'Grid' },
|
|
39
|
+
{ value: 'flex', label: 'Fixed' },
|
|
40
|
+
{ value: 'notebook', label: 'Notebook' }
|
|
41
|
+
]
|
|
42
|
+
}],
|
|
43
|
+
typeField: '#node-input-layoutType'
|
|
44
|
+
})
|
|
45
|
+
},
|
|
46
|
+
label: function () {
|
|
47
|
+
const baseNode = RED.nodes.node(this.ui)
|
|
48
|
+
const base = baseNode ? baseNode.path : '/'
|
|
49
|
+
const path = this.path || ''
|
|
50
|
+
return `${this.name} [${base}${path}]` || 'UI Page'
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<script type="text/html" data-template-name="ui-page">
|
|
56
|
+
<div class="form-row">
|
|
57
|
+
<label for="node-config-input-name"><i class="fa fa-bookmark"></i> Name</label>
|
|
58
|
+
<input type="text" id="node-config-input-name">
|
|
59
|
+
</div>
|
|
60
|
+
<div class="form-row">
|
|
61
|
+
<label for="node-config-input-ui"><i class="fa fa-bookmark"></i> UI</label>
|
|
62
|
+
<input type="text" id="node-config-input-ui">
|
|
63
|
+
</div>
|
|
64
|
+
<div class="form-row">
|
|
65
|
+
<label for="node-config-input-path"><i class="fa fa-bookmark"></i> Path</label>
|
|
66
|
+
<input type="text" id="node-config-input-path">
|
|
67
|
+
</div>
|
|
68
|
+
<div class="form-row">
|
|
69
|
+
<label for="node-config-input-theme"><i class="fa fa-bookmark"></i> Theme</label>
|
|
70
|
+
<input type="text" id="node-config-input-theme">
|
|
71
|
+
</div>
|
|
72
|
+
<div class="form-row">
|
|
73
|
+
<label for="node-config-input-layout"><i class="fa fa-bookmark"></i> Layout</label>
|
|
74
|
+
<input type="text" id="node-config-input-layout">
|
|
75
|
+
<input type="hidden" id="node-config-input-layoutType">
|
|
76
|
+
</div>
|
|
77
|
+
<div class="form-row" id="text-row-class">
|
|
78
|
+
<label for="node-config-input-className"><i class="fa fa-code"></i> Class</label>
|
|
79
|
+
<input type="text" id="node-config-input-className" placeholder="Optional CSS class name(s) for page"/>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="form-row">
|
|
82
|
+
<button onclick="RED.sidebar.show('dashboard-2.0')" class="editor-button editor-button-small">Open Dashboard 2.0 Sidebar</button>
|
|
83
|
+
</div>
|
|
84
|
+
</script>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {*} config
|
|
5
|
+
*/
|
|
6
|
+
function UIPageNode (config) {
|
|
7
|
+
RED.nodes.createNode(this, config)
|
|
8
|
+
const node = this
|
|
9
|
+
|
|
10
|
+
node.on('close', function (removed, done) {
|
|
11
|
+
node.deregister() // deregister self
|
|
12
|
+
done()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Function for widgets to register themselves with this page
|
|
17
|
+
* Calls the parent UI Base "register" function and registers this page,
|
|
18
|
+
* along with the widget
|
|
19
|
+
* @param {*} widget
|
|
20
|
+
*/
|
|
21
|
+
node.register = function (group, widgetNode, widgetConfig, widgetEvents) {
|
|
22
|
+
const ui = RED.nodes.getNode(config.ui)
|
|
23
|
+
const page = config
|
|
24
|
+
ui.register(page, group, widgetNode, widgetConfig, widgetEvents)
|
|
25
|
+
}
|
|
26
|
+
node.deregister = function (group, widgetNode) {
|
|
27
|
+
const ui = RED.nodes.getNode(config.ui)
|
|
28
|
+
const page = config
|
|
29
|
+
ui.deregister(page, group, widgetNode)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
RED.nodes.registerType('ui-page', UIPageNode)
|
|
33
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('ui-theme', {
|
|
3
|
+
category: 'config',
|
|
4
|
+
defaults: {
|
|
5
|
+
name: {
|
|
6
|
+
value: 'Theme Name',
|
|
7
|
+
required: true
|
|
8
|
+
},
|
|
9
|
+
// colors
|
|
10
|
+
colors: {
|
|
11
|
+
value: null
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
oneditprepare: function () {
|
|
15
|
+
if (!this.colors) {
|
|
16
|
+
this.colors = {}
|
|
17
|
+
// set default values
|
|
18
|
+
this.colors.surface = '#ffffff'
|
|
19
|
+
this.colors.primary = '#0094CE'
|
|
20
|
+
// pages
|
|
21
|
+
this.colors.bgPage = '#eeeeee'
|
|
22
|
+
// groups
|
|
23
|
+
this.colors.groupBg = '#ffffff'
|
|
24
|
+
this.colors.groupOutline = '#cccccc'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// loop over keys in this.colors
|
|
28
|
+
Object.keys(this.colors).forEach((color) => {
|
|
29
|
+
// get the value of the key
|
|
30
|
+
const value = this.colors[color]
|
|
31
|
+
// set the value of the input
|
|
32
|
+
$('#node-config-input-' + color).val(value)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
// update label b/g to match the colour input values
|
|
36
|
+
// this provides nicer styling than the default browser styling
|
|
37
|
+
const colorWrappers = $('.color-picker-wrapper')
|
|
38
|
+
colorWrappers.each(function (i) {
|
|
39
|
+
const wrapper = $(this)
|
|
40
|
+
const colorPicker = wrapper.children("input[type='color']").eq(0)
|
|
41
|
+
colorPicker.on('change', () => {
|
|
42
|
+
wrapper.css('background-color', colorPicker.val())
|
|
43
|
+
})
|
|
44
|
+
wrapper.css('background-color', colorPicker.val())
|
|
45
|
+
})
|
|
46
|
+
},
|
|
47
|
+
oneditsave: function () {
|
|
48
|
+
// update our config values from the input values
|
|
49
|
+
Object.keys(this.colors).forEach((color) => {
|
|
50
|
+
// set the value of the input
|
|
51
|
+
this.colors[color] = $('#node-config-input-' + color).val()
|
|
52
|
+
})
|
|
53
|
+
},
|
|
54
|
+
label: function () {
|
|
55
|
+
return `${this.name}` || 'UI Theme'
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<script type="text/html" data-template-name="ui-theme">
|
|
61
|
+
<div class="form-row">
|
|
62
|
+
<label for="node-config-input-name"><i class="fa fa-bookmark"></i> Name</label>
|
|
63
|
+
<input type="text" id="node-config-input-name">
|
|
64
|
+
</div>
|
|
65
|
+
<div class="form-row">
|
|
66
|
+
<label><i class="fa fa-bookmark"></i> Surface</label>
|
|
67
|
+
<label class="color-picker-wrapper" for="node-config-input-primary" style="width: 100px; height: 32px; border-radius: 6px; border: 1px solid #ccc">
|
|
68
|
+
<input type="color" id="node-config-input-surface" style="opacity: 0; width: 100%;"/>
|
|
69
|
+
</label>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="form-row">
|
|
72
|
+
<label><i class="fa fa-bookmark"></i> Primary</label>
|
|
73
|
+
<label class="color-picker-wrapper" for="node-config-input-primary" style="width: 100px; height: 32px; border-radius: 6px; border: 1px solid #ccc">
|
|
74
|
+
<input type="color" id="node-config-input-primary" style="opacity: 0; width: 100%;"/>
|
|
75
|
+
</label>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="form-row">
|
|
78
|
+
<h4 style="margin-bottom: 0;">Pages</h4>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="form-row">
|
|
81
|
+
<label><i class="fa fa-bookmark"></i> Background</label>
|
|
82
|
+
<label class="color-picker-wrapper" for="node-config-input-background" style="width: 100px; height: 32px; border-radius: 6px; border: 1px solid #ccc">
|
|
83
|
+
<input type="color" id="node-config-input-bgPage" style="opacity: 0; width: 100%;"/>
|
|
84
|
+
</label>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="form-row">
|
|
87
|
+
<h4 style="margin-bottom: 0;">Groups</h4>
|
|
88
|
+
</div>
|
|
89
|
+
<div class="form-row">
|
|
90
|
+
<label><i class="fa fa-bookmark"></i> Background</label>
|
|
91
|
+
<label class="color-picker-wrapper" for="node-config-input-background" style="width: 100px; height: 32px; border-radius: 6px; border: 1px solid #ccc">
|
|
92
|
+
<input type="color" id="node-config-input-groupBg" style="opacity: 0; width: 100%;"/>
|
|
93
|
+
</label>
|
|
94
|
+
</div>
|
|
95
|
+
<div class="form-row">
|
|
96
|
+
<label><i class="fa fa-bookmark"></i> Outline</label>
|
|
97
|
+
<label class="color-picker-wrapper" for="node-config-input-background" style="width: 100px; height: 32px; border-radius: 6px; border: 1px solid #ccc">
|
|
98
|
+
<input type="color" id="node-config-input-groupOutline" style="opacity: 0; width: 100%;"/>
|
|
99
|
+
</label>
|
|
100
|
+
</div>
|
|
101
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {*} config
|
|
5
|
+
*/
|
|
6
|
+
function UIThemeNode (config) {
|
|
7
|
+
RED.nodes.createNode(this, config)
|
|
8
|
+
const node = this
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line no-unused-vars
|
|
11
|
+
const { id, name, type, _users, ...rest } = config
|
|
12
|
+
node.colors = { ...rest.colors }
|
|
13
|
+
}
|
|
14
|
+
RED.nodes.registerType('ui-theme', UIThemeNode)
|
|
15
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const data = {}
|
|
2
|
+
|
|
3
|
+
const getters = {
|
|
4
|
+
// given a widget id, return the latest msg received
|
|
5
|
+
msg (id) {
|
|
6
|
+
return data[id]
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const setters = {
|
|
11
|
+
// remove data associated to a given widget
|
|
12
|
+
clear (id) {
|
|
13
|
+
delete data[id]
|
|
14
|
+
},
|
|
15
|
+
// given a widget id, and msg, store that latest value
|
|
16
|
+
save (id, msg) {
|
|
17
|
+
data[id] = msg
|
|
18
|
+
},
|
|
19
|
+
// given a widget id, and msg, store in an array of history of values
|
|
20
|
+
// useful for charting widgets
|
|
21
|
+
append (id, msg) {
|
|
22
|
+
if (!data[id]) {
|
|
23
|
+
data[id] = []
|
|
24
|
+
}
|
|
25
|
+
data[id].push(msg)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = {
|
|
30
|
+
get: getters.msg,
|
|
31
|
+
save: setters.save,
|
|
32
|
+
append: setters.append,
|
|
33
|
+
clear: setters.clear
|
|
34
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function asyncEvaluateNodeProperty (RED, value, type, node, msg) {
|
|
2
|
+
return new Promise(function (resolve, reject) {
|
|
3
|
+
RED.util.evaluateNodeProperty(value, type, node, msg, function (e, r) {
|
|
4
|
+
if (e) {
|
|
5
|
+
reject(e)
|
|
6
|
+
} else {
|
|
7
|
+
resolve(r)
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
|
+
})
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function appendTopic (RED, config, wNode, msg) {
|
|
14
|
+
// populate topic if the node specifies one
|
|
15
|
+
if (config.topic || config.topicType) {
|
|
16
|
+
try {
|
|
17
|
+
msg.topic = await asyncEvaluateNodeProperty(RED, config.topic, config.topicType || 'str', wNode, msg) || ''
|
|
18
|
+
} catch (_err) {
|
|
19
|
+
// do nothing
|
|
20
|
+
console.error(_err)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ensure we have a topic property in the msg, even if it's an empty string
|
|
25
|
+
if (!('topic' in msg)) {
|
|
26
|
+
msg.topic = ''
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return msg
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
asyncEvaluateNodeProperty,
|
|
34
|
+
appendTopic
|
|
35
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<script type="text/html" data-help-name="ui-button">
|
|
2
|
+
<p>Adds a button to the user interface.</p>
|
|
3
|
+
<p>
|
|
4
|
+
Clicking the button generates a message with <code>msg.payload</code>
|
|
5
|
+
set to the <b>Payload</b> field, and <code>msg.topic</code> to the <b>Topic</b> field.
|
|
6
|
+
</p>
|
|
7
|
+
</script>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui-button": {
|
|
3
|
+
"label": {
|
|
4
|
+
"group": "Group",
|
|
5
|
+
"size": "Size",
|
|
6
|
+
"icon": "Icon",
|
|
7
|
+
"optionalIcon": "optional icon",
|
|
8
|
+
"label": "Label",
|
|
9
|
+
"optionalLabel": "optional label",
|
|
10
|
+
"tooltip": "Tooltip",
|
|
11
|
+
"optionalTooltip": "optional tooltip",
|
|
12
|
+
"color": "Color",
|
|
13
|
+
"optionalColor": "optional text/icon color",
|
|
14
|
+
"background": "Background",
|
|
15
|
+
"optionalBackgroundColor": "optional background color",
|
|
16
|
+
"whenClicked": "When clicked, send:",
|
|
17
|
+
"payload": "Payload",
|
|
18
|
+
"topic": "Topic",
|
|
19
|
+
"emulateClick": "If msg arrives on input, emulate a button click:",
|
|
20
|
+
"className": "Class",
|
|
21
|
+
"classNamePlaceholder": "Optional CSS class name(s) for widget"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
<script type="text/html" data-help-name="ui-chart">
|
|
3
|
+
<h3>Properties</h3>
|
|
4
|
+
<dl class="message-properties">
|
|
5
|
+
<dt>Label <span class="property-type">str</span></dt>
|
|
6
|
+
<dd>Text shown above the rendered chart in the Dashboard.</dd>
|
|
7
|
+
<dt>Type <span class="property-type">line | bar | scatter</span></dt>
|
|
8
|
+
<dd>Choose the type of graph that you wish to render data with. Note
|
|
9
|
+
that different data structures are accepted for different chart types.</dd>
|
|
10
|
+
<dt>Show Legend <span class="property-type">bool</span></dt>
|
|
11
|
+
<dd>Defines whether or not a legend is shown between the title and the chart. Each label is driven by <code>msg.topic</code>.</dd>
|
|
12
|
+
<dt>X-Axis Type <span class="property-type">linear | categorical | time</span></dt>
|
|
13
|
+
<dd>
|
|
14
|
+
For charts with an x-axis, this option allows customisation
|
|
15
|
+
of the type of axis to render.
|
|
16
|
+
</dd>
|
|
17
|
+
<dt>Properties <span class="property-type">string</span></dt>
|
|
18
|
+
<dd>
|
|
19
|
+
<p><b>Series:</b> Controls how you want to set the Series of data stream into this widget. The default is <code>msg.topic</code>, where separate topics will render to a new line/bar in their respective plots.</p>
|
|
20
|
+
<p><b>X:</b> Only available for Line & Scatter Charts. This defines the key (which can be nested) of the value that should be plotted onto the x-axis. If left blank, the x-value will be calculated as the current timestamp.</p>
|
|
21
|
+
<p><b>Y:</b> Defines the key (which can be nested, e.g. <code>'nested.value'</code>) of the value that should be plotted onto the x-axis. This value is ignored if injecting single numerical values into the chart.</p>
|
|
22
|
+
</dd>
|
|
23
|
+
</dl>
|
|
24
|
+
<h3>Input</h3>
|
|
25
|
+
<p>Data can be passed into the Chart node in a variety of formats,
|
|
26
|
+
depending on the "X-Axis Type" (e.g. linear, categorical, time).</p>
|
|
27
|
+
<dl class="message-properties">
|
|
28
|
+
<dt>Numerical <span class="property-type">linear | categorical | time</span></dt>
|
|
29
|
+
<dd><pre>msg.payload = 5</pre> A single value, that will be plotted
|
|
30
|
+
in the y-axis, and the current time of injection as the x-value.</dd>
|
|
31
|
+
<dt>Series <span class="property-type">linear | categorical | time</span></dt>
|
|
32
|
+
<dd><pre>msg.topic = 'Series 1'</pre> Multiple series can
|
|
33
|
+
be shown on the same chart by using a different msg.topic value on each
|
|
34
|
+
input message.</dd>
|
|
35
|
+
<dt>Object <span class="property-type">linear</span></dt>
|
|
36
|
+
<dd><pre>msg.payload = {x: 10, y: 15}</pre>This type of data is only
|
|
37
|
+
supported on linear plots, e.g. "Line" or "Scatter" charts.</dd>
|
|
38
|
+
</dl>
|
|
39
|
+
<h3>Details</h3>
|
|
40
|
+
<p></p>
|
|
41
|
+
</script>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui-chart": {
|
|
3
|
+
"label": {
|
|
4
|
+
"seriesColors": "Series Colors",
|
|
5
|
+
"seconds": "Seconds",
|
|
6
|
+
"minutes": "Minutes",
|
|
7
|
+
"hours": "Hours",
|
|
8
|
+
"days": "Days",
|
|
9
|
+
"weeks": "Weeks",
|
|
10
|
+
"or": "OR",
|
|
11
|
+
"points": "points",
|
|
12
|
+
"xLimit": "X-Axis Limit",
|
|
13
|
+
"xType": "X-Axis Type",
|
|
14
|
+
"last": "last"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script type="text/html" data-help-name="ui-dropdown">
|
|
2
|
+
<p>
|
|
3
|
+
Adds a dropdown to your dashboard that will emit values
|
|
4
|
+
in Node-RED under `msg.payload` anytime it's value is changed.
|
|
5
|
+
</p>
|
|
6
|
+
<p>
|
|
7
|
+
In the case where a single option is selected, returns the object detailing that selection.
|
|
8
|
+
If "Allow multiple selections" is enabled, returns an array of objects detailing the selections.
|
|
9
|
+
</p>
|
|
10
|
+
<h3>Selecting Options via <code>msg.</code></h3>
|
|
11
|
+
<p>
|
|
12
|
+
You can dynamically make selections for this dropdown by passing in the respective <code>value</code> to <code>msg.payload</code>.
|
|
13
|
+
</p>
|
|
14
|
+
<p>
|
|
15
|
+
To make a single selection, pass in the <code>value</code> of the option as <code>msg.payload</code>, e.g. <code>msg.payload = "option1"</code>.
|
|
16
|
+
</p>
|
|
17
|
+
<p>
|
|
18
|
+
To make a multi-selection selection, you must first have "Allow Multiple" enabled on the node, you can then
|
|
19
|
+
pass an Array of <code>value</code> of the respective options as <code>msg.payload</code>, e.g. <code>msg.payload = ["option1", "option2"]</code>.
|
|
20
|
+
</p>
|
|
21
|
+
<p>
|
|
22
|
+
To clear any selection for a dropdown, pass an empty array <code>[]</code> as <code>msg.payload</code>.
|
|
23
|
+
</p>
|
|
24
|
+
</script>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script type="text/html" data-help-name="ui-form">
|
|
2
|
+
<p>Adds a form to user interface.</p>
|
|
3
|
+
<p>Helps to collect multiple value from the user on submit button click as an object in <code>msg.payload</code> </p>
|
|
4
|
+
<p>Multiple input elements can be added using add elements button</p>
|
|
5
|
+
<p>Each element contains following components:</p>
|
|
6
|
+
<ul>
|
|
7
|
+
<li> <b>Label</b> : Value that will be the label of the element in the user interface</li>
|
|
8
|
+
<li> <b>Name</b> : Represents the key (variable name) in the <code>msg.payload</code> in which the value of the corresponding element present</li>
|
|
9
|
+
<li> <b>Type</b> : Drop down option to select the type of input element</li>
|
|
10
|
+
<li> <b>Required</b> : On switching on the user has to supply the value before submitting</li>
|
|
11
|
+
<li> <b>Rows</b> : number of UI rows for multiline text input</li>
|
|
12
|
+
<li> <b>Delete</b> : To remove the current element from the form</li>
|
|
13
|
+
</ul>
|
|
14
|
+
<p>Optionally the <b>Topic</b> field can be used to set the <code>msg.topic</code> property.</p>
|
|
15
|
+
<p>The Cancel button can be hidden by setting it's value to be blank "".</p>
|
|
16
|
+
</script>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui-form": {
|
|
3
|
+
"label": {
|
|
4
|
+
"group": "Group",
|
|
5
|
+
"size": "Size",
|
|
6
|
+
"label": "Label",
|
|
7
|
+
"optionalLabel": "optional label",
|
|
8
|
+
"formElements": "Form elements",
|
|
9
|
+
"type": "Type",
|
|
10
|
+
"required": "Required",
|
|
11
|
+
"rows": "Rows",
|
|
12
|
+
"remove": "Remove",
|
|
13
|
+
"egName": "e.g. Name",
|
|
14
|
+
"egName2": "e.g. name",
|
|
15
|
+
"text": "Text",
|
|
16
|
+
"multiline": "Multiline",
|
|
17
|
+
"number": "Number",
|
|
18
|
+
"email": "E-mail",
|
|
19
|
+
"password": "Password",
|
|
20
|
+
"checkbox": "Checkbox",
|
|
21
|
+
"switch": "Switch",
|
|
22
|
+
"date": "Date",
|
|
23
|
+
"time": "Time",
|
|
24
|
+
"element": "element",
|
|
25
|
+
"buttons": "Buttons",
|
|
26
|
+
"submitButtonText": "submit button text",
|
|
27
|
+
"cancelButtonText": "cancel button text",
|
|
28
|
+
"topic": "Topic",
|
|
29
|
+
"optionalMsgTopic": "optional msg.topic",
|
|
30
|
+
"splitLayout":"Place the form elements in two columns",
|
|
31
|
+
"resetOnSubmit":"Reset the form when submitted",
|
|
32
|
+
"className": "Class",
|
|
33
|
+
"classNamePlaceholder": "Optional CSS class name(s) for widget"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script type="text/html" data-help-name="ui-text">
|
|
2
|
+
<p>
|
|
3
|
+
Converts markdown to rendered HTML int the Dashboard.
|
|
4
|
+
</p>
|
|
5
|
+
<p>
|
|
6
|
+
Can be use for rendering labels, headers or even full blog articles. If you're
|
|
7
|
+
looking for a quick cheat sheet on how to write Markdown, you can check out
|
|
8
|
+
FlowFuse's guide <a href="https://flowfuse.com/handbook/development/markdown-how-to/#markdown-how-to" target="_blank">here</a>.
|
|
9
|
+
</p>
|
|
10
|
+
</script>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
<script type="text/html" data-help-name="ui-slider">
|
|
3
|
+
<p>Adds a slider widget to the user interface.</p>
|
|
4
|
+
<p>
|
|
5
|
+
The user can change its value between the limits (<b>min</b> and <b>max</b>).
|
|
6
|
+
Each value change will generate a message with the value set as <b>payload</b>.
|
|
7
|
+
</p>
|
|
8
|
+
<p>The slider can be reversed by setting the min value larger than the max value. e.g. min 100, max 0.</p>
|
|
9
|
+
</script>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script type="text/html" data-help-name="ui-switch">
|
|
2
|
+
<p>
|
|
3
|
+
Adds a toggle switch to the user interface.
|
|
4
|
+
</p>
|
|
5
|
+
<p>
|
|
6
|
+
Each change in the state of the switch will generate
|
|
7
|
+
a <code>msg.payload</code> with the specified <b>On</b> and <b>Off</b> values.
|
|
8
|
+
</p>
|
|
9
|
+
<p>
|
|
10
|
+
The <b>On/Off Color</b> and <b>On/Off Icon</b> are optional fields. If the icons are present, the default
|
|
11
|
+
toggle switch will be replaced with the relevant icons and their respective colors (if defined).
|
|
12
|
+
</p>
|
|
13
|
+
<p>
|
|
14
|
+
The <b>On/Off Icon</b> field can be either a <a href="https://klarsys.github.io/angular-material-icons/" target="_blank">Material Design icon</a>
|
|
15
|
+
<i>(e.g. 'check', 'close')</i> or a <a href="https://fontawesome.com/v4.7.0/icons/" target="_blank">Font Awesome icon</a>
|
|
16
|
+
<i>(e.g. 'fa-fire')</i>, or a <a href="https://github.com/Paul-Reed/weather-icons-lite/blob/master/css_mappings.md">Weather icon</a>.
|
|
17
|
+
You can use the full set of google material icons if you add 'mi-' to the icon name. e.g. 'mi-videogame_asset'.
|
|
18
|
+
</p>
|
|
19
|
+
<p>
|
|
20
|
+
The switch state can be updated by an incoming <code>msg.payload</code>. The values must either be <code>true</code>/<code>false</code>
|
|
21
|
+
or match the specified type (number, string, etc) in the node's configuration.</p>
|
|
22
|
+
<!-- <p>
|
|
23
|
+
The label can also be set by a message property by setting
|
|
24
|
+
the field to the name of the property, for example <code>{{msg.topic}}</code>.</p>
|
|
25
|
+
<p>If a <b>Topic</b> is specified, it will be added to the output as <code>msg.topic</code>.</p> -->
|
|
26
|
+
<!-- <p>Setting <code>msg.enabled</code> to <code>false</code> will disable the switch widget.</p> -->
|
|
27
|
+
<!-- <p>
|
|
28
|
+
If a <b>Class</b> is specified, it will be added to the parent card. This way you can style the card
|
|
29
|
+
and the elements inside it with custom CSS. The Class can be set at runtime by setting a
|
|
30
|
+
<code>msg.className</code> string property.
|
|
31
|
+
</p> -->
|
|
32
|
+
</script>
|