@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,368 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
(function () {
|
|
3
|
+
// convert to i18 text
|
|
4
|
+
function c_ (x) {
|
|
5
|
+
return RED._('@flowforge/node-red-dashboard/ui-form:ui-form.' + x)
|
|
6
|
+
}
|
|
7
|
+
function hasProperty (obj, prop) {
|
|
8
|
+
return Object.prototype.hasOwnProperty.call(obj, prop)
|
|
9
|
+
}
|
|
10
|
+
RED.nodes.registerType('ui-form', {
|
|
11
|
+
category: RED._('@flowforge/node-red-dashboard/ui-base:ui-base.label.category'),
|
|
12
|
+
color: RED._('@flowforge/node-red-dashboard/ui-base:ui-base.colors.light'),
|
|
13
|
+
defaults: {
|
|
14
|
+
name: { value: '' },
|
|
15
|
+
group: { type: 'ui-group', required: true },
|
|
16
|
+
label: { value: '' },
|
|
17
|
+
order: { value: 0 },
|
|
18
|
+
width: {
|
|
19
|
+
value: 0,
|
|
20
|
+
validate: function (v) {
|
|
21
|
+
const width = v || 0
|
|
22
|
+
const currentGroup = $('#node-input-group').val() || this.group
|
|
23
|
+
const groupNode = RED.nodes.node(currentGroup)
|
|
24
|
+
const valid = !groupNode || +width <= +groupNode.width
|
|
25
|
+
$('#node-input-size').toggleClass('input-error', !valid)
|
|
26
|
+
return valid
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
height: { value: 0 },
|
|
30
|
+
options: {
|
|
31
|
+
value: [{ value: '', label: '', type: '', required: true }],
|
|
32
|
+
validate: function (value) {
|
|
33
|
+
if (value.length) {
|
|
34
|
+
for (let i = 0; i < value.length; i++) {
|
|
35
|
+
if (!value[i].key) {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
return true
|
|
43
|
+
},
|
|
44
|
+
required: true
|
|
45
|
+
},
|
|
46
|
+
formValue: { value: {} },
|
|
47
|
+
payload: { value: '' },
|
|
48
|
+
submit: { value: 'submit' },
|
|
49
|
+
cancel: { value: 'clear' },
|
|
50
|
+
resetOnSubmit: { value: true },
|
|
51
|
+
topic: { value: 'topic', validate: (hasProperty(RED.validators, 'typedInput') ? RED.validators.typedInput('topicType') : function (v) { return true }) },
|
|
52
|
+
topicType: { value: 'msg' },
|
|
53
|
+
splitLayout: { value: '' },
|
|
54
|
+
className: { value: '' }
|
|
55
|
+
},
|
|
56
|
+
inputs: 0,
|
|
57
|
+
outputs: 1,
|
|
58
|
+
icon: 'font-awesome/fa-list-alt',
|
|
59
|
+
paletteLabel: 'form',
|
|
60
|
+
label: function () { return this.name || this.label || 'form' },
|
|
61
|
+
labelStyle: function () { return this.name ? 'node_label_italic' : '' },
|
|
62
|
+
oneditprepare: function () {
|
|
63
|
+
if ($('#node-input-submit').val() === null) { $('#node-input-submit').val('submit') }
|
|
64
|
+
if ($('#node-input-cancel').val() === null) { $('#node-input-cancel').val('cancel') }
|
|
65
|
+
$('#node-input-size').elementSizer({
|
|
66
|
+
width: '#node-input-width',
|
|
67
|
+
height: '#node-input-height',
|
|
68
|
+
group: '#node-input-group'
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
this.resizeRule = function (option, newWidth) {
|
|
72
|
+
// option.find(".node-input-option-type").width(newWidth);
|
|
73
|
+
// option.find(".node-input-option-label").width(newWidth);
|
|
74
|
+
// option.find(".node-input-option-key").width(newWidth);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function generateOption (i, option) {
|
|
78
|
+
const container = $('<li/>', { style: 'margin:0; padding:8px 0px 0px; border-bottom:1px solid var(--red-ui-form-input-border-color, #ccc);' })
|
|
79
|
+
const row = $('<div/>').appendTo(container)
|
|
80
|
+
$('<div/>', { style: 'padding-top:5px; padding-left:175px;' }).appendTo(container)
|
|
81
|
+
$('<div/>', { style: 'padding-top:5px; padding-left:120px;' }).appendTo(container)
|
|
82
|
+
|
|
83
|
+
$('<i style="cursor:move; margin-left:3px;" class="node-input-option-handle fa fa-bars"></i>').appendTo(row)
|
|
84
|
+
|
|
85
|
+
// label field
|
|
86
|
+
$('<input/>', { class: 'node-input-option-label', type: 'text', style: 'margin-left:7px; width:20%;', placeholder: c_('label.egName'), value: option.label }).appendTo(row)
|
|
87
|
+
|
|
88
|
+
// key field
|
|
89
|
+
let keyClass = 'node-input-option-key'
|
|
90
|
+
if (!option.key) { keyClass = 'node-input-option-key input-error' }
|
|
91
|
+
const keyField = $('<input/>', { class: keyClass, type: 'text', style: 'margin-left:7px; width:20%;', placeholder: c_('label.egName2'), value: option.key }).appendTo(row)
|
|
92
|
+
keyField.keyup(function () {
|
|
93
|
+
if ($(this).val() && $(this).hasClass('input-error')) {
|
|
94
|
+
$(this).removeClass('input-error')
|
|
95
|
+
} else {
|
|
96
|
+
if (!$(this).val()) {
|
|
97
|
+
$(this).addClass('input-error')
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// type field
|
|
103
|
+
const typeField = $('<select/>', { class: 'node-input-option-type', type: 'text', style: 'margin-left:7px; width:16%' }).appendTo(row)// .typedInput({default:'str',types:['str', 'num']});
|
|
104
|
+
|
|
105
|
+
const arr = [
|
|
106
|
+
{ val: 'text', text: c_('label.text') },
|
|
107
|
+
{ val: 'multiline', text: c_('label.multiline') },
|
|
108
|
+
{ val: 'number', text: c_('label.number') },
|
|
109
|
+
{ val: 'email', text: c_('label.email') },
|
|
110
|
+
{ val: 'password', text: c_('label.password') },
|
|
111
|
+
{ val: 'checkbox', text: c_('label.checkbox') },
|
|
112
|
+
{ val: 'switch', text: c_('label.switch') },
|
|
113
|
+
{ val: 'date', text: c_('label.date') },
|
|
114
|
+
{ val: 'time', text: c_('label.time') }
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
// var sel = $('<select>').appendTo('body');
|
|
118
|
+
$(arr).each(function () {
|
|
119
|
+
let isSelected = false
|
|
120
|
+
if (option.type === this.val) {
|
|
121
|
+
isSelected = true
|
|
122
|
+
}
|
|
123
|
+
typeField.append($('<option>').attr('value', this.val).text(this.text).prop('selected', isSelected))
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
// which input types don't need a 'require' option
|
|
127
|
+
const noReqd = ['checkbox', 'switch']
|
|
128
|
+
|
|
129
|
+
// required
|
|
130
|
+
const requiredContainer = $('<div/>', { style: 'display:inline-block; height:34px; width:13%; vertical-align: middle' }).appendTo(row)
|
|
131
|
+
const requiredInnerContainer = $('<div/>', { style: 'left:35%; position:relative; width:30px' }).appendTo(requiredContainer)
|
|
132
|
+
const reqVis = noReqd.includes(option.type) ? 'hidden' : 'visible'
|
|
133
|
+
const reqRow = $('<label />', { class: 'switch', style: 'top:10px; width:30px;' }).css('visibility', reqVis).appendTo(requiredInnerContainer)
|
|
134
|
+
const reqd = $('<input/>', { class: 'node-input-option-required', type: 'checkbox', checked: option.required, style: 'vertical-align:top;' }).appendTo(reqRow)// labelForRequried);//.typedInput({default:'str',types:['str', 'num']});
|
|
135
|
+
$('<div />', { class: 'slider round' }).appendTo(reqRow)
|
|
136
|
+
|
|
137
|
+
// ui rows
|
|
138
|
+
const rowsVis = option.rows ? 'visible' : 'hidden'
|
|
139
|
+
const rowsField = $('<input/>', { class: 'node-input-option-rows', type: 'number', style: 'width:10%;', placeholder: 'Rows', value: option.rows }).css('visibility', rowsVis).appendTo(row)
|
|
140
|
+
|
|
141
|
+
const finalspan = $('<div/>', { style: 'display:inline-block; width:5%;' }).appendTo(row)
|
|
142
|
+
const deleteButton = $('<a/>', { href: '#', class: 'editor-button', style: 'font-size:1.3em; left:45%; position:relative;' }).appendTo(finalspan)
|
|
143
|
+
$('<i/>', { class: 'fa fa-trash-o' }).appendTo(deleteButton)
|
|
144
|
+
|
|
145
|
+
typeField.change(function (e) {
|
|
146
|
+
// decide whether we need to show the "rows" option
|
|
147
|
+
if (e.target.value !== 'multiline') {
|
|
148
|
+
rowsField.val(undefined)
|
|
149
|
+
option.rows = null
|
|
150
|
+
rowsField.css('visibility', 'hidden')
|
|
151
|
+
} else {
|
|
152
|
+
rowsField.css('visibility', 'visible')
|
|
153
|
+
if (!rowsField[0].value) rowsField[0].value = 3
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// device whether we need to show the "required" option
|
|
157
|
+
if (noReqd.includes(e.target.value)) {
|
|
158
|
+
reqd.val(false)
|
|
159
|
+
option.required = false
|
|
160
|
+
reqRow.css('visibility', 'hidden')
|
|
161
|
+
} else {
|
|
162
|
+
reqRow.css('visibility', 'visible')
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
deleteButton.click(function () {
|
|
167
|
+
container.find('.node-input-option-key').removeAttr('required')
|
|
168
|
+
container.css({ background: 'var(--red-ui-secondary-background-inactive, #fee)' })
|
|
169
|
+
container.fadeOut(300, function () {
|
|
170
|
+
$(this).remove()
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
$('#node-input-option-container').append(container)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
$('#node-input-add-option').click(function () {
|
|
178
|
+
generateOption($('#node-input-option-container').children().length + 1, {})
|
|
179
|
+
$('#node-input-option-container-div').scrollTop($('#node-input-option-container-div').get(0).scrollHeight)
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
for (let i = 0; i < this.options.length; i++) {
|
|
183
|
+
const option = this.options[i]
|
|
184
|
+
generateOption(i + 1, option)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
$('#node-input-topic').typedInput({
|
|
188
|
+
default: 'str',
|
|
189
|
+
typeField: $('#node-input-topicType'),
|
|
190
|
+
types: ['str', 'msg', 'flow', 'global']
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
$('#node-input-option-container').sortable({
|
|
194
|
+
axis: 'y',
|
|
195
|
+
handle: '.node-input-option-handle',
|
|
196
|
+
cursor: 'move'
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
// use jQuery UI tooltip to convert the plain old title attribute to a nice tooltip
|
|
200
|
+
$('.ui-node-popover-title').tooltip({
|
|
201
|
+
show: {
|
|
202
|
+
effect: 'slideDown',
|
|
203
|
+
delay: 150
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
},
|
|
207
|
+
oneditsave: function () {
|
|
208
|
+
const options = $('#node-input-option-container').children()
|
|
209
|
+
const node = this
|
|
210
|
+
node.options = []
|
|
211
|
+
node.formValue = {}
|
|
212
|
+
options.each(function (i) {
|
|
213
|
+
const option = $(this)
|
|
214
|
+
const o = {
|
|
215
|
+
label: option.find('.node-input-option-label').val(),
|
|
216
|
+
key: option.find('.node-input-option-key').val(),
|
|
217
|
+
type: option.find('.node-input-option-type').val(),
|
|
218
|
+
required: option.find('.node-input-option-required').is(':checked'),
|
|
219
|
+
rows: parseInt(option.find('.node-input-option-rows').val())
|
|
220
|
+
}
|
|
221
|
+
node.formValue[o.key] = o.type === 'checkbox' || o.type === 'switch' ? false : ''
|
|
222
|
+
node.options.push(o)
|
|
223
|
+
})
|
|
224
|
+
},
|
|
225
|
+
oneditresize: function () {
|
|
226
|
+
const options = $('#node-input-option-container').children()
|
|
227
|
+
const newWidth = ($('#node-input-option-container').width() - 175) / 2
|
|
228
|
+
const node = this
|
|
229
|
+
options.each(function (i) {
|
|
230
|
+
node.resizeRule($(this), newWidth)
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
})
|
|
234
|
+
})()
|
|
235
|
+
</script>
|
|
236
|
+
|
|
237
|
+
<script type="text/html" data-template-name="ui-form">
|
|
238
|
+
<style>
|
|
239
|
+
.switch {
|
|
240
|
+
position: relative;
|
|
241
|
+
display: inline-block;
|
|
242
|
+
width: 30px;
|
|
243
|
+
height: 18px;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.switch input {display:none;}
|
|
247
|
+
|
|
248
|
+
.slider {
|
|
249
|
+
position: absolute;
|
|
250
|
+
cursor: pointer;
|
|
251
|
+
top: 0;
|
|
252
|
+
left: 0;
|
|
253
|
+
right: 0;
|
|
254
|
+
bottom: 0;
|
|
255
|
+
background-color: var(--red-ui-tertiary-border-color, #ccc);
|
|
256
|
+
-webkit-transition: .4s;
|
|
257
|
+
transition: .4s;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.slider:before {
|
|
261
|
+
position: absolute;
|
|
262
|
+
content: "";
|
|
263
|
+
height: 15px;
|
|
264
|
+
width: 15px;
|
|
265
|
+
left: 2px;
|
|
266
|
+
bottom: 2px;
|
|
267
|
+
background-color: var(--red-ui-secondary-background, white);
|
|
268
|
+
-webkit-transition: .4s;
|
|
269
|
+
transition: .4s;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
input:checked + .slider {
|
|
273
|
+
background-color: #910000;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
input:focus + .slider {
|
|
277
|
+
box-shadow: 0 0 1px #2196F3;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
input:checked + .slider:before {
|
|
281
|
+
-webkit-transform: translateX(11px);
|
|
282
|
+
-ms-transform: translateX(11px);
|
|
283
|
+
transform: translateX(11px);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* Rounded sliders */
|
|
287
|
+
.slider.round {
|
|
288
|
+
border-radius: 34px;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.slider.round:before {
|
|
292
|
+
border-radius: 50%;
|
|
293
|
+
}
|
|
294
|
+
</style>
|
|
295
|
+
<div class="form-row">
|
|
296
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></label>
|
|
297
|
+
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
|
|
298
|
+
</div>
|
|
299
|
+
<div class="form-row">
|
|
300
|
+
<label for="node-input-group"><i class="fa fa-table"></i> <span data-i18n="ui-form.label.group"></label>
|
|
301
|
+
<input type="text" id="node-input-group">
|
|
302
|
+
</div>
|
|
303
|
+
<div class="form-row">
|
|
304
|
+
<label><i class="fa fa-object-group"></i> <span data-i18n="ui-form.label.size"></label>
|
|
305
|
+
<input type="hidden" id="node-input-width">
|
|
306
|
+
<input type="hidden" id="node-input-height">
|
|
307
|
+
<button class="editor-button" id="node-input-size"></button>
|
|
308
|
+
</div>
|
|
309
|
+
<div class="form-row">
|
|
310
|
+
<label for="node-input-label"><i class="fa fa-tag"></i> <span data-i18n="ui-form.label.label"></label>
|
|
311
|
+
<input type="text" id="node-input-label" data-i18n="[placeholder]ui-form.label.optionalLabel">
|
|
312
|
+
</div>
|
|
313
|
+
<div class="form-row">
|
|
314
|
+
<label for="node-input-className"><i class="fa fa-code"></i> Class</label>
|
|
315
|
+
<div style="display: inline;">
|
|
316
|
+
<input style="width: 70%;" type="text" id="node-input-className" placeholder="Optional CSS class name(s)" style="flex-grow: 1;">
|
|
317
|
+
<a
|
|
318
|
+
data-html="true"
|
|
319
|
+
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."
|
|
320
|
+
class="red-ui-button ui-node-popover-title"
|
|
321
|
+
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;">
|
|
322
|
+
<i style="font-family: ui-serif;">fx</i>
|
|
323
|
+
</a>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
<div class="form-row node-input-option-container-row" style="margin-bottom:0px; width:100%; min-width:520px">
|
|
327
|
+
<label style="vertical-align:top;"><i class="fa fa-list-alt"></i> <span data-i18n="ui-form.label.formElements"></label>
|
|
328
|
+
<div style="display:inline-block; width:78%; border:1px solid var(--red-ui-form-input-border-color, #ccc); border-radius:5px; box-sizing:border-box;">
|
|
329
|
+
<div class="red-ui-tray-header" style="width:100%; display: inline-block; padding-top:10px; padding-bottom:10px; border-top:0px solid; border-radius:5px 5px 0 0; border-bottom:1px solid var(--red-ui-form-input-border-color, #ccc);">
|
|
330
|
+
<div style="width:94%; display:inline-block; margin-left:27px">
|
|
331
|
+
<div style="width:20%; text-align:center; float:left;" data-i18n="ui-form.label.label"></span></div>
|
|
332
|
+
<div style="width:20%; text-align:center; float:left; margin-left:9px" data-i18n="node-red:common.label.name"></div>
|
|
333
|
+
<div style="margin-left:7px; width:16%; text-align:center; float:left; margin-left:9px" data-i18n="ui-form.label.type"></div>
|
|
334
|
+
<div style="width:16%; text-align:center; float:left;" data-i18n="ui-form.label.required"></div>
|
|
335
|
+
<div style="width:10%; text-align:center; float:left;" data-i18n="ui-form.label.rows"></div>
|
|
336
|
+
<div style="width:12%; text-align:center; float:left;" data-i18n="ui-form.label.remove"></div>
|
|
337
|
+
</div>
|
|
338
|
+
</div>
|
|
339
|
+
<div id="node-input-option-container-div" style=" height: 257px; padding: 5px; overflow-y:scroll;">
|
|
340
|
+
<ol id="node-input-option-container" style=" list-style-type:none; margin: 0;"></ol>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
<div class="form-row">
|
|
345
|
+
<a href="#" class="editor-button editor-button-small" id="node-input-add-option" style="margin-top: 4px; margin-left: 103px;"><i class="fa fa-plus"></i> <span data-i18n="ui-form.label.element"></span></a>
|
|
346
|
+
</div>
|
|
347
|
+
<div class="form-row">
|
|
348
|
+
<label for="node-input-submit"><i class="fa fa-square"></i> <span data-i18n="ui-form.label.buttons"></label>
|
|
349
|
+
<i class="fa fa-thumbs-o-up"></i> <input type="text" id="node-input-submit" data-i18n="[placeholder]ui-form.label.submitButtonText" style="width:35%;">
|
|
350
|
+
<span style="margin-left:16px"><i class="fa fa-thumbs-o-down"></i></span>
|
|
351
|
+
<input type="text" id="node-input-cancel" data-i18n="[placeholder]ui-form.label.cancelButtonText" style="width:35%;">
|
|
352
|
+
</div>
|
|
353
|
+
<div class="form-row">
|
|
354
|
+
<label></label>
|
|
355
|
+
<input type="checkbox" id="node-input-splitLayout" style="display:inline-block; width:auto; vertical-align:top;">
|
|
356
|
+
<label for="node-input-splitLayout" style="width: auto" data-i18n="ui-form.label.splitLayout">
|
|
357
|
+
</div>
|
|
358
|
+
<div class="form-row">
|
|
359
|
+
<label></label>
|
|
360
|
+
<input type="checkbox" id="node-input-resetOnSubmit" style="display:inline-block; width:auto; vertical-align:top;">
|
|
361
|
+
<label for="node-input-resetOnSubmit" style="width: auto" data-i18n="ui-form.label.resetOnSubmit"></label>
|
|
362
|
+
</div>
|
|
363
|
+
<div class="form-row">
|
|
364
|
+
<label for="node-input-topic"><i class="fa fa-tasks"></i> <span data-i18n="ui-form.label.topic"></label>
|
|
365
|
+
<input type="text" id="node-input-topic" style="width:70%" data-i18n="[placeholder]ui-form.label.optionalMsgTopic">
|
|
366
|
+
<input type="hidden" id="node-input-topicType">
|
|
367
|
+
</div>
|
|
368
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
function FormNode (config) {
|
|
3
|
+
RED.nodes.createNode(this, config)
|
|
4
|
+
|
|
5
|
+
const node = this
|
|
6
|
+
|
|
7
|
+
const group = RED.nodes.getNode(config.group)
|
|
8
|
+
if (!group) { return }
|
|
9
|
+
|
|
10
|
+
const evts = {
|
|
11
|
+
onAction: true
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// inform the dashboard UI that we are adding this node
|
|
15
|
+
group.register(node, config, evts)
|
|
16
|
+
}
|
|
17
|
+
RED.nodes.registerType('ui-form', FormNode)
|
|
18
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
(function () {
|
|
3
|
+
// convert to i18 text
|
|
4
|
+
function c_ (x) {
|
|
5
|
+
return RED._('@flowforge/node-red-dashboard/ui-markdown:ui-markdown.' + x)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
RED.nodes.registerType('ui-markdown', {
|
|
9
|
+
category: RED._('@flowforge/node-red-dashboard/ui-base:ui-base.label.category'),
|
|
10
|
+
color: RED._('@flowforge/node-red-dashboard/ui-base:ui-base.colors.dark'),
|
|
11
|
+
defaults: {
|
|
12
|
+
group: { type: 'ui-group', required: true },
|
|
13
|
+
name: { value: '' },
|
|
14
|
+
order: { value: 0 },
|
|
15
|
+
width: {
|
|
16
|
+
value: 0,
|
|
17
|
+
validate: function (v) {
|
|
18
|
+
let valid = true
|
|
19
|
+
if (this.templateScope !== 'global') {
|
|
20
|
+
const width = v || 0
|
|
21
|
+
const currentGroup = $('#node-input-group').val() || this.group
|
|
22
|
+
const groupNode = RED.nodes.node(currentGroup)
|
|
23
|
+
valid = !groupNode || +width <= +groupNode.width
|
|
24
|
+
$('#node-input-size').toggleClass('input-error', !valid)
|
|
25
|
+
}
|
|
26
|
+
return valid
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
height: { value: 0 },
|
|
30
|
+
content: { value: '# Markdown Content\n\nGoes here...' },
|
|
31
|
+
className: { value: '' }
|
|
32
|
+
},
|
|
33
|
+
inputs: 1,
|
|
34
|
+
outputs: 1,
|
|
35
|
+
icon: 'ui-markdown.png',
|
|
36
|
+
paletteLabel: 'markdown',
|
|
37
|
+
label: function () { return this.name || 'markdown' },
|
|
38
|
+
labelStyle: function () { return this.name ? 'node_label_italic' : '' },
|
|
39
|
+
oneditprepare: function () {
|
|
40
|
+
if (RED.editor.__debug === true) {
|
|
41
|
+
console.log('ui-markdown: oneditprepare')
|
|
42
|
+
}
|
|
43
|
+
$('#node-input-size').elementSizer({
|
|
44
|
+
width: '#node-input-width',
|
|
45
|
+
height: '#node-input-height',
|
|
46
|
+
group: '#node-input-group'
|
|
47
|
+
})
|
|
48
|
+
this.editor = RED.editor.createEditor({
|
|
49
|
+
id: 'node-input-content-editor',
|
|
50
|
+
mode: 'ace/mode/markdown',
|
|
51
|
+
value: $('#node-input-content').val()
|
|
52
|
+
})
|
|
53
|
+
RED.library.create({
|
|
54
|
+
url: 'uimarkdown', // where to get the data from
|
|
55
|
+
type: 'ui-markdown', // the type of object the library is for
|
|
56
|
+
editor: this.editor, // the field name the main text body goes to
|
|
57
|
+
mode: 'ace/mode/markdown',
|
|
58
|
+
fields: ['name']
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
this.editor.focus()
|
|
62
|
+
|
|
63
|
+
RED.popover.tooltip($('#node-markdown-expand-editor'), c_('label.expand'))
|
|
64
|
+
|
|
65
|
+
// use jQuery UI tooltip to convert the plain old title attribute to a nice tooltip
|
|
66
|
+
$('.ui-node-popover-title').tooltip({
|
|
67
|
+
show: {
|
|
68
|
+
effect: 'slideDown',
|
|
69
|
+
delay: 150
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
},
|
|
73
|
+
oneditsave: function () {
|
|
74
|
+
$('#node-input-content').val(this.editor.getValue())
|
|
75
|
+
this.editor.destroy()
|
|
76
|
+
delete this.editor
|
|
77
|
+
},
|
|
78
|
+
oneditcancel: function () {
|
|
79
|
+
this.editor.destroy()
|
|
80
|
+
delete this.editor
|
|
81
|
+
},
|
|
82
|
+
oneditresize: function (size) {
|
|
83
|
+
const rows = $('#dialog-form>div:not(.node-text-editor-row)')
|
|
84
|
+
let height = $('#dialog-form').height()
|
|
85
|
+
for (let i = 0; i < rows.size(); i++) {
|
|
86
|
+
height = height - $(rows[i]).outerHeight(true)
|
|
87
|
+
}
|
|
88
|
+
const editorRow = $('#dialog-form>div.node-text-editor-row')
|
|
89
|
+
height -= (parseInt(editorRow.css('marginTop')) + parseInt(editorRow.css('marginBottom')))
|
|
90
|
+
$('.node-text-editor').css('height', height + 'px')
|
|
91
|
+
this.editor.resize()
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
})()
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<script type="text/html" data-template-name="ui-markdown">
|
|
98
|
+
<div class="form-row">
|
|
99
|
+
<label for="node-input-group"><i class="fa fa-table"></i> Group</label>
|
|
100
|
+
<input style="flex-grow:1" type="text" id="node-input-group">
|
|
101
|
+
</div>
|
|
102
|
+
<div class="form-row">
|
|
103
|
+
<label><i class="fa fa-object-group"></i> Size</label>
|
|
104
|
+
<input type="hidden" id="node-input-width">
|
|
105
|
+
<input type="hidden" id="node-input-height">
|
|
106
|
+
<button class="editor-button" id="node-input-size"></button>
|
|
107
|
+
</div>
|
|
108
|
+
<div class="form-row">
|
|
109
|
+
<label for="node-input-className"><i class="fa fa-code"></i> Class</label>
|
|
110
|
+
<div style="display: inline;">
|
|
111
|
+
<input style="width: 70%;" type="text" id="node-input-className" placeholder="Optional CSS class name(s)" style="flex-grow: 1;">
|
|
112
|
+
<a
|
|
113
|
+
data-html="true"
|
|
114
|
+
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."
|
|
115
|
+
class="red-ui-button ui-node-popover-title"
|
|
116
|
+
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;">
|
|
117
|
+
<i style="font-family: ui-serif;">fx</i>
|
|
118
|
+
</a>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
<div class="form-row">
|
|
122
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
|
|
123
|
+
<div style="flex-grow: 1">
|
|
124
|
+
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="form-row" style="margin-bottom:0px;">
|
|
128
|
+
<label for="node-input-content"><i class="fa fa-copy"></i> Content</label>
|
|
129
|
+
<input type="hidden" id="node-input-content">
|
|
130
|
+
</div>
|
|
131
|
+
<div class="form-row node-text-editor-row" style="display: block;">
|
|
132
|
+
<div style="height:250px; min-height:100px" class="node-text-editor" id="node-input-content-editor" ></div>
|
|
133
|
+
</div>
|
|
134
|
+
</script>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
function MarkdownNode (config) {
|
|
3
|
+
const node = this
|
|
4
|
+
|
|
5
|
+
RED.nodes.createNode(this, config)
|
|
6
|
+
|
|
7
|
+
// which group are we rendering this widget
|
|
8
|
+
const group = RED.nodes.getNode(config.group)
|
|
9
|
+
|
|
10
|
+
// inform the dashboard UI that we are adding this node
|
|
11
|
+
group.register(node, config)
|
|
12
|
+
}
|
|
13
|
+
RED.nodes.registerType('ui-markdown', MarkdownNode)
|
|
14
|
+
}
|