@flowfuse/node-red-dashboard 1.4.1 → 1.4.2-603b043-202403211300.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/nodes/config/locales/en-US/ui_base.json +7 -2
- package/nodes/config/ui_base.html +244 -21
- package/nodes/config/ui_theme.html +13 -2
- package/nodes/widgets/locales/en-US/ui_table.json +7 -1
- package/nodes/widgets/ui_table.html +19 -3
- package/nodes/widgets/ui_table.js +10 -1
- package/package.json +1 -1
- package/dist/assets/array-Nw74a44z.js +0 -1
- package/dist/assets/c4Diagram-c0b17d02-a2pebagc.js +0 -10
- package/dist/assets/classDiagram-a8cc8886-GZGIdAJ_.js +0 -1
- package/dist/assets/classDiagram-v2-802a48d3-HsmQ8rG1.js +0 -2
- package/dist/assets/createText-3b1f58a4-mxGZySa5.js +0 -7
- package/dist/assets/edges-0005682e-fKeIHISH.js +0 -4
- package/dist/assets/erDiagram-dedf2781-eQZ1uSA4.js +0 -51
- package/dist/assets/flowDb-ff651a22-LfeipZDx.js +0 -6
- package/dist/assets/flowDiagram-d6f8fe3a-JN4Ed9yZ.js +0 -4
- package/dist/assets/flowDiagram-v2-58f49b84-33yARutL.js +0 -1
- package/dist/assets/flowchart-elk-definition-56584a6c-bfP0iEF8.js +0 -139
- package/dist/assets/ganttDiagram-088dbd90-e7z2jUgU.js +0 -266
- package/dist/assets/gitGraphDiagram-e0ffc2d1-I_KYQh4w.js +0 -70
- package/dist/assets/index-Bg4_FLds.css +0 -13
- package/dist/assets/index-asnKLxJa.js +0 -244
- package/dist/assets/index-f58d48f9-d4cGR4h9.js +0 -1
- package/dist/assets/infoDiagram-64895a6e-vN27pifj.js +0 -7
- package/dist/assets/init-Hi12RPRh.js +0 -1
- package/dist/assets/journeyDiagram-adaa34f8-xi8F80bo.js +0 -139
- package/dist/assets/layout-3LCZs9R0.js +0 -1
- package/dist/assets/line-fvKpAihG.js +0 -1
- package/dist/assets/linear-uqAl50Gy.js +0 -1
- package/dist/assets/logo-yAM2wbsA.png +0 -0
- package/dist/assets/materialdesignicons-webfont-AeJCkVfO.woff2 +0 -0
- package/dist/assets/materialdesignicons-webfont-GtBnFie6.woff +0 -0
- package/dist/assets/materialdesignicons-webfont-IwmCr2II.ttf +0 -0
- package/dist/assets/materialdesignicons-webfont-JbV82i5g.eot +0 -0
- package/dist/assets/mindmap-definition-57868176-LV1c2j1Q.js +0 -109
- package/dist/assets/ordinal-OOfG4Z7H.js +0 -1
- package/dist/assets/pieDiagram-3fca7ce7-vfEvOfTZ.js +0 -35
- package/dist/assets/quadrantDiagram-0ca4be02-OEgV-acy.js +0 -7
- package/dist/assets/requirementDiagram-e13af0f0-uQ3nZvjs.js +0 -52
- package/dist/assets/sankeyDiagram-a7f8e230-ndSWm-w9.js +0 -8
- package/dist/assets/sequenceDiagram-84aa38e3-1fPqwfPD.js +0 -122
- package/dist/assets/stateDiagram-9a586ac6--PiHEPfC.js +0 -1
- package/dist/assets/stateDiagram-v2-96f2b9df-NwLYhf_v.js +0 -1
- package/dist/assets/styles-1b0c237a-MROaEgpy.js +0 -110
- package/dist/assets/styles-622362e4-vxjPbudl.js +0 -160
- package/dist/assets/styles-a1a6e33f-zXFCWLTw.js +0 -207
- package/dist/assets/svgDraw-70101091-9ZNdrwGr.js +0 -2
- package/dist/assets/svgDrawCommon-42e92da3-N6cP2Lo3.js +0 -1
- package/dist/assets/timeline-definition-1a90b03d-RxP2u2Dq.js +0 -61
- package/dist/favicon.ico +0 -0
- package/dist/index.html +0 -20
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"openDashboard": "Open Dashboard",
|
|
11
11
|
"layout": "Layout",
|
|
12
12
|
"layoutMessage": "Here you can re-order and move your widgets, groups and pages.",
|
|
13
|
+
"unattachedMessage": "The following Groups have do not have a parent page defined.",
|
|
13
14
|
"theming": "Theming",
|
|
14
15
|
"themingMessage": "Here you can can get quick access to your UI Themes, defined on your Dashboard.",
|
|
15
16
|
"page": "Page",
|
|
@@ -26,13 +27,17 @@
|
|
|
26
27
|
},
|
|
27
28
|
"layout": {
|
|
28
29
|
"pages": "Pages",
|
|
30
|
+
"page": "Page",
|
|
31
|
+
"group": "Group",
|
|
29
32
|
"edit": "Edit",
|
|
30
33
|
"focus": "Focus",
|
|
31
34
|
"collapse": "Collapse",
|
|
32
|
-
"expand": "Expand"
|
|
35
|
+
"expand": "Expand",
|
|
36
|
+
"unattachedGroups": "Unattached Groups"
|
|
33
37
|
},
|
|
34
38
|
"themes": {
|
|
35
|
-
"header": "Themes"
|
|
39
|
+
"header": "Themes",
|
|
40
|
+
"theme": "Theme"
|
|
36
41
|
},
|
|
37
42
|
"colors": {
|
|
38
43
|
"light": "var(--nrdb-node-light)",
|
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
background-color: #e3f2fd;
|
|
58
58
|
}
|
|
59
59
|
/* Dashboard 2.0 Sidebar */
|
|
60
|
+
.nrdb2-sb-list-button-group {
|
|
61
|
+
display: flex;
|
|
62
|
+
gap: 4px;
|
|
63
|
+
}
|
|
60
64
|
.nrdb2-sidebar-tab-content {
|
|
61
65
|
padding: 8px 10px;
|
|
62
66
|
height: 100%;
|
|
@@ -81,6 +85,11 @@
|
|
|
81
85
|
padding: 0;
|
|
82
86
|
border-bottom: 0;
|
|
83
87
|
}
|
|
88
|
+
.nrdb2-sb-unattached-groups-list li {
|
|
89
|
+
padding: 0;
|
|
90
|
+
border-bottom: 0;
|
|
91
|
+
background-color: #ffefef;
|
|
92
|
+
}
|
|
84
93
|
.nrdb2-sb-list-header {
|
|
85
94
|
display: flex;
|
|
86
95
|
gap: 6px;
|
|
@@ -312,7 +321,7 @@
|
|
|
312
321
|
* Add Custom Dashboard Side Menu
|
|
313
322
|
* */
|
|
314
323
|
|
|
315
|
-
function
|
|
324
|
+
function dashboardLink (id, name, path) {
|
|
316
325
|
const base = RED.settings.httpNodeRoot || '/'
|
|
317
326
|
const basePart = base.endsWith('/') ? base : `${base}/`
|
|
318
327
|
const dashPart = path.startsWith('/') ? path.slice(1) : path
|
|
@@ -465,6 +474,128 @@
|
|
|
465
474
|
}
|
|
466
475
|
}
|
|
467
476
|
|
|
477
|
+
function addConfigNode (node) {
|
|
478
|
+
if (!node.user) {
|
|
479
|
+
node.users = []
|
|
480
|
+
}
|
|
481
|
+
node.dirty = true
|
|
482
|
+
RED.nodes.add(node)
|
|
483
|
+
RED.editor.validateNode(node)
|
|
484
|
+
RED.history.push({
|
|
485
|
+
t: 'add',
|
|
486
|
+
nodes: [node.id],
|
|
487
|
+
dirty: RED.nodes.dirty()
|
|
488
|
+
})
|
|
489
|
+
RED.nodes.dirty(true)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function mapDefaults (defaults) {
|
|
493
|
+
const values = {}
|
|
494
|
+
for (const key in defaults) {
|
|
495
|
+
if (Object.prototype.hasOwnProperty.call(defaults, key)) {
|
|
496
|
+
values[key] = defaults[key].value
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return values
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function addDefaultPage (baseId, themeId) {
|
|
503
|
+
const page = RED.nodes.getType('ui-page')
|
|
504
|
+
const pageNode = {
|
|
505
|
+
_def: page,
|
|
506
|
+
id: RED.nodes.id(),
|
|
507
|
+
type: 'ui-page',
|
|
508
|
+
...mapDefaults(page.defaults),
|
|
509
|
+
path: '/pageN', // TODO: generate a unique path
|
|
510
|
+
name: 'Page N',
|
|
511
|
+
ui: baseId,
|
|
512
|
+
theme: themeId,
|
|
513
|
+
layout: 'grid'
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
addConfigNode(pageNode)
|
|
517
|
+
return pageNode
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
function addDefaultGroup (pageId) {
|
|
521
|
+
const group = RED.nodes.getType('ui-group')
|
|
522
|
+
const groupNode = {
|
|
523
|
+
_def: group,
|
|
524
|
+
id: RED.nodes.id(),
|
|
525
|
+
type: 'ui-group',
|
|
526
|
+
...mapDefaults(group.defaults),
|
|
527
|
+
name: 'My Group',
|
|
528
|
+
page: pageId
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
addConfigNode(groupNode)
|
|
532
|
+
return groupNode
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
function addDefaultTheme () {
|
|
536
|
+
const theme = RED.nodes.getType('ui-theme')
|
|
537
|
+
const themeNode = {
|
|
538
|
+
_def: theme,
|
|
539
|
+
id: RED.nodes.id(),
|
|
540
|
+
type: 'ui-theme',
|
|
541
|
+
...mapDefaults(theme.defaults),
|
|
542
|
+
name: 'Default Theme'
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
addConfigNode(themeNode)
|
|
546
|
+
return themeNode
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function addLayoutsDefaults () {
|
|
550
|
+
const cNodes = ['ui-base', 'ui-page', 'ui-group', 'ui-theme']
|
|
551
|
+
let exists = false
|
|
552
|
+
RED.nodes.eachConfig((n) => {
|
|
553
|
+
if (cNodes.includes(n.type)) {
|
|
554
|
+
exists = true
|
|
555
|
+
}
|
|
556
|
+
})
|
|
557
|
+
|
|
558
|
+
// check if we haven't got any of these yet
|
|
559
|
+
if (!exists) {
|
|
560
|
+
// Add Single Base Node
|
|
561
|
+
const base = RED.nodes.getType('ui-base')
|
|
562
|
+
const baseNode = {
|
|
563
|
+
_def: base,
|
|
564
|
+
id: RED.nodes.id(),
|
|
565
|
+
type: 'ui-base',
|
|
566
|
+
...mapDefaults(base.defaults),
|
|
567
|
+
name: 'My Dashboard'
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
addConfigNode(baseNode)
|
|
571
|
+
|
|
572
|
+
const theme = addDefaultTheme()
|
|
573
|
+
const page = addDefaultPage(base.id, theme.id)
|
|
574
|
+
const group = addDefaultGroup(page.id)
|
|
575
|
+
|
|
576
|
+
// update existing `ui-` nodes to use the new base/page/theme/group
|
|
577
|
+
RED.nodes.eachNode((node) => {
|
|
578
|
+
if (node.type.startsWith('ui-')) {
|
|
579
|
+
// if node has a group property
|
|
580
|
+
if (hasProperty(node._def.defaults, 'group') && !node.group) {
|
|
581
|
+
// group-scoped widgets - which is most of them
|
|
582
|
+
node.group = group.id
|
|
583
|
+
} else if (hasProperty(node._def.defaults, 'page') && !node.page) {
|
|
584
|
+
// page-scoped widgets
|
|
585
|
+
node.page = page.id
|
|
586
|
+
} else if (hasProperty(node._def.defaults, 'ui') && !node.ui) {
|
|
587
|
+
// base-scoped widgets, e.g. ui-notification/control
|
|
588
|
+
node.ui = baseNode.id
|
|
589
|
+
}
|
|
590
|
+
RED.editor.validateNode(node)
|
|
591
|
+
}
|
|
592
|
+
})
|
|
593
|
+
|
|
594
|
+
RED.view.redraw()
|
|
595
|
+
RED.sidebar.config.refresh()
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
468
599
|
// watch for nodes changed, added, removed - use this to refresh the sidebar
|
|
469
600
|
let refreshBusy = false // this is set/reset inside refreshSidebarEditors
|
|
470
601
|
const refreshSidebarEditorDebounced = debounce(refreshSidebarEditors, 300)
|
|
@@ -478,7 +609,6 @@
|
|
|
478
609
|
const conditionalSidebarRefresh = function (node, eventName) {
|
|
479
610
|
// if the layout editor is not in view, don't refresh
|
|
480
611
|
if ($('#ff-node-red-dashboard').parent().css('display') === 'none') { return }
|
|
481
|
-
if ($('#dashboard-2-pages').css('display') === 'none') { return }
|
|
482
612
|
// if a refresh is in progress, don't refresh
|
|
483
613
|
if (refreshBusy) { return }
|
|
484
614
|
if (RED._db2debug) { console.log('dashboard 2: conditionalSidebarRefresh (node, eventName)', node, eventName) }
|
|
@@ -514,6 +644,7 @@
|
|
|
514
644
|
conditionalSidebarRefresh(event, 'nodes:change')
|
|
515
645
|
})
|
|
516
646
|
|
|
647
|
+
const addLayoutsDefaultsDebounced = debounce(addLayoutsDefaults, 25)
|
|
517
648
|
const checkDuplicateUiBasesDebounced = debounce(checkDuplicateUiBases, 25)
|
|
518
649
|
RED.events.on('nodes:add', function (node) {
|
|
519
650
|
if (RED._db2debug) { console.log('nodes:add', node) }
|
|
@@ -527,6 +658,7 @@
|
|
|
527
658
|
if (node.type.startsWith('ui-')) {
|
|
528
659
|
// action on all ui- elements to ensure we've remapped (now) missing ui-base nodes
|
|
529
660
|
checkDuplicateUiBasesDebounced()
|
|
661
|
+
addLayoutsDefaultsDebounced()
|
|
530
662
|
}
|
|
531
663
|
})
|
|
532
664
|
RED.events.on('nodes:remove', function (event) {
|
|
@@ -538,7 +670,7 @@
|
|
|
538
670
|
* @param {Object} parent - jQuery object to add this button group as a child element to
|
|
539
671
|
* @param {DashboardItem} item - The page/group/widget that these actions are bound to
|
|
540
672
|
*/
|
|
541
|
-
function addRowActions (parent, item) {
|
|
673
|
+
function addRowActions (parent, item, list) {
|
|
542
674
|
const configNodes = ['ui-base', 'ui-page', 'ui-group', 'ui-theme']
|
|
543
675
|
const btnGroup = $('<div>', { class: 'nrdb2-sb-list-header-button-group', id: item.id }).appendTo(parent)
|
|
544
676
|
if (!configNodes.includes(item.type)) {
|
|
@@ -559,6 +691,15 @@
|
|
|
559
691
|
evt.stopPropagation()
|
|
560
692
|
evt.preventDefault()
|
|
561
693
|
})
|
|
694
|
+
if (item.type === 'ui-page') {
|
|
695
|
+
// add the "+ group" button
|
|
696
|
+
$('<a href="#" class="editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-plus"></i> ' + c_('layout.group') + '</a>')
|
|
697
|
+
.click(function (evt) {
|
|
698
|
+
list.editableList('addItem')
|
|
699
|
+
evt.preventDefault()
|
|
700
|
+
})
|
|
701
|
+
.appendTo(btnGroup)
|
|
702
|
+
}
|
|
562
703
|
}
|
|
563
704
|
|
|
564
705
|
/**
|
|
@@ -660,26 +801,34 @@
|
|
|
660
801
|
* @param {DashboardItemLookup} widgetsByGroup - The lookup of widgets by group
|
|
661
802
|
*/
|
|
662
803
|
function addGroupOrderingList (pageId, container, groups, widgetsByGroup) {
|
|
663
|
-
// ordered list of
|
|
804
|
+
// ordered list of groups to live within a container (e.g. page list item)
|
|
664
805
|
const groupsOL = $('<ol>', { class: 'nrdb2-sb-group-list' }).appendTo(container).editableList({
|
|
665
806
|
sortable: '.nrdb2-sb-groups-list-header',
|
|
666
807
|
addButton: false,
|
|
667
808
|
height: 'auto',
|
|
668
809
|
connectWith: '.nrdb2-sb-group-list',
|
|
669
810
|
addItem: function (container, i, group) {
|
|
811
|
+
if (!group || !group.id) {
|
|
812
|
+
console.log('add group', group, 'to', pageId)
|
|
813
|
+
// this is a new page that's been added and we need to setup the basics
|
|
814
|
+
group = addDefaultGroup(pageId)
|
|
815
|
+
RED.editor.editConfig('', group.type, group.id)
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
const widgets = widgetsByGroup[group.id] || []
|
|
670
819
|
const titleRow = $('<div>', { class: 'nrdb2-sb-list-header nrdb2-sb-groups-list-header' }).appendTo(container)
|
|
671
820
|
$('<i class="nrdb2-sb-list-handle nrdb2-sb-group-list-handle fa fa-bars"></i>').appendTo(titleRow)
|
|
672
821
|
const chevron = $('<i class="fa fa-angle-down nrdb2-sb-list-chevron">', { style: 'width:10px;' }).appendTo(titleRow)
|
|
673
822
|
const groupicon = 'fa-table'
|
|
674
823
|
$('<i>', { class: 'nrdb2-sb-icon nrdb2-sb-group-icon fa ' + groupicon }).appendTo(titleRow)
|
|
675
824
|
$('<span>', { class: 'nrdb2-sb-title' }).text(group.name || group.id).appendTo(titleRow)
|
|
825
|
+
$('<span>', { class: 'nrdb2-sb-info' }).text(`${widgets.length} Widgets`).appendTo(titleRow)
|
|
676
826
|
|
|
677
827
|
const actions = $('<div>', { class: 'nrdb2-sb-list-header-actions' }).appendTo(titleRow)
|
|
678
828
|
addRowActions(actions, group)
|
|
679
829
|
addRowStateOptions(actions, group)
|
|
680
830
|
|
|
681
831
|
// adds widgets within this group
|
|
682
|
-
const widgets = widgetsByGroup[group.id] || []
|
|
683
832
|
const widgetsList = $('<div>', { class: 'nrdb2-sb-widget-list-container' }).appendTo(container)
|
|
684
833
|
|
|
685
834
|
// add chevron/list toggle
|
|
@@ -724,6 +873,8 @@
|
|
|
724
873
|
if (RED._db2debug) { if (RED._db2debug) { console.log('dashboard 2: ui_base.html: addGroupOrderingList: adding group', group) } }
|
|
725
874
|
groupsOL.editableList('addItem', group)
|
|
726
875
|
})
|
|
876
|
+
|
|
877
|
+
return groupsOL
|
|
727
878
|
}
|
|
728
879
|
|
|
729
880
|
/**
|
|
@@ -869,12 +1020,21 @@
|
|
|
869
1020
|
.appendTo(buttonGroup)
|
|
870
1021
|
RED.popover.tooltip(buttonExpand, c_('layout.expand'))
|
|
871
1022
|
|
|
1023
|
+
// add page button
|
|
1024
|
+
$('<a href="#" class="editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-plus"></i> ' + c_('layout.page') + '</a>')
|
|
1025
|
+
.click(function (evt) {
|
|
1026
|
+
pagesOL.editableList('addItem')
|
|
1027
|
+
evt.preventDefault()
|
|
1028
|
+
})
|
|
1029
|
+
.appendTo(buttonGroup)
|
|
1030
|
+
|
|
872
1031
|
divTabs.append('<div class="nrdb2-layout-helptext">' + c_('label.layoutMessage') + '</div>')
|
|
873
1032
|
|
|
874
1033
|
/** @type {DashboardItemLookup} */
|
|
875
1034
|
const pages = {}
|
|
876
1035
|
/** @type {DashboardItemLookup} */
|
|
877
1036
|
const groupsByPage = {}
|
|
1037
|
+
const unattachedGroups = []
|
|
878
1038
|
/** @type {DashboardItemLookup} */
|
|
879
1039
|
const widgetsByGroup = {}
|
|
880
1040
|
const subflowDefinitions = new Map()
|
|
@@ -883,11 +1043,16 @@
|
|
|
883
1043
|
if (n.type === 'ui-page' && !!n.ui) {
|
|
884
1044
|
pages[n.id] = toDashboardItem(n)
|
|
885
1045
|
}
|
|
886
|
-
if (n.type === 'ui-group'
|
|
887
|
-
|
|
888
|
-
|
|
1046
|
+
if (n.type === 'ui-group') {
|
|
1047
|
+
const p = n.page
|
|
1048
|
+
if (!p) {
|
|
1049
|
+
unattachedGroups.push(toDashboardItem(n))
|
|
1050
|
+
} else {
|
|
1051
|
+
if (!groupsByPage[p]) {
|
|
1052
|
+
groupsByPage[p] = []
|
|
1053
|
+
}
|
|
1054
|
+
groupsByPage[p].push(toDashboardItem(n))
|
|
889
1055
|
}
|
|
890
|
-
groupsByPage[n.page].push(toDashboardItem(n))
|
|
891
1056
|
}
|
|
892
1057
|
})
|
|
893
1058
|
|
|
@@ -951,27 +1116,34 @@
|
|
|
951
1116
|
sortable: '.nrdb2-sb-pages-list-header',
|
|
952
1117
|
addButton: false,
|
|
953
1118
|
addItem: function (container, i, page) {
|
|
1119
|
+
if (!page || !page.id) {
|
|
1120
|
+
// this is a new page that's been added and we need to setup the basics
|
|
1121
|
+
page = addDefaultPage()
|
|
1122
|
+
RED.editor.editConfig('', page.type, page.id)
|
|
1123
|
+
}
|
|
1124
|
+
const groups = groupsByPage[page.id] || []
|
|
1125
|
+
|
|
954
1126
|
container.addClass('nrdb2-sb-pages-list-item')
|
|
955
1127
|
|
|
956
1128
|
const titleRow = $('<div>', { class: 'nrdb2-sb-list-header nrdb2-sb-pages-list-header' }).appendTo(container)
|
|
1129
|
+
const groupsList = $('<div>', { class: 'nrdb2-sb-group-list-container' }).appendTo(container)
|
|
1130
|
+
|
|
1131
|
+
// build title row
|
|
957
1132
|
$('<i class="nrdb2-sb-list-handle nrdb2-sb-page-list-handle fa fa-bars"></i>').appendTo(titleRow)
|
|
958
1133
|
const chevron = $('<i class="fa fa-angle-down nrdb2-sb-list-chevron">', { style: 'width:10px;' }).appendTo(titleRow)
|
|
959
1134
|
const tabicon = 'fa-object-group'
|
|
960
1135
|
$('<i>', { class: 'nrdb2-sb-icon nrdb2-sb-tab-icon fa ' + tabicon }).appendTo(titleRow)
|
|
961
1136
|
$('<span>', { class: 'nrdb2-sb-title' }).text(page.name || page.id).appendTo(titleRow)
|
|
962
|
-
|
|
963
|
-
// page - actions
|
|
964
|
-
const actions = $('<div>', { class: 'nrdb2-sb-list-header-actions' }).appendTo(titleRow)
|
|
965
|
-
addRowActions(actions, page)
|
|
966
|
-
addRowStateOptions(actions, page)
|
|
1137
|
+
$('<span>', { class: 'nrdb2-sb-info' }).text(`${groups.length} Groups`).appendTo(titleRow)
|
|
967
1138
|
|
|
968
1139
|
// adds groups within this page
|
|
969
|
-
const groups = groupsByPage[page.id] || []
|
|
970
|
-
const groupsList = $('<div>', { class: 'nrdb2-sb-group-list-container' }).appendTo(container)
|
|
971
|
-
|
|
972
1140
|
titleRow.click(titleToggle(page.id, groupsList, chevron))
|
|
1141
|
+
const groupsOL = addGroupOrderingList(page.id, groupsList, groups, widgetsByGroup)
|
|
973
1142
|
|
|
974
|
-
|
|
1143
|
+
// page - actions
|
|
1144
|
+
const actions = $('<div>', { class: 'nrdb2-sb-list-header-actions' }).appendTo(titleRow)
|
|
1145
|
+
addRowActions(actions, page, groupsOL)
|
|
1146
|
+
addRowStateOptions(actions, page)
|
|
975
1147
|
},
|
|
976
1148
|
sortItems: function (items) {
|
|
977
1149
|
// track any changes
|
|
@@ -986,9 +1158,9 @@
|
|
|
986
1158
|
}
|
|
987
1159
|
})
|
|
988
1160
|
|
|
989
|
-
Object.values(
|
|
1161
|
+
Object.values(pages).sort((a, b) => a.order - b.order).forEach(function (page) {
|
|
1162
|
+
const groups = groupsByPage[page.id] || []
|
|
990
1163
|
if (RED._db2debug) { console.log('dashboard 2: ui_base.html: buildLayoutOrderEditor: adding groups', groups) }
|
|
991
|
-
const page = pages[groups[0].page]
|
|
992
1164
|
if (page) {
|
|
993
1165
|
pagesOL.editableList('addItem', page)
|
|
994
1166
|
}
|
|
@@ -997,6 +1169,41 @@
|
|
|
997
1169
|
// })
|
|
998
1170
|
})
|
|
999
1171
|
|
|
1172
|
+
// add Unattached Groups to the bottom
|
|
1173
|
+
if (unattachedGroups.length > 0) {
|
|
1174
|
+
const unattachedGroupsSection = $('<div>', { class: 'nrdb2-sidebar-header', style: 'padding-top: 12px;' }).appendTo(divTabs)
|
|
1175
|
+
$('<b>').html(c_('layout.unattachedGroups')).appendTo(unattachedGroupsSection)
|
|
1176
|
+
divTabs.append('<div class="nrdb2-layout-helptext">' + c_('label.unattachedMessage') + '</div>')
|
|
1177
|
+
|
|
1178
|
+
// we have some groups bound to a page that no longer exists
|
|
1179
|
+
const unattachedGroupsOL = $('<ol>', { class: 'nrdb2-sb-unattached-groups-list' }).appendTo(divTabs).editableList({
|
|
1180
|
+
sortable: '.nrdb2-sb-unattached-groups-list-header',
|
|
1181
|
+
addButton: false,
|
|
1182
|
+
addItem: function (container, i, group) {
|
|
1183
|
+
if (!group || !group.id) {
|
|
1184
|
+
// this is a new group that's been added and we need to setup the basics
|
|
1185
|
+
group = addDefaultGroup()
|
|
1186
|
+
RED.editor.editConfig('', group.type, group.id)
|
|
1187
|
+
}
|
|
1188
|
+
container.addClass('nrdb2-sb-unattached-groups-list-item')
|
|
1189
|
+
|
|
1190
|
+
const titleRow = $('<div>', { class: 'nrdb2-sb-list-header nrdb2-sb-unattached-groups-list-header' }).appendTo(container)
|
|
1191
|
+
const tabicon = 'fa-table'
|
|
1192
|
+
$('<i>', { class: 'nrdb2-sb-icon nrdb2-sb-tab-icon fa ' + tabicon }).appendTo(titleRow)
|
|
1193
|
+
$('<span>', { class: 'nrdb2-sb-title' }).text(group.name || group.id).appendTo(titleRow)
|
|
1194
|
+
$('<span>', { class: 'nrdb2-sb-info' }).text('No Page Assigned').appendTo(titleRow)
|
|
1195
|
+
|
|
1196
|
+
// group - actions
|
|
1197
|
+
const actions = $('<div>', { class: 'nrdb2-sb-list-header-actions' }).appendTo(titleRow)
|
|
1198
|
+
addRowActions(actions, group)
|
|
1199
|
+
}
|
|
1200
|
+
})
|
|
1201
|
+
|
|
1202
|
+
unattachedGroups.forEach(function (group) {
|
|
1203
|
+
unattachedGroupsOL.editableList('addItem', group)
|
|
1204
|
+
})
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1000
1207
|
// call updateLayoutVisibility to sync display level
|
|
1001
1208
|
updateLayoutVisibility(layoutDisplayLevel)
|
|
1002
1209
|
}
|
|
@@ -1009,6 +1216,17 @@
|
|
|
1009
1216
|
const themeHeader = $('<div>', { class: 'nrdb2-sidebar-header' }).appendTo(divTabs)
|
|
1010
1217
|
$('<b>').html(c_('themes.header')).appendTo(themeHeader)
|
|
1011
1218
|
|
|
1219
|
+
// button group
|
|
1220
|
+
const buttonGroup = $('<div>', { class: 'nrdb2-sb-list-button-group' }).appendTo(themeHeader)
|
|
1221
|
+
|
|
1222
|
+
// add theme button
|
|
1223
|
+
$('<a href="#" class="editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-plus"></i> ' + c_('themes.theme') + '</a>')
|
|
1224
|
+
.click(function (evt) {
|
|
1225
|
+
themesOL.editableList('addItem')
|
|
1226
|
+
evt.preventDefault()
|
|
1227
|
+
})
|
|
1228
|
+
.appendTo(buttonGroup)
|
|
1229
|
+
|
|
1012
1230
|
divTabs.append('<div class="nrdb2-layout-helptext">' + c_('label.themingMessage') + '</div>')
|
|
1013
1231
|
|
|
1014
1232
|
const themes = {}
|
|
@@ -1024,6 +1242,11 @@
|
|
|
1024
1242
|
sortable: '.nrdb2-sb-pages-list-header',
|
|
1025
1243
|
addButton: false,
|
|
1026
1244
|
addItem: function (container, i, theme) {
|
|
1245
|
+
if (!theme || !theme.id) {
|
|
1246
|
+
// this is a new theme that's been added and we need to setup the basics
|
|
1247
|
+
theme = addDefaultTheme()
|
|
1248
|
+
RED.editor.editConfig('', theme.type, theme.id)
|
|
1249
|
+
}
|
|
1027
1250
|
container.addClass('nrdb2-sb-pages-list-item')
|
|
1028
1251
|
|
|
1029
1252
|
const titleRow = $('<div>', { class: 'nrdb2-sb-list-header nrdb2-sb-themes-list-header' }).appendTo(container)
|
|
@@ -1108,7 +1331,7 @@
|
|
|
1108
1331
|
RED.nodes.eachConfig(function (n) {
|
|
1109
1332
|
if (n.type === 'ui-base') {
|
|
1110
1333
|
const base = n
|
|
1111
|
-
sidebar.append(
|
|
1334
|
+
sidebar.append(dashboardLink(base.id, base.name, base.path))
|
|
1112
1335
|
const divTab = $('<div class="red-ui-tabs">').appendTo(sidebar)
|
|
1113
1336
|
|
|
1114
1337
|
const ulDashboardTabs = $('<ul id="dashboard-tabs-list"></ul>').appendTo(divTab)
|
|
@@ -8,11 +8,22 @@
|
|
|
8
8
|
},
|
|
9
9
|
// colors
|
|
10
10
|
colors: {
|
|
11
|
-
value:
|
|
11
|
+
value: {
|
|
12
|
+
surface: '#ffffff',
|
|
13
|
+
primary: '#0094CE',
|
|
14
|
+
bgPage: '#eeeeee',
|
|
15
|
+
groupBg: '#ffffff',
|
|
16
|
+
groupOutline: '#cccccc'
|
|
17
|
+
}
|
|
12
18
|
},
|
|
13
19
|
// sizes
|
|
14
20
|
sizes: {
|
|
15
|
-
value:
|
|
21
|
+
value: {
|
|
22
|
+
pagePadding: '12px',
|
|
23
|
+
groupGap: '12px',
|
|
24
|
+
groupBorderRadius: '4px',
|
|
25
|
+
widgetGap: '12px'
|
|
26
|
+
}
|
|
16
27
|
}
|
|
17
28
|
},
|
|
18
29
|
oneditprepare: function () {
|
|
@@ -8,7 +8,13 @@
|
|
|
8
8
|
"autoCalculateColumns": "Auto Calculate Columns",
|
|
9
9
|
"key": "Key",
|
|
10
10
|
"label": "Label",
|
|
11
|
-
"column": "column"
|
|
11
|
+
"column": "column",
|
|
12
|
+
"selection": "Interaction"
|
|
13
|
+
},
|
|
14
|
+
"selection": {
|
|
15
|
+
"none": "None",
|
|
16
|
+
"checkbox": "Checkboxes",
|
|
17
|
+
"click": "Click"
|
|
12
18
|
}
|
|
13
19
|
}
|
|
14
20
|
}
|
|
@@ -21,13 +21,15 @@
|
|
|
21
21
|
},
|
|
22
22
|
height: { value: 0 },
|
|
23
23
|
maxrows: { value: 0, validate: RED.validators.number() },
|
|
24
|
+
passthru: { value: false },
|
|
24
25
|
autocols: { value: true },
|
|
26
|
+
selectionType: { value: 'none' },
|
|
25
27
|
columns: {
|
|
26
28
|
value: null
|
|
27
29
|
}
|
|
28
30
|
},
|
|
29
31
|
inputs: 1,
|
|
30
|
-
outputs:
|
|
32
|
+
outputs: 1,
|
|
31
33
|
outputLabels: function () { return this.mode },
|
|
32
34
|
icon: 'font-awesome/fa-table',
|
|
33
35
|
paletteLabel: 'table',
|
|
@@ -35,6 +37,12 @@
|
|
|
35
37
|
return this.name || 'table'
|
|
36
38
|
},
|
|
37
39
|
oneditprepare: function () {
|
|
40
|
+
// handle backward compatibility
|
|
41
|
+
const validSelectionTypes = ['none', 'checkbox', 'click']
|
|
42
|
+
if (!validSelectionTypes.includes(this.selectionType)) {
|
|
43
|
+
$('#node-input-selectionType').val('none')
|
|
44
|
+
}
|
|
45
|
+
|
|
38
46
|
$('#node-input-size').elementSizer({
|
|
39
47
|
width: '#node-input-width',
|
|
40
48
|
height: '#node-input-height',
|
|
@@ -62,7 +70,7 @@
|
|
|
62
70
|
$('<i style="color: var(--red-ui-form-text-color, #eee); cursor:move; margin-left:3px;" class="node-input-column-handle fa fa-bars"></i>').appendTo(row)
|
|
63
71
|
|
|
64
72
|
$('<input/>', { class: 'node-input-column-key', type: 'text', style: 'margin-left:7px; width:calc(50% - 32px);', placeholder: RED._('@flowfuse/node-red-dashboard/ui-table:ui-table.label.key'), value: col.key }).appendTo(row)
|
|
65
|
-
$('<input/>', { class: 'node-input-column-label', type: 'text', style: 'margin-left:7px; width:calc(50% - 32px);', placeholder: RED._('@flowfuse/node-red-dashboard/ui-table:ui-table.label.label'), value: col.
|
|
73
|
+
$('<input/>', { class: 'node-input-column-label', type: 'text', style: 'margin-left:7px; width:calc(50% - 32px);', placeholder: RED._('@flowfuse/node-red-dashboard/ui-table:ui-table.label.label'), value: col.title }).appendTo(row)
|
|
66
74
|
|
|
67
75
|
const finalSpan = $('<span/>', { style: 'float:right; margin-right:8px;' }).appendTo(row)
|
|
68
76
|
const deleteButton = $('<a/>', { href: '#', class: 'editor-button editor-button-small', style: 'margin-top:7px; margin-left:5px;' }).appendTo(finalSpan)
|
|
@@ -80,7 +88,7 @@
|
|
|
80
88
|
|
|
81
89
|
$('#node-input-add-column').click(function () {
|
|
82
90
|
generateColumn($('#node-input-column-container').children().length + 1, {})
|
|
83
|
-
$('#node-input-column-container-div').scrollTop($('#node-input-column-
|
|
91
|
+
$('#node-input-column-container-div').scrollTop($('#node-input-column-container-div').get(0).scrollHeight)
|
|
84
92
|
})
|
|
85
93
|
|
|
86
94
|
for (let i = 0; i < this.columns?.length; i++) {
|
|
@@ -130,6 +138,14 @@
|
|
|
130
138
|
<label for="node-input-maxrows"><i class="fa fa-tag"></i> <span data-i18n="ui-table.label.maxRows"></label>
|
|
131
139
|
<input type="number" id="node-input-maxrows">
|
|
132
140
|
</div>
|
|
141
|
+
<div class="form-row">
|
|
142
|
+
<label for="node-input-selectionType"><i class="fa fa-crosshairs"></i> <span data-i18n="ui-table.label.selection"></span></label>
|
|
143
|
+
<select id="node-input-selectionType">
|
|
144
|
+
<option value="none" data-i18n="ui-table.selection.none"></option>
|
|
145
|
+
<option value="click" data-i18n="ui-table.selection.click"></option>
|
|
146
|
+
<option value="checkbox" data-i18n="ui-table.selection.checkbox"></option>
|
|
147
|
+
</select>
|
|
148
|
+
</div>
|
|
133
149
|
<div class="form-row" style="display:flex;">
|
|
134
150
|
<label for="node-input-width" style="vertical-align:top"><i class="fa fa-list-alt"></i> <span data-i18n="ui-table.label.columns"></label>
|
|
135
151
|
<div class="form-row node-input-column-container-row" style="margin-bottom: 0px; width:calc(70% + 15px);">
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const datastore = require('../store/data.js')
|
|
2
|
+
|
|
1
3
|
module.exports = function (RED) {
|
|
2
4
|
function TableNode (config) {
|
|
3
5
|
const node = this
|
|
@@ -21,7 +23,14 @@ module.exports = function (RED) {
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
// inform the dashboard UI that we are adding this node
|
|
24
|
-
group.register(node, config
|
|
26
|
+
group.register(node, config, {
|
|
27
|
+
onAction: true,
|
|
28
|
+
onInput: function (msg) {
|
|
29
|
+
// store the latest msg passed to node
|
|
30
|
+
datastore.save(group.getBase(), node, msg)
|
|
31
|
+
// do nothing else - do not pass the message on
|
|
32
|
+
}
|
|
33
|
+
})
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
RED.nodes.registerType('ui-table', TableNode)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowfuse/node-red-dashboard",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2-603b043-202403211300.0",
|
|
4
4
|
"description": "Dashboard 2.0 - A collection of Node-RED nodes that provide functionality to build your own UI applications (inc. forms, buttons, charts).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node-red"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function t(r){return typeof r=="object"&&"length"in r?r:Array.from(r)}export{t as a};
|