@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,283 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
(function () {
|
|
3
|
+
// convert to i18 text
|
|
4
|
+
function c_ (x) {
|
|
5
|
+
return RED._('@flowforge/node-red-dashboard/ui-template:ui-template.' + x)
|
|
6
|
+
}
|
|
7
|
+
// TODO: move this to util.js for reuse & unit testing
|
|
8
|
+
function hasProperty (obj, prop) {
|
|
9
|
+
return Object.prototype.hasOwnProperty.call(obj, prop)
|
|
10
|
+
}
|
|
11
|
+
RED.nodes.registerType('ui-template', {
|
|
12
|
+
category: RED._('@flowforge/node-red-dashboard/ui-base:ui-base.label.category'),
|
|
13
|
+
color: RED._('@flowforge/node-red-dashboard/ui-base:ui-base.colors.dark'),
|
|
14
|
+
defaults: {
|
|
15
|
+
group: { type: 'ui-group', required: true }, // for when template is scoped to 'local' (default)
|
|
16
|
+
dashboard: { type: 'ui-base', required: false }, // for when template is scoped to 'site'
|
|
17
|
+
page: { type: 'ui-page', required: false }, // for when template is scoped to 'page'
|
|
18
|
+
name: { value: '' },
|
|
19
|
+
order: { value: 0 },
|
|
20
|
+
width: {
|
|
21
|
+
value: 0,
|
|
22
|
+
validate: function (v) {
|
|
23
|
+
let valid = true
|
|
24
|
+
if (this.templateScope !== 'global') {
|
|
25
|
+
const width = v || 0
|
|
26
|
+
const currentGroup = $('#node-input-group').val() || this.group
|
|
27
|
+
const groupNode = RED.nodes.node(currentGroup)
|
|
28
|
+
valid = !groupNode || +width <= +groupNode.width
|
|
29
|
+
$('#node-input-size').toggleClass('input-error', !valid)
|
|
30
|
+
}
|
|
31
|
+
return valid
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
height: { value: 0 },
|
|
35
|
+
head: { value: '' },
|
|
36
|
+
format: { value: '<div>{{ msg.payload }}</div>' },
|
|
37
|
+
storeOutMessages: { value: true },
|
|
38
|
+
fwdInMessages: { value: true },
|
|
39
|
+
resendOnRefresh: { value: true },
|
|
40
|
+
templateScope: { value: 'local' },
|
|
41
|
+
className: { value: '' }
|
|
42
|
+
},
|
|
43
|
+
inputs: 1,
|
|
44
|
+
outputs: 1,
|
|
45
|
+
icon: 'font-awesome/fa-code',
|
|
46
|
+
paletteLabel: 'template',
|
|
47
|
+
label: function () {
|
|
48
|
+
if (this.name) { return this.name }
|
|
49
|
+
const knownLabels = {
|
|
50
|
+
local: 'template',
|
|
51
|
+
'site:style': 'site style',
|
|
52
|
+
'page:style': 'page style'
|
|
53
|
+
}
|
|
54
|
+
return knownLabels[this.templateScope] || 'template'
|
|
55
|
+
},
|
|
56
|
+
labelStyle: function () { return this.name ? 'node_label_italic' : '' },
|
|
57
|
+
oneditprepare: function () {
|
|
58
|
+
if (RED.editor.__debug === true) {
|
|
59
|
+
console.log('ui-template: oneditprepare') // useful for locating this code in the browser debugger
|
|
60
|
+
}
|
|
61
|
+
if (hasProperty(RED.editor, 'editText') && typeof RED.editor.editText === 'function') {
|
|
62
|
+
$('#node-template-expand-editor').show()
|
|
63
|
+
} else {
|
|
64
|
+
$('#node-template-expand-editor').hide()
|
|
65
|
+
}
|
|
66
|
+
const that = this
|
|
67
|
+
const $templateScope = $('#node-input-templateScope')
|
|
68
|
+
|
|
69
|
+
$('#node-input-size').elementSizer({
|
|
70
|
+
width: '#node-input-width',
|
|
71
|
+
height: '#node-input-height',
|
|
72
|
+
group: '#node-input-group'
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
if (typeof this.storeOutMessages === 'undefined') {
|
|
76
|
+
this.storeOutMessages = true
|
|
77
|
+
$('#node-input-storeOutMessages').prop('checked', true)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (typeof this.fwdInMessages === 'undefined') {
|
|
81
|
+
this.fwdInMessages = true
|
|
82
|
+
$('#node-input-fwdInMessages').prop('checked', true)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (typeof this.templateScope === 'undefined') {
|
|
86
|
+
this.templateScope = 'local'
|
|
87
|
+
$templateScope.val(this.templateScope)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
$templateScope.on('change', function () {
|
|
91
|
+
that._def.defaults.group.required = false
|
|
92
|
+
that._def.defaults.page.required = false
|
|
93
|
+
that._def.defaults.dashboard.required = false
|
|
94
|
+
$('#template-row-group, #template-row-page, #template-row-dashboard, #template-row-class').hide()
|
|
95
|
+
switch ($templateScope.val()) {
|
|
96
|
+
case 'site:style':
|
|
97
|
+
$('#template-row-dashboard').show()
|
|
98
|
+
that._def.defaults.dashboard.required = true
|
|
99
|
+
that.editor.getSession().setMode('ace/mode/css')
|
|
100
|
+
break
|
|
101
|
+
case 'page:style':
|
|
102
|
+
$('#template-row-page').show()
|
|
103
|
+
that._def.defaults.dashboard.required = true
|
|
104
|
+
that.editor.getSession().setMode('ace/mode/css')
|
|
105
|
+
break
|
|
106
|
+
case 'site:script':
|
|
107
|
+
$('#template-row-dashboard').show()
|
|
108
|
+
that._def.defaults.dashboard.required = true
|
|
109
|
+
that.editor.getSession().setMode('ace/mode/javascript')
|
|
110
|
+
break
|
|
111
|
+
case 'page:script':
|
|
112
|
+
$('#template-row-page').show()
|
|
113
|
+
that._def.defaults.dashboard.required = true
|
|
114
|
+
that.editor.getSession().setMode('ace/mode/javascript')
|
|
115
|
+
break
|
|
116
|
+
default:
|
|
117
|
+
$('#template-row-group, #template-row-class').show()
|
|
118
|
+
that._def.defaults.group.required = true
|
|
119
|
+
that.editor.getSession().setMode('ace/mode/html')
|
|
120
|
+
break
|
|
121
|
+
}
|
|
122
|
+
resize.call(that)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
this.editor = RED.editor.createEditor({
|
|
126
|
+
id: 'node-input-format-editor',
|
|
127
|
+
mode: 'ace/mode/html',
|
|
128
|
+
value: $('#node-input-format').val()
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
RED.library.create({
|
|
132
|
+
url: 'uitemplates', // where to get the data from
|
|
133
|
+
type: 'ui-template', // the type of object the library is for
|
|
134
|
+
editor: this.editor, // the field name the main text body goes to
|
|
135
|
+
mode: 'ace/mode/html',
|
|
136
|
+
fields: ['name']
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
this.editor.focus()
|
|
140
|
+
|
|
141
|
+
RED.popover.tooltip($('#node-template-expand-editor'), c_('label.expand'))
|
|
142
|
+
|
|
143
|
+
$('#node-template-expand-editor').on('click', function (e) {
|
|
144
|
+
e.preventDefault()
|
|
145
|
+
const value = that.editor.getValue()
|
|
146
|
+
RED.editor.editText({
|
|
147
|
+
mode: $templateScope.val() === 'global' ? 'css' : 'html',
|
|
148
|
+
value,
|
|
149
|
+
width: 'Infinity',
|
|
150
|
+
cursor: that.editor.getCursorPosition(),
|
|
151
|
+
complete: function (v, cursor) {
|
|
152
|
+
that.editor.setValue(v, -1)
|
|
153
|
+
that.editor.gotoLine(cursor.row + 1, cursor.column, false)
|
|
154
|
+
setTimeout(function () { that.editor.focus() }, 300)
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
// use jQuery UI tooltip to convert the plain old title attribute to a nice tooltip
|
|
160
|
+
$('.ui-node-popover-title').tooltip({
|
|
161
|
+
show: {
|
|
162
|
+
effect: 'slideDown',
|
|
163
|
+
delay: 150
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
$templateScope.trigger('change') // trigger the change event to hide/show the group/dashboard row
|
|
168
|
+
},
|
|
169
|
+
oneditsave: function () {
|
|
170
|
+
const annot = this.editor.getSession().getAnnotations()
|
|
171
|
+
this.noerr = 0
|
|
172
|
+
$('#node-input-noerr').val(0)
|
|
173
|
+
for (let k = 0; k < annot.length; k++) {
|
|
174
|
+
if (annot[k].type === 'error') {
|
|
175
|
+
$('#node-input-noerr').val(annot.length)
|
|
176
|
+
this.noerr = annot.length
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
$('#node-input-format').val(this.editor.getValue())
|
|
180
|
+
this.editor.destroy()
|
|
181
|
+
delete this.editor
|
|
182
|
+
},
|
|
183
|
+
oneditcancel: function () {
|
|
184
|
+
this.editor.destroy()
|
|
185
|
+
delete this.editor
|
|
186
|
+
},
|
|
187
|
+
oneditresize: resize.bind(this)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
function resize (size) {
|
|
191
|
+
const rows = $('#dialog-form>div:not(.node-text-editor-row)')
|
|
192
|
+
let fixRowsHeight = 0
|
|
193
|
+
for (let i = 0; i < rows.size(); i++) {
|
|
194
|
+
fixRowsHeight += $(rows[i]).height()
|
|
195
|
+
}
|
|
196
|
+
const dialogHeight = $('#dialog-form').height()
|
|
197
|
+
const height = dialogHeight - fixRowsHeight
|
|
198
|
+
$('.node-text-editor').css('height', height + 'px')
|
|
199
|
+
if (RED.editor.__debug === true) {
|
|
200
|
+
console.log('dialogHeight', dialogHeight, 'fixRowsHeight', fixRowsHeight, 'height', height, 'editorRow')
|
|
201
|
+
}
|
|
202
|
+
this.editor && this.editor.resize()
|
|
203
|
+
}
|
|
204
|
+
})()
|
|
205
|
+
</script>
|
|
206
|
+
|
|
207
|
+
<script type="text/html" data-template-name="ui-template">
|
|
208
|
+
<div class="form-row">
|
|
209
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
|
|
210
|
+
<div style="display:inline-block; width:calc(100% - 105px)">
|
|
211
|
+
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
<div class="form-row">
|
|
215
|
+
<label for="node-input-temlplateScope"><i class="fa fa-dot-circle-o"></i> <span data-i18n="ui-template.label.scope"></span></label>
|
|
216
|
+
<select style="width:76%" id="node-input-templateScope">
|
|
217
|
+
<option value="local" data-i18n="ui-template.label.local"></option>
|
|
218
|
+
<option value="site:style" data-i18n="ui-template.label.site-style"></option>
|
|
219
|
+
<option value="page:style" data-i18n="ui-template.label.page-style"></option>
|
|
220
|
+
<!-- FUTURE? <option value="site:script" data-i18n="ui-template.label.site-script"></option>
|
|
221
|
+
<option value="page:script" data-i18n="ui-template.label.page-script"></option> -->
|
|
222
|
+
</select>
|
|
223
|
+
</div>
|
|
224
|
+
<div id="template-row-group" class="form-row">
|
|
225
|
+
<label for="node-input-group"><i class="fa fa-table"></i> Group</label>
|
|
226
|
+
<input type="text" id="node-input-group">
|
|
227
|
+
</div>
|
|
228
|
+
<div id="template-row-dashboard" class="form-row">
|
|
229
|
+
<label for="node-input-dashboard"><i class="fa fa-bookmark"></i> Dashboard</label>
|
|
230
|
+
<input type="text" id="node-input-dashboard">
|
|
231
|
+
</div>
|
|
232
|
+
<div id="template-row-page" class="form-row">
|
|
233
|
+
<label for="node-input-page"><i class="fa fa-bookmark"></i> Page</label>
|
|
234
|
+
<input type="text" id="node-input-page">
|
|
235
|
+
</div>
|
|
236
|
+
<div class="form-row">
|
|
237
|
+
<label><i class="fa fa-object-group"></i> Size</label>
|
|
238
|
+
<input type="hidden" id="node-input-width">
|
|
239
|
+
<input type="hidden" id="node-input-height">
|
|
240
|
+
<button class="editor-button" id="node-input-size"></button>
|
|
241
|
+
</div>
|
|
242
|
+
<!--<div class="form-row" id="template-row-size">
|
|
243
|
+
<label><i class="fa fa-object-group"></i> <span data-i18n="ui-template.label.size"></span></label>
|
|
244
|
+
<input type="hidden" id="node-input-width">
|
|
245
|
+
<input type="hidden" id="node-input-height">
|
|
246
|
+
<button class="editor-button" id="node-input-size"></button>
|
|
247
|
+
</div>-->
|
|
248
|
+
<div class="form-row">
|
|
249
|
+
<label for="node-input-className"><i class="fa fa-code"></i> Class</label>
|
|
250
|
+
<div style="display: inline;">
|
|
251
|
+
<input style="width: 70%;" type="text" id="node-input-className" placeholder="Optional CSS class name(s)" style="flex-grow: 1;">
|
|
252
|
+
<a
|
|
253
|
+
data-html="true"
|
|
254
|
+
title="Dynamic Property: Class names can also be set by sending a message to the node with a msg.topic of 'ui-property:class' and a payload containing the class name(s) to be applied. NOTE: classes set at runtime will be applied in addition to any class(es) set in the nodes class field."
|
|
255
|
+
class="red-ui-button ui-node-popover-title"
|
|
256
|
+
style="margin-left: 4px; cursor: help; font-size: 0.625rem; border-radius: 50%; width: 24px; height: 24px; display: inline-flex; justify-content: center; align-items: center;">
|
|
257
|
+
<i style="font-family: ui-serif;">fx</i>
|
|
258
|
+
</a>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
<div class="form-row" style="margin-bottom:0px;">
|
|
262
|
+
<label for="node-input-format"><i class="fa fa-copy"></i> <span data-i18n="ui-template.label.template"></span></label>
|
|
263
|
+
<input type="hidden" id="node-input-format">
|
|
264
|
+
<button id="node-template-expand-editor" class="red-ui-button red-ui-button-small" style="float:right"><i class="fa fa-expand"></i></button>
|
|
265
|
+
</div>
|
|
266
|
+
<div class="form-row node-text-editor-row" style="display: block;">
|
|
267
|
+
<div style="height:250px; min-height:100px" class="node-text-editor" id="node-input-format-editor" ></div>
|
|
268
|
+
</div>
|
|
269
|
+
<!--<div id="template-pass-store">
|
|
270
|
+
<div class="form-row" style="margin-bottom:0px;">
|
|
271
|
+
<input type="checkbox" id="node-input-fwdInMessages" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
|
|
272
|
+
<label for="node-input-fwdInMessages" style="width:70%;"> <span data-i18n="ui-template.label.pass-through"></span></label>
|
|
273
|
+
</div>
|
|
274
|
+
<div class="form-row" style="margin-bottom:0px;">
|
|
275
|
+
<input type="checkbox" id="node-input-storeOutMessages" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
|
|
276
|
+
<label for="node-input-storeOutMessages" style="width:70%;"> <span data-i18n="ui-template.label.store-state"></span></label>
|
|
277
|
+
</div>
|
|
278
|
+
<div class="form-row" style="margin-bottom:0px;">
|
|
279
|
+
<input type="checkbox" id="node-input-resendOnRefresh" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
|
|
280
|
+
<label for="node-input-resendOnRefresh" style="width:70%;"> <span data-i18n="ui-template.label.resend"></span></label>
|
|
281
|
+
</div>
|
|
282
|
+
</div> -->
|
|
283
|
+
</script>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
function TemplateNode (config) {
|
|
3
|
+
const node = this
|
|
4
|
+
|
|
5
|
+
// create node in Node-RED
|
|
6
|
+
RED.nodes.createNode(this, config)
|
|
7
|
+
|
|
8
|
+
// which group are we rendering this widget
|
|
9
|
+
const group = RED.nodes.getNode(config.group)
|
|
10
|
+
|
|
11
|
+
const evts = {
|
|
12
|
+
onAction: true // TODO: think we need an onSend event for template nodes that matches up with a `widget-send` message
|
|
13
|
+
}
|
|
14
|
+
// inform the dashboard UI that we are adding this node
|
|
15
|
+
group.register(node, config, evts)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
RED.nodes.registerType('ui-template', TemplateNode)
|
|
19
|
+
}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
(function () {
|
|
3
|
+
const fonts = [
|
|
4
|
+
{
|
|
5
|
+
value: 'Arial,Arial,Helvetica,sans-serif',
|
|
6
|
+
name: 'Arial'
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
value: 'Arial Black,Arial Black,Gadget,sans-serif',
|
|
10
|
+
name: 'Arial Black'
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
value: 'Arial Narrow,Nimbus Sans L,sans-serif',
|
|
14
|
+
name: 'Arial Narrow'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
value: 'Century Gothic,CenturyGothic,AppleGothic,sans-serif',
|
|
18
|
+
name: 'Century Gothic'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
value: 'Copperplate,Copperplate Gothic Light,fantasy',
|
|
22
|
+
name: 'Copperplate'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
value: 'Courier,monospace',
|
|
26
|
+
name: 'Courier'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
value: 'Georgia,Georgia,serif',
|
|
30
|
+
name: 'Georgia'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
value: 'Gill Sans,Geneva,sans-serif',
|
|
34
|
+
name: 'Gill Sans'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
value: 'Impact,Impact,Charcoal,sans-serif',
|
|
38
|
+
name: 'Impact'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
value: 'Lucida Sans Typewriter,Lucida Console,Monaco,monospace',
|
|
42
|
+
name: 'Lucida Console'
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
value: 'Lucida Sans Unicode,Lucida Grande,sans-serif',
|
|
46
|
+
name: 'Lucida Sans'
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
value: 'Palatino Linotype,Palatino,Book Antiqua,serif',
|
|
50
|
+
name: 'Palatino Linotype'
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
value: 'Tahoma,Geneva,sans-serif',
|
|
54
|
+
name: 'Tahoma'
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
value: 'Times New Roman,Times,serif',
|
|
58
|
+
name: 'Times New Roman'
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
value: 'Trebuchet MS,Helvetica,sans-serif',
|
|
62
|
+
name: 'Trebuchet MS'
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
value: 'Verdana,Verdana,Geneva,sans-serif',
|
|
66
|
+
name: 'Verdana'
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
RED.nodes.registerType('ui-text', {
|
|
71
|
+
category: RED._('@flowforge/node-red-dashboard/ui-base:ui-base.label.category'),
|
|
72
|
+
color: RED._('@flowforge/node-red-dashboard/ui-base:ui-base.colors.medium'),
|
|
73
|
+
defaults: {
|
|
74
|
+
group: { type: 'ui-group', required: true },
|
|
75
|
+
order: { value: 0 },
|
|
76
|
+
width: {
|
|
77
|
+
value: 0,
|
|
78
|
+
validate: function (v) {
|
|
79
|
+
const width = v || 0
|
|
80
|
+
const currentGroup = $('#node-input-group').val() || this.group
|
|
81
|
+
const groupNode = RED.nodes.node(currentGroup)
|
|
82
|
+
const valid = !groupNode || +width <= +groupNode.width
|
|
83
|
+
$('#node-input-size').toggleClass('input-error', !valid)
|
|
84
|
+
return valid
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
height: { value: 0 },
|
|
88
|
+
name: { value: '' },
|
|
89
|
+
label: { value: 'text' },
|
|
90
|
+
format: { value: '{{msg.payload}}' },
|
|
91
|
+
layout: { value: 'row-spread' },
|
|
92
|
+
style: { value: false },
|
|
93
|
+
font: { value: '' },
|
|
94
|
+
fontSize: { value: 16 },
|
|
95
|
+
color: { value: '#000' },
|
|
96
|
+
className: { value: '' }
|
|
97
|
+
},
|
|
98
|
+
inputs: 1,
|
|
99
|
+
outputs: 0,
|
|
100
|
+
align: 'right',
|
|
101
|
+
icon: 'font-awesome/fa-font',
|
|
102
|
+
paletteLabel: 'text',
|
|
103
|
+
label: function () { return this.name || (~this.label.indexOf('{' + '{') ? null : this.label) || 'text' },
|
|
104
|
+
labelStyle: function () { return this.name ? 'node_label_italic' : '' },
|
|
105
|
+
oneditprepare: function () {
|
|
106
|
+
$('#node-input-size').elementSizer({
|
|
107
|
+
width: '#node-input-width',
|
|
108
|
+
height: '#node-input-height',
|
|
109
|
+
group: '#node-input-group'
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
$('.nr-db-text-layout-' + (this.layout || 'row-spread')).addClass('selected');
|
|
113
|
+
['.nr-db-text-layout-row-left', '.nr-db-text-layout-row-center', '.nr-db-text-layout-row-right', '.nr-db-text-layout-row-spread', '.nr-db-text-layout-col-center']
|
|
114
|
+
.forEach(function (id) {
|
|
115
|
+
$(id).click(function (e) {
|
|
116
|
+
$('.nr-db-text-layout').removeClass('selected')
|
|
117
|
+
$(this).addClass('selected')
|
|
118
|
+
$('#node-input-layout').val(id.substring('.nr-db-text-layout-'.length))
|
|
119
|
+
e.preventDefault()
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
const select = $('#node-select-font')
|
|
124
|
+
|
|
125
|
+
// add font options
|
|
126
|
+
fonts.forEach((font) => {
|
|
127
|
+
const name = font.name
|
|
128
|
+
const val = font.value
|
|
129
|
+
$('<option/>', {
|
|
130
|
+
value: val
|
|
131
|
+
}).text(name).appendTo(select)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
// when a font is selected
|
|
135
|
+
$(select).change(() => {
|
|
136
|
+
const val = $('#node-select-font').val()
|
|
137
|
+
// update hidden input
|
|
138
|
+
$('#node-input-font').val(val)
|
|
139
|
+
// update test text
|
|
140
|
+
$('#node-test-text').css({
|
|
141
|
+
'font-family': val
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
$(select).val(this.font)
|
|
145
|
+
$(select).change()
|
|
146
|
+
|
|
147
|
+
// make the fontsize a numeric spinner
|
|
148
|
+
$('#node-input-fontSize').spinner({
|
|
149
|
+
min: 1,
|
|
150
|
+
max: 100,
|
|
151
|
+
spin: () => {
|
|
152
|
+
// update the test text when value is changed
|
|
153
|
+
const val = $('#node-input-fontSize').val()
|
|
154
|
+
$('#node-test-text').css({
|
|
155
|
+
'font-size': val + 'px'
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
// add change handler to color picker to update test text
|
|
161
|
+
$('#node-input-color').change(() => {
|
|
162
|
+
const val = $('#node-input-color').val()
|
|
163
|
+
$('#node-test-text').css({
|
|
164
|
+
color: val
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
// add change handler to show/hide style config options
|
|
169
|
+
$('#node-input-style').change(() => {
|
|
170
|
+
const val = $('#node-input-style').prop('checked')
|
|
171
|
+
if (val) {
|
|
172
|
+
$('#node-styles').show()
|
|
173
|
+
} else {
|
|
174
|
+
$('#node-styles').hide()
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
$('#node-input-style').change()
|
|
178
|
+
|
|
179
|
+
// when opening the config, make sure the test text is updated
|
|
180
|
+
if (this.fontSize) {
|
|
181
|
+
$('#node-test-text').css({
|
|
182
|
+
'font-size': this.fontSize + 'px'
|
|
183
|
+
})
|
|
184
|
+
}
|
|
185
|
+
if (this.color) {
|
|
186
|
+
$('#node-test-text').css({
|
|
187
|
+
color: this.color
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// use jQuery UI tooltip to convert the plain old title attribute to a nice tooltip
|
|
192
|
+
$('.ui-node-popover-title').tooltip({
|
|
193
|
+
show: {
|
|
194
|
+
effect: 'slideDown',
|
|
195
|
+
delay: 150
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
})()
|
|
201
|
+
</script>
|
|
202
|
+
|
|
203
|
+
<script type="text/html" data-template-name="ui-text">
|
|
204
|
+
<div class="form-row">
|
|
205
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
206
|
+
<input type="text" id="node-input-name">
|
|
207
|
+
</div>
|
|
208
|
+
<div class="form-row">
|
|
209
|
+
<label for="node-input-group"><i class="fa fa-table"></i> Group</label>
|
|
210
|
+
<input type="text" id="node-input-group">
|
|
211
|
+
</div>
|
|
212
|
+
<div class="form-row">
|
|
213
|
+
<label><i class="fa fa-object-group"></i> Size</label>
|
|
214
|
+
<input type="hidden" id="node-input-width">
|
|
215
|
+
<input type="hidden" id="node-input-height">
|
|
216
|
+
<button class="editor-button" id="node-input-size"></button>
|
|
217
|
+
</div>
|
|
218
|
+
<div class="form-row">
|
|
219
|
+
<label for="node-input-label"><i class="fa fa-i-cursor"></i> Label</label>
|
|
220
|
+
<input type="text" id="node-input-label">
|
|
221
|
+
</div>
|
|
222
|
+
<div class="form-row">
|
|
223
|
+
<label for="node-input-className"><i class="fa fa-code"></i> Class</label>
|
|
224
|
+
<div style="display: inline;">
|
|
225
|
+
<input style="width: 70%;" type="text" id="node-input-className" placeholder="Optional CSS class name(s)" style="flex-grow: 1;">
|
|
226
|
+
<a
|
|
227
|
+
data-html="true"
|
|
228
|
+
title="Dynamic Property: Class names can also be set by sending a message to the node with a msg.topic of 'ui-property:class' and a payload containing the class name(s) to be applied. NOTE: classes set at runtime will be applied in addition to any class(es) set in the nodes class field."
|
|
229
|
+
class="red-ui-button ui-node-popover-title"
|
|
230
|
+
style="margin-left: 4px; cursor: help; font-size: 0.625rem; border-radius: 50%; width: 24px; height: 24px; display: inline-flex; justify-content: center; align-items: center;">
|
|
231
|
+
<i style="font-family: ui-serif;">fx</i>
|
|
232
|
+
</a>
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
<!--<div class="form-row">
|
|
236
|
+
<label for="node-input-format"><i class="fa fa-i-cursor"></i> Value format</label>
|
|
237
|
+
<input type="text" id="node-input-format" placeholder="{{msg.payload}}">
|
|
238
|
+
</div>-->
|
|
239
|
+
<div class="form-row">
|
|
240
|
+
<label style="vertical-align: top"><i class="fa fa-th-large"></i> Layout</label>
|
|
241
|
+
<div style="display:inline-block">
|
|
242
|
+
<input type="hidden" id="node-input-layout">
|
|
243
|
+
<input type="hidden" id="node-input-layoutAlign" >
|
|
244
|
+
<div>
|
|
245
|
+
<a href="#" class="nr-db-text-layout nr-db-text-layout-row nr-db-text-layout-row-left">
|
|
246
|
+
<span class="nr-db-text-layout-label">label</span>
|
|
247
|
+
<span class="nr-db-text-layout-value">value</span>
|
|
248
|
+
<div class="nr-db-text-layout-checkbox"></div>
|
|
249
|
+
</a>
|
|
250
|
+
<a href="#" class="nr-db-text-layout nr-db-text-layout-row nr-db-text-layout-row-center">
|
|
251
|
+
<span class="nr-db-text-layout-label">label</span>
|
|
252
|
+
<span class="nr-db-text-layout-value">value</span>
|
|
253
|
+
<div class="nr-db-text-layout-checkbox"></div>
|
|
254
|
+
</a>
|
|
255
|
+
<a href="#" class="nr-db-text-layout nr-db-text-layout-row nr-db-text-layout-row-right">
|
|
256
|
+
<span class="nr-db-text-layout-label">label</span>
|
|
257
|
+
<span class="nr-db-text-layout-value">value</span>
|
|
258
|
+
<div class="nr-db-text-layout-checkbox"></div>
|
|
259
|
+
</a>
|
|
260
|
+
</div>
|
|
261
|
+
<div>
|
|
262
|
+
<a href="#" class="nr-db-text-layout nr-db-text-layout-row nr-db-text-layout-row-spread">
|
|
263
|
+
<span class="nr-db-text-layout-label">label</span>
|
|
264
|
+
<span class="nr-db-text-layout-value">value</span>
|
|
265
|
+
<div class="nr-db-text-layout-checkbox"></div>
|
|
266
|
+
</a>
|
|
267
|
+
<a href="#" class="nr-db-text-layout nr-db-text-layout-col nr-db-text-layout-col-center">
|
|
268
|
+
<span class="nr-db-text-layout-label">label</span>
|
|
269
|
+
<span class="nr-db-text-layout-value">value</span>
|
|
270
|
+
<div class="nr-db-text-layout-checkbox"></div>
|
|
271
|
+
</a>
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
<div class="form-row">
|
|
277
|
+
<label><i class="fa fa-cog"></i> Style</label>
|
|
278
|
+
<input type="checkbox" id="node-input-style" style="display: inline-block; width: auto; vertical-align: top; margin: 0 3px 0 0;"/>
|
|
279
|
+
<label for="node-input-style" style="width: 70%;"> Apply Style</label>
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
<div id="node-styles">
|
|
283
|
+
<div class="form-row">
|
|
284
|
+
<label for="node-input-font"><i class="fa fa-font"></i> Font</label>
|
|
285
|
+
<select id="node-select-font">
|
|
286
|
+
</select>
|
|
287
|
+
<input type="hidden" id="node-input-font"/>
|
|
288
|
+
</div>
|
|
289
|
+
<div class="form-row">
|
|
290
|
+
<label for="node-input-fontSize"><i class="fa fa-text-height"></i> Text Size</label>
|
|
291
|
+
<input id="node-input-fontSize" value="16" style="width: 50px;"/>
|
|
292
|
+
</div>
|
|
293
|
+
<div class="form-row">
|
|
294
|
+
<label for="node-input-color"><i class="fa fa-tint"></i> Text Color</label>
|
|
295
|
+
<input type="color" id="node-input-color" style="width: 50px;"/>
|
|
296
|
+
</div>
|
|
297
|
+
<div class="form-row">
|
|
298
|
+
<label> </label>
|
|
299
|
+
<input id="node-test-text" value="Enter Sample Here"/ style="width: 280px;">
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
</script>
|
|
303
|
+
|
|
304
|
+
<style>
|
|
305
|
+
.nr-db-text-layout {
|
|
306
|
+
position:relative;
|
|
307
|
+
display: inline-block;
|
|
308
|
+
width: 90px;
|
|
309
|
+
height: 60px;
|
|
310
|
+
border-radius:3px;
|
|
311
|
+
border:1px solid var(--red-ui-form-input-border-color, #bbb);
|
|
312
|
+
cursor:pointer;
|
|
313
|
+
color: #666;
|
|
314
|
+
margin-right: 10px;
|
|
315
|
+
margin-bottom: 10px;
|
|
316
|
+
}
|
|
317
|
+
.nr-db-text-layout.selected, .nr-db-text-layout:hover {
|
|
318
|
+
border-color: var(--red-ui-form-input-border-selected-color, #333);
|
|
319
|
+
color: var(--red-ui-secondary-text-color-selected, #333);
|
|
320
|
+
}
|
|
321
|
+
.nr-db-text-layout span {
|
|
322
|
+
position: absolute;
|
|
323
|
+
}
|
|
324
|
+
.nr-db-text-layout-value {
|
|
325
|
+
font-weight: bold;
|
|
326
|
+
}
|
|
327
|
+
.nr-db-text-layout-row span { top: 20px; }
|
|
328
|
+
.nr-db-text-layout-row-left .nr-db-text-layout-label { left: 2px; }
|
|
329
|
+
.nr-db-text-layout-row-left .nr-db-text-layout-value { left: 34px; }
|
|
330
|
+
.nr-db-text-layout-row-spread .nr-db-text-layout-label { left: 2px; }
|
|
331
|
+
.nr-db-text-layout-row-spread .nr-db-text-layout-value { right: 2px; }
|
|
332
|
+
.nr-db-text-layout-row-center .nr-db-text-layout-label { left: 11px; }
|
|
333
|
+
.nr-db-text-layout-row-center .nr-db-text-layout-value { right: 11px; }
|
|
334
|
+
.nr-db-text-layout-row-right .nr-db-text-layout-label { right: 40px; }
|
|
335
|
+
.nr-db-text-layout-row-right .nr-db-text-layout-value { right: 2px; }
|
|
336
|
+
|
|
337
|
+
.nr-db-text-layout-col span { width: 90px; text-align: center; left: 0px;}
|
|
338
|
+
.nr-db-text-layout-col-center .nr-db-text-layout-label { top: 12px; }
|
|
339
|
+
.nr-db-text-layout-col-center .nr-db-text-layout-value { top: 26px; }
|
|
340
|
+
.nr-db-text-layout-checkbox {
|
|
341
|
+
display: none;
|
|
342
|
+
width: 10px;
|
|
343
|
+
height: 10px;
|
|
344
|
+
border-radius: 10px;
|
|
345
|
+
border: 1px solid var(--red-ui-primary-border-color, #bbb);
|
|
346
|
+
position: absolute;
|
|
347
|
+
right: -5px;
|
|
348
|
+
top: -5px;
|
|
349
|
+
background: var(--red-ui-secondary-background, #fff);
|
|
350
|
+
}
|
|
351
|
+
.nr-db-text-layout.selected .nr-db-text-layout-checkbox {
|
|
352
|
+
display:inline-block;
|
|
353
|
+
box-shadow: inset 0px 0px 0px 2px #fff;
|
|
354
|
+
background: #333;
|
|
355
|
+
border-color: #333;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
</style>
|