node-red-dashboard
Version:
A set of dashboard nodes for Node-RED
968 lines (918 loc) • 125 kB
HTML
<style>
.nr-db-sb {
position: absolute;
top: 1px;
bottom: 2px;
left: 1px;
right: 1px;
overflow-y: scroll;
padding: 10px;
}
.nr-db-sb .form-row label {
display: block;
width: auto;
}
.nr-db-sb .form-row input,
.nr-db-sb .form-row select {
width: calc(100% - 100px);
margin-bottom:0;
}
.nr-db-sb .compact {
margin-bottom: 8px !important;
}
.nr-db-sb .red-ui-editableList-container {
padding: 0;
min-height: 250px;
height: auto;
}
.nr-db-sb-tab-list {
min-height: 250px;
height: auto;
}
.nr-db-sb-tab-list li {
padding: 0;
}
.nr-db-sb-tab-list-item {
border-radius: 4px;
color: #333;
}
.nr-db-sb-list-header {
cursor: pointer;
position:relative;
color: #666;
padding:3px;
white-space: nowrap;
}
.nr-db-sb-list-header:hover {
color: #333;
}
.nr-db-sb-tab-list-header {
background: #f3f3f3;
padding:5px;
}
.nr-db-sb-group-list-header:hover,
.nr-db-sb-widget-list-header:hover {
background: #f9f9f9;
}
.nr-db-sb-list-chevron {
width: 15px;
text-align: center;
margin: 3px 5px 3px 5px;
}
.nr-db-sb-tab-list-item .red-ui-editableList-container {
border-radius: 0;
border: none;
height: auto !important;
min-height: unset;
}
.nr-db-sb-list-handle {
vertical-align: top;
opacity: 0;
cursor: move;
}
.nr-db-sb-list-header:hover>.nr-db-sb-list-handle,
.nr-db-sb-list-header:hover>.nr-db-sb-list-header-button-group {
opacity: 1;
}
.nr-db-sb-list-header-button-group {
opacity: 0;
}
.nr-db-sb-list-handle {
color: #bbb;
padding:5px;
}
.nr-db-sb-tab-list-header>.nr-db-sb-list-chevron {
margin-left: 0px;
transition: transform 0.2s ease-in-out;
}
.nr-db-sb-group-list-header>.nr-db-sb-list-chevron {
margin-left: 20px;
transition: transform 0.2s ease-in-out;
}
.nr-db-sb-group-list {
min-height: 10px;
}
.nr-db-sb-group-list li {
border-bottom-color: #eee;
}
.nr-db-sb-group-list>li.ui-sortable-helper {
border-top: 1px solid #eee;
}
.nr-db-sb-group-list>li:last-child {
border-bottom: none;
}
.nr-db-sb-widget-list>li {
border: none !important;
}
.nr-db-sb-group-list>li>.red-ui-editableList-item-handle {
left: 10px;
}
.nr-db-sb-list-button-group {
position: absolute;
right: 3px;
top: 0px;
z-index: 2;
}
.nr-db-sb-list-header-button-group {
position: absolute;
right: 3px;
top: 4px;
}
.nr-db-sb-list-header-button {
margin-left: 5px;
}
.nr-db-sb li.ui-sortable-helper {
opacity: 0.9;
}
.nr-db-sb-widget-icon {
margin-left: 56px;
}
.nr-db-sb-icon {
margin-right: 10px;
}
.nr-db-sb-link {
display: inline-block;
padding-left: 20px;
}
.nr-db-sb-link-name-container .fa-external-link {
margin-right: 10px;
}
.nr-db-sb-link-url {
font-size: 0.8em;
color: #999;
}
span.nr-db-color-pick-container {
max-width: 50px;
border-radius: 3px;
margin-left: 15px;
}
input.nr-db-field-themeColor {
width: 60px !important;
padding: 0px;
height: 20px;
border: none;
box-shadow: none;
position: absolute;
right: 36px;
border-radius: 3px !important;
border: solid 1px #ccc;
-webkit-appearance: none;
font-size: smaller;
text-align: center;
}
input.nr-db-field-themeColor::-webkit-color-swatch {
border: none;
}
.red-ui-tabs {
margin-bottom: 15px;
}
.red-ui-tab.hidden {
display: none;;
}
#dashboard-tabs-list li a:hover {
cursor: pointer;
}
#dash-link-button {
background: none;
border: none;
margin-top: 3px;
display: inline-block;
margin: 3px 0px 0px 3px;
height: 32px;
line-height: 29px;
max-width: 200px;
overflow: hidden;
white-space: nowrap;
position: relative;
padding: 0px 7px 0px 7px;
}
/*#dash-link-button:hover {
background-color: #eee;
}*/
ul.red-ui-dashboard-theme-styles {
list-style: none;
}
ul.red-ui-dashboard-theme-styles li {
margin-bottom: 10px;
}
.nr-db-resetIcon {
margin: 3px 6px 0px 6px;
float: right;
color: grey;
opacity: 0.8;
display: block;
}
.nr-db-resetIcon:hover {
cursor: pointer;
}
#nr-db-field-font {
margin-left: 2em;
width: calc(100% - 81px);
}
.nr-db-theme-label {
font-weight: bold;
}
#custom-theme-library-container .btn-group {
margin-bottom: 10px;
}
</style>
<script type="text/javascript">
(function($) {
var editSaveEventHandler;
var nodesAddEventHandler;
var nodesRemoveEventHandler;
var uip = 'ui';
var attemptedVendorLoad = false;
var loadTinyColor = function(path) {
$.ajax({ url: path,
success: function (data) {
var jsScript = document.createElement("script");
jsScript.type = "application/javascript";
jsScript.src = path;
document.body.appendChild(jsScript);
//console.log('Tiny Color Loaded:',path);
},
error: function (xhr, ajaxOptions, thrownError) {
if (xhr.status === 404 && !attemptedVendorLoad) {
loadTinyColor('/'+uip+'/vendor/tinycolor2/dist/tinycolor-min.js');
attemptedVendorLoad = true;
}
}
});
}
// convert to i18 text
function c_(x) {
return RED._("node-red-dashboard/ui_base:ui_base."+x);
}
// Try to load dist version first
// then if fails, load non dist version
loadTinyColor('ui_base/js/tinycolor-min.js');
//loadTinyColor('ui_base/tinycolor2/dist/tinycolor-min.js');
RED.nodes.registerType('ui_base',{
category: 'config',
defaults: {
name: {},
theme: {},
site: {}
},
hasUsers: false,
paletteLabel: 'Dashboard',
label: function() { return this.name || 'Node-RED Dashboard'; },
labelStyle: function() { return this.name?"node_label_italic":""; },
onpaletteremove: function() {
RED.sidebar.removeTab("dashboard");
RED.events.off("editor:save",editSaveEventHandler);
RED.events.off("nodes:add",nodesAddEventHandler);
RED.events.off("nodes:remove",nodesRemoveEventHandler);
},
onpaletteadd: function() {
var globalDashboardNode = null;
var editor;
var baseStyles = ['base-color'];
var configurableStyles = ['page-titlebar-backgroundColor', 'page-backgroundColor', 'page-sidebar-backgroundColor',
'group-textColor', 'group-borderColor', 'group-backgroundColor',
'widget-textColor', 'widget-backgroundColor','widget-borderColor'];
var baseFontName = "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif";
var aTheme = {primary:"indigo", accents:"blue", warn:"red", background:"grey"};
// tiny colour implementation
var colours = {
leastReadable: function(base, colours) {
var least = tinycolor.readability(base, colours[0]);
var leastColor = colours[0];
for (var i=1; i<colours.length; i++) {
var readability = tinycolor.readability(base, colours[i]);
if (readability < least) {
least = readability;
leastColor = colours[i];
}
}
return leastColor;
},
whiteGreyMostReadable: function (base) {
var rgb = tinycolor(base).toRgb();
var level = ((rgb.r*299) + (rgb.g*587) + (rgb.b*114))/1000;
var readable = (level >= 128) ? '#111111' : '#eeeeee';
return readable;
},
whiteBlackLeastReadable: function(base) {
return this.leastReadable(base, ["#000000", "#ffffff"]);
},
calculate_page_backgroundColor: function(base) {
var pageBackground = "#fafafa";
var theme = "light";
if (globalDashboardNode && globalDashboardNode.hasOwnProperty("theme") && globalDashboardNode.theme.hasOwnProperty("name")) {
theme = globalDashboardNode.theme.name.split('-')[1];
}
if (theme === "dark") {
pageBackground = "#111111";
}
else if (theme === "custom") {
var whiteOrBlack = this.whiteBlackLeastReadable(base);
if (whiteOrBlack === "#000000") { pageBackground = "#111111"; }
}
return pageBackground;
},
calculate_page_sidebar_backgroundColor: function(base) {
return this.whiteBlackLeastReadable(base);
},
calculate_page_titlebar_backgroundColor: function(base) {
return base;
},
calculate_group_textColor: function(base) {
var groupTextColour = tinycolor(base).lighten(15).toHexString();
//if (this.whiteBlackLeastReadable(base) === "#ffffff") { groupTextColour = "#000000"; }
return groupTextColour;
},
calculate_group_backgroundColor: function(base) {
var groupBackground = "#ffffff";
var theme = "light";
if (globalDashboardNode && globalDashboardNode.hasOwnProperty("theme") && globalDashboardNode.theme.hasOwnProperty("name")) {
theme = globalDashboardNode.theme.name.split('-')[1];
}
if (theme === "dark") {
groupBackground = "#333333";
}
else if (theme === "custom") {
var whiteOrBlack = this.whiteBlackLeastReadable(base);
if (whiteOrBlack === "#000000") { groupBackground = "#333333"; }
}
return groupBackground;
},
calculate_group_borderColor: function(base) {
var groupBackground = this.calculate_group_backgroundColor(base);
return this.leastReadable(groupBackground, ["#ffffff", "#555555"]);
},
calculate_widget_textColor: function(base) {
//most readable against group background
var groupBackground = this.calculate_group_backgroundColor(base);
return tinycolor.mostReadable(groupBackground, ["#111111", "#eeeeee"]).toHexString();
},
calculate_widget_backgroundColor: function(base) {
//return tinycolor(base).darken(5).toHexString()
return tinycolor(base).toHexString();
},
calculate_widget_borderColor: function(base) {
var widgetBorder = "#ffffff";
var theme = "light";
if (globalDashboardNode && globalDashboardNode.hasOwnProperty("theme") && globalDashboardNode.theme.hasOwnProperty("name")) {
theme = globalDashboardNode.theme.name.split('-')[1];
}
if (theme === "dark") {
widgetBorder = "#333333";
}
else if (theme === "custom") {
var whiteOrBlack = this.whiteBlackLeastReadable(base);
if (whiteOrBlack === "#000000") { widgetBorder = "#333333"; }
}
return widgetBorder;
},
calculate_base_font: function(base) {
return baseFontName;
}
}
var sizes = {
sx: 48, // width of <1> grid square
sy: 48, // height of <1> grid square
gx: 6, // gap between groups
gy: 6, // gap between groups
cx: 6, // gap between components
cy: 6, // gap between components
px: 0, // padding of group's cards
py: 0 // padding of group's cards
};
function ensureDashboardNode(createMissing) {
if (globalDashboardNode !== null) {
// Check if it has been deleted beneath us
var n = RED.nodes.node(globalDashboardNode.id);
if (n === null) { globalDashboardNode = null; }
}
// Find the old dashboard node
if (globalDashboardNode === null) {
var bases = [];
RED.nodes.eachConfig(function(n) {
if (n.type === 'ui_base') { bases.push(n); }
});
// make sure we only have one ui_base node
// at the moment this will just use our existing one - deleting any new base node and theme
// at some point we may want to make this an option to select one or the other.
while (bases.length > 1) {
var n = bases.pop();
RED.nodes.remove(n.id);
RED.nodes.dirty(true);
}
if (bases.length === 1) { globalDashboardNode = bases[0]; }
// If there is no dashboard node, ensure we create it after
// initialising
var noDashboardNode = (globalDashboardNode === null);
// set up theme state
var themeState = {};
var baseColor = "#0094CE"
for (var i=0; i<baseStyles.length; i++) {
themeState[baseStyles[i]] = { default:baseColor, value:baseColor, edited:false };
}
for (var j = 0; j < configurableStyles.length; j++) {
var underscore = configurableStyles[j].split("-").join("_");
var colour = colours['calculate_'+underscore](baseColor);
themeState[configurableStyles[j]] = {value:colour, edited:false};
}
themeState["base-font"] = {value:baseFontName};
var missingFields = (!globalDashboardNode || !globalDashboardNode.theme || !globalDashboardNode.site || !globalDashboardNode.site.sizes );
if (missingFields && createMissing) {
var lightTheme = {
default: baseColor,
baseColor: baseColor,
baseFont: baseFontName,
edited: false
}
var darkTheme = {
default: "#097479",
baseColor: "#097479",
baseFont: baseFontName,
edited: false
}
var customTheme = {
name: 'Untitled Theme 1',
default: "#4B7930",
baseColor: "#4B7930",
baseFont: baseFontName
}
var oldThemeName;
if (globalDashboardNode && typeof(globalDashboardNode.theme === 'string')) { oldThemeName = globalDashboardNode.theme; }
var theme = {
name: oldThemeName || "theme-light",
lightTheme: lightTheme,
darkTheme: darkTheme,
customTheme: customTheme,
themeState: themeState,
angularTheme: aTheme
}
var site_name = c_("site.title");
var site_date_format = c_("site.date-format");
var site = { name:site_name, hideToolbar:"false", allowSwipe:"false", lockMenu:"false", allowTempTheme:"true", dateFormat:site_date_format, sizes:sizes };
if (globalDashboardNode !== null) {
if (typeof globalDashboardNode.site !== "undefined") {
site = {
name: globalDashboardNode.site.name || globalDashboardNode.name,
hideToolbar: globalDashboardNode.site.hideToolbar,
lockMenu: globalDashboardNode.site.lockMenu,
allowSwipe: globalDashboardNode.site.allowSwipe,
allowTempTheme: globalDashboardNode.site.allowTempTheme,
dateFormat: globalDashboardNode.site.dateFormat,
sizes: globalDashboardNode.site.sizes
}
}
if (globalDashboardNode.theme.hasOwnProperty("angularTheme")) {
aTheme = globalDashboardNode.theme.angularTheme;
}
else { globalDashboardNode.theme.angularTheme = aTheme; }
}
if (noDashboardNode) {
globalDashboardNode = {
id: RED.nodes.id(),
_def: RED.nodes.getType("ui_base"),
type: "ui_base",
site: site,
theme: theme,
users: []
}
RED.nodes.add(globalDashboardNode);
}
else {
globalDashboardNode["_def"] = RED.nodes.getType("ui_base");
globalDashboardNode.site = site;
globalDashboardNode.theme = theme;
delete globalDashboardNode.name;
}
$("#nr-db-field-font").val(baseFontName);
RED.nodes.dirty(true);
}
}
}
var content = $("<div>").css({"position":"relative","height":"100%"});
var mainContent = $("<div>",{class:"nr-db-sb"}).appendTo(content);
var form = $('<form class="dialog-form">').appendTo(mainContent);
// Dashboard Tabs markup
var divTab = $('<div class="red-ui-tabs">').appendTo(form);
var ulDashboardTabs = $('<ul id="dashboard-tabs-list"></ul>').appendTo(divTab);
var layout_label = c_("label.layout");
var site_label = c_("label.site");
var theme_label = c_("label.theme");
var angular_label = c_("label.angular");
var liLayoutTab = $('<li class="red-ui-tab" style="width:70px;"><a class="red-ui-tab-label" title="Layout"><span>'+layout_label+'</span></a></li>').appendTo(ulDashboardTabs);
var liSiteTab = $('<li class="red-ui-tab" style="width:70px;"><a class="red-ui-tab-label" title="Site" style="width:60px;"><span>'+site_label+'</span></a></li>').appendTo(ulDashboardTabs);
var liThemeTab = $('<li class="red-ui-tab" style="width:70px;"><a class="red-ui-tab-label" title="Theme" style="width:80px;"><span>'+theme_label+'</span></a></li>').appendTo(ulDashboardTabs);
var liAngularTab = $('<li class="red-ui-tab" style="width:70px;"><a class="red-ui-tab-label" title="Angular" style="width:80px;"><span>'+angular_label+'</span></a></li>').appendTo(ulDashboardTabs);
// Link out to dashboard
$.getJSON('uisettings',function(data) {
if (data.hasOwnProperty("path")) { uip = data.path; }
var lnk = document.location.host+RED.settings.httpNodeRoot+"/"+uip;
var re = new RegExp('\/{1,}','g');
lnk = lnk.replace(re,'/');
if (!RED.hasOwnProperty("actions")) {
RED.keyboard.add("*",/* d */ 68,{ctrl:true, shift:true},function() { window.open(document.location.protocol+"//"+lnk) });
}
else {
RED.keyboard.add("*","ctrl-shift-d","dashboard:show-dashboard");
RED.actions.add("dashboard:show-dashboard",function() { window.open(document.location.protocol+"//"+lnk) });
}
$('<span id="dash-link-button" class="editor-button" style="position:absolute; right:0px;"><i class="fa fa-external-link"></i></span>')
.click(function(evt) {
window.open(document.location.protocol+"//"+lnk);
evt.preventDefault();
})
.appendTo(ulDashboardTabs);
});
// Dashboard Tab containers
var layoutTab = $('<div id="dashboard-layout" style="height:calc(100% - 48px)">').appendTo(form);
var siteTab = $('<div id="dashboard-site" style="display:none;">').appendTo(form);
var themeTab = $('<div id="dashboard-theme" style="display:none;">').appendTo(form);
var angularTab = $('<div id="dashboard-angular" style="display:none;">').appendTo(form);
ulDashboardTabs.children().first().addClass("active");
// Tab logic
var onTabClick = function() {
//Toggle tabs
ulDashboardTabs.children().removeClass("active");
ulDashboardTabs.children().css({"transition": "width 100ms"});
$(this).parent().addClass("active");
var selectedTab = $(this)[0].title;
if (selectedTab === 'Layout') {
themeTab.hide();
siteTab.hide();
angularTab.hide();
layoutTab.show();
}
else if (selectedTab === 'Angular') {
themeTab.hide();
siteTab.hide();
angularTab.show();
layoutTab.hide();
}
else if (selectedTab === 'Theme') {
layoutTab.hide();
siteTab.hide();
angularTab.hide();
themeTab.show();
if ($("#nr-db-field-theme option:selected").val() === 'theme-custom') { themeSettingsContainer.show(); }
else { themeSettingsContainer.hide(); }
}
else {
layoutTab.hide();
themeTab.hide();
angularTab.hide();
siteTab.show();
}
}
ulDashboardTabs.find("li.red-ui-tab a").on("click",onTabClick)
// Site Tab
var divTitle = $('<div>',{class:"form-row compact"}).appendTo(siteTab);
$('<div>').html('<b>'+c_("label.title")+'</b>').appendTo(divTitle);
$('<input type="text" id="nr-db-field-title">').val(site_name).css("width","100%")
.change(function() {
if (!globalDashboardNode || globalDashboardNode.site.name !== $(this).val()) {
ensureDashboardNode(true);
globalDashboardNode.site.name = $(this).val();
RED.nodes.dirty(true);
}
})
.appendTo(divTitle);
var divHideToolbar = $('<div>',{class:"form-row compact"}).appendTo(siteTab);
$('<div>').html('<b>'+c_("label.options")+'</b>').appendTo(divHideToolbar);
$('<select id="nr-db-field-hideToolbar">')
.css("width","100%")
.append($('<option>', { value:"false", text:c_("title-bar.show"), selected:true }))
.append($('<option>', { value:"true", text:c_("title-bar.hide") }))
.val("false")
.change(function() {
if (!globalDashboardNode || globalDashboardNode.site.hideToolbar !== $(this).val()) {
ensureDashboardNode(true);
globalDashboardNode.site.hideToolbar = $(this).val();
RED.nodes.dirty(true);
}
})
.appendTo(divHideToolbar);
var divLockMenu = $('<div>',{class:"form-row compact"}).appendTo(siteTab);
$('<select id="nr-db-field-lockMenu">')
.css("width","100%")
.append($('<option>', { value:"false", text:c_("lock.clicked"), selected:true }))
.append($('<option>', { value:"true", text:c_("lock.locked") }))
.val("false")
.change(function() {
if (!globalDashboardNode || globalDashboardNode.site.lockMenu !== $(this).val()) {
ensureDashboardNode(true);
globalDashboardNode.site.lockMenu = $(this).val();
RED.nodes.dirty(true);
}
})
.appendTo(divLockMenu);
var divAllowSwipe = $('<div>',{class:"form-row compact"}).appendTo(siteTab);
$('<select id="nr-db-field-allowSwipe">')
.css("width","100%")
.append($('<option>', { value:"false", text:c_("swipe.no-swipe"), selected:true }))
.append($('<option>', { value:"true", text:c_("swipe.allow-swipe") }))
.val("false")
.change(function() {
if (!globalDashboardNode || globalDashboardNode.site.allowSwipe !== $(this).val()) {
ensureDashboardNode(true);
globalDashboardNode.site.allowSwipe = $(this).val();
RED.nodes.dirty(true);
}
})
.appendTo(divAllowSwipe);
var divAllowTempTheme = $('<div>',{class:"form-row compact"}).appendTo(siteTab);
$('<select id="nr-db-field-allowTempTheme">')
.css("width","100%")
.append($('<option>', { value:"true", text:c_("temp.allow-theme"), selected:true }))
.append($('<option>', { value:"false", text:c_("temp.no-theme") }))
.append($('<option>', { value:"none", text:c_("temp.none") }))
.val("true")
.change(function() {
if (!globalDashboardNode || globalDashboardNode.site.allowTempTheme !== $(this).val()) {
ensureDashboardNode(true);
globalDashboardNode.site.allowTempTheme = $(this).val();
RED.nodes.dirty(true);
}
if ($('#nr-db-field-allowTempTheme').val() === "none") {
ulDashboardTabs.children().eq(2).addClass("hidden");
ulDashboardTabs.children().eq(3).removeClass("hidden");
}
else {
ulDashboardTabs.children().eq(2).removeClass("hidden");
ulDashboardTabs.children().eq(3).addClass("hidden");
}
})
.appendTo(divAllowTempTheme);
var site_name = c_("site.title");
var site_date_format = c_("site.date-format");
var divDateFormat = $('<div>',{class:"form-row"}).appendTo(siteTab);
$('<div>').html('<b>'+c_("label.date-format")+'</b>')
.css("width","80%")
.css("display","inline-block")
.appendTo(divDateFormat);
$('<div>').html("<a href='https://momentjs.com/docs/#/displaying/format/' target='_new'><i class='fa fa-info-circle' style='color:grey;'></i></a>")
.css("display","inline-block")
.css("margin-right","6px")
.css("float","right")
.appendTo(divDateFormat);
$('<input type="text" id="nr-db-field-dateFormat">').val(site_date_format).css("width","100%")
.change(function() {
if (!globalDashboardNode || globalDashboardNode.site.dateFormat !== $(this).val()) {
ensureDashboardNode(true);
globalDashboardNode.site.dateFormat = $(this).val();
RED.nodes.dirty(true);
}
})
.appendTo(divDateFormat);
var divSetSizes = $('<div>',{class:"form-row"}).appendTo(siteTab);
$('<span style="width:45%; display:inline-block">').html('<b>'+c_("label.sizes")+'</b>').appendTo(divSetSizes);
$('<span style="width:25%; display:inline-block; font-size:smaller">').html(c_("label.horizontal")).appendTo(divSetSizes);
$('<span style="width:20%; display:inline-block; font-size:smaller">').html(c_("label.vertical")).appendTo(divSetSizes);
$('<i id="sizes-reset" class="fa fa-undo nr-db-resetIcon"></i>')
.css({opacity:1.0})
.click(function(e) {
$("#nr-db-field-sx").val(sizes.sx); globalDashboardNode.site.sizes.sx = sizes.sx;
$("#nr-db-field-sy").val(sizes.sy); globalDashboardNode.site.sizes.sy = sizes.sy;
$("#nr-db-field-px").val(sizes.px); globalDashboardNode.site.sizes.px = sizes.px;
$("#nr-db-field-py").val(sizes.py); globalDashboardNode.site.sizes.py = sizes.py;
$("#nr-db-field-gx").val(sizes.gx); globalDashboardNode.site.sizes.gx = sizes.gx;
$("#nr-db-field-gy").val(sizes.gy); globalDashboardNode.site.sizes.gy = sizes.gy;
$("#nr-db-field-cx").val(sizes.cx); globalDashboardNode.site.sizes.cx = sizes.cx;
$("#nr-db-field-cy").val(sizes.cy); globalDashboardNode.site.sizes.cy = sizes.cy;
RED.nodes.dirty(true);
})
.appendTo(divSetSizes);
$('<br/><span style="width:45%; display:inline-block">').html(c_("label.widget-size")).appendTo(divSetSizes);
$('<input type="number" name="sx" min="24" id="nr-db-field-sx">').val(48).css("width","20%")
.change(function() { ensureDashboardNode(true); globalDashboardNode.site.sizes.sx=Number($(this).val()); RED.nodes.dirty(true); } )
.appendTo(divSetSizes);
$('<span style="width:5%; display:inline-block">').text(' ').appendTo(divSetSizes);
$('<input type="number" name="sy" min="24" id="nr-db-field-sy">').val(48).css("width","20%")
.change(function() { ensureDashboardNode(true); globalDashboardNode.site.sizes.sy=Number($(this).val()); RED.nodes.dirty(true); } )
.appendTo(divSetSizes);
$('<br/><span style="width:45%; display:inline-block">').html(c_("label.widget-spacing")).appendTo(divSetSizes);
$('<input type="number" name="cx" min="0" id="nr-db-field-cx">').val(6).css("width","20%")
.change(function() { ensureDashboardNode(true); globalDashboardNode.site.sizes.cx=Number($(this).val()); RED.nodes.dirty(true); } )
.appendTo(divSetSizes);
$('<span style="width:5%; display:inline-block">').text(' ').appendTo(divSetSizes);
$('<input type="number" name="cy" min="0" id="nr-db-field-cy">').val(6).css("width","20%")
.change(function() { ensureDashboardNode(true); globalDashboardNode.site.sizes.cy=Number($(this).val()); RED.nodes.dirty(true); } )
.appendTo(divSetSizes);
$('<br/><span style="width:45%; display:inline-block">').html(c_("label.group-padding")).appendTo(divSetSizes);
$('<input type="number" name="px" min="0" id="nr-db-field-px">').val(0).css("width","20%")
.change(function() { ensureDashboardNode(true); globalDashboardNode.site.sizes.px=Number($(this).val()); RED.nodes.dirty(true); } )
.appendTo(divSetSizes);
$('<span style="width:5%; display:inline-block">').text(' ').appendTo(divSetSizes);
$('<input type="number" name="py" min="0" id="nr-db-field-py">').val(0).css("width","20%")
.change(function() { ensureDashboardNode(true); globalDashboardNode.site.sizes.py=Number($(this).val()); RED.nodes.dirty(true); } )
.appendTo(divSetSizes);
$('<br/><span style="width:45%; display:inline-block">').html(c_("label.group-spacing")).appendTo(divSetSizes);
$('<input type="number" name="gx" min="0" id="nr-db-field-gx">').val(6).css("width","20%")
.change(function() { ensureDashboardNode(true); globalDashboardNode.site.sizes.gx=Number($(this).val()); RED.nodes.dirty(true); } )
.appendTo(divSetSizes);
$('<span style="width:5%; display:inline-block">').text(' ').appendTo(divSetSizes);
$('<input type="number" name="gy" min="0" id="nr-db-field-gy">').val(6).css("width","20%")
.change(function() { ensureDashboardNode(true); globalDashboardNode.site.sizes.gy=Number($(this).val()); RED.nodes.dirty(true); } )
.appendTo(divSetSizes);
// Angular Theme Tab
var changed = function() {
ensureDashboardNode(true);
globalDashboardNode.theme.angularTheme = aTheme;
RED.nodes.dirty(true);
}
var angColorList = ["red", "pink", "purple", "deep-purple", "indigo", "blue", "light-blue", "cyan", "teal", "green", "light-green", "lime", "yellow", "amber", "orange", "deep-orange", "brown", "grey", "blue-grey"];
var angColors = "";
angColorList.forEach(function(c) { angColors += '<option value="' + c + '">' + c + '</option>'; });
var divPrimStyle = $('<div>',{class:"form-row"}).appendTo(angularTab);
$('<span style="width:45%; display:inline-block">')
.html('<b>'+c_("style.primary")+'</b>')
.appendTo(divPrimStyle);
$('<i id="ang-reset" class="fa fa-undo nr-db-resetIcon"></i>')
.css({opacity:1.0})
.click(function(e) {
$("#nr-db-field-angPrimary").val("indigo"); globalDashboardNode.theme.angularTheme.primary = "indigo";
RED.nodes.dirty(true);
})
.appendTo(divPrimStyle);
$('<select id="nr-db-field-angPrimary">'+angColors+'</select>')
.css("width","100%")
.val(aTheme.primary)
.change(function() { aTheme.primary = $(this).val(); changed(); })
.appendTo(divPrimStyle);
var divAccStyle = $('<div>',{class:"form-row"}).appendTo(angularTab);
$('<span style="width:45%; display:inline-block">')
.html('<b>'+c_("style.accents")+'</b>')
.appendTo(divAccStyle);
$('<i id="ang-reset" class="fa fa-undo nr-db-resetIcon"></i>')
.css({opacity:1.0})
.click(function(e) {
$("#nr-db-field-angAccents").val("blue"); globalDashboardNode.theme.angularTheme.accents = "blue";
RED.nodes.dirty(true);
})
.appendTo(divAccStyle);
$('<select id="nr-db-field-angAccents">'+angColors+'</select>')
.css("width","100%")
.val(aTheme.accents)
.change(function() { aTheme.accents = $(this).val(); changed(); })
.appendTo(divAccStyle);
var divWarnStyle = $('<div>',{class:"form-row"}).appendTo(angularTab);
$('<span style="width:45%; display:inline-block">')
.html('<b>'+c_("style.warnings")+'</b>')
.appendTo(divWarnStyle);
$('<i id="ang-reset" class="fa fa-undo nr-db-resetIcon"></i>')
.css({opacity:1.0})
.click(function(e) {
$("#nr-db-field-angWarn").val("red"); globalDashboardNode.theme.angularTheme.warn = "red";
RED.nodes.dirty(true);
})
.appendTo(divWarnStyle);
$('<select id="nr-db-field-angWarn">'+angColors+'</select>')
.css("width","100%")
.val(aTheme.warn)
.change(function() { aTheme.warn = $(this).val(); changed(); })
.appendTo(divWarnStyle);
var divBackStyle = $('<div>',{class:"form-row"}).appendTo(angularTab);
$('<span style="width:45%; display:inline-block">')
.html('<b>'+c_("style.background")+'</b>')
.appendTo(divBackStyle);
$('<i id="ang-reset" class="fa fa-undo nr-db-resetIcon"></i>')
.css({opacity:1.0})
.click(function(e) {
$("#nr-db-field-angBackground").val("grey"); globalDashboardNode.theme.angularTheme.background = "grey";
RED.nodes.dirty(true);
})
.appendTo(divBackStyle);
$('<select id="nr-db-field-angBackground">'+angColors+'</select>')
.css("width","100%")
.val(aTheme.background)
.change(function() { aTheme.background = $(this).val(); changed(); })
.appendTo(divBackStyle);
var divPalStyle = $('<div>',{class:"form-row"}).appendTo(angularTab);
$('<span style="width:45%; display:inline-block">')
.html('<b>'+c_("style.palette")+'</b>')
.appendTo(divPalStyle);
var lightdark = '<option value="light">' +c_("style.light")+ '</option>';
lightdark += '<option value="dark">' +c_("style.dark")+ '</option>';
$('<select id="nr-db-field-angLook">'+lightdark+'</select>')
.css("width","100%")
.val(aTheme.palette || "light")
.change(function() { aTheme.palette = $(this).val(); changed(); })
.appendTo(divPalStyle);
// Theme Tab
// For all customisable styles, generate and apply the css
var generateColours = function(base) {
var theme = globalDashboardNode.theme.name.split('-')[1];
if (!globalDashboardNode.theme.themeState.hasOwnProperty["base-font"]) {
if (globalDashboardNode.theme[theme+"Theme"].baseFont === "Helvetica Neue") {
globalDashboardNode.theme[theme+"Theme"].baseFont = baseFontName;
}
globalDashboardNode.theme.themeState["base-font"] = {value:globalDashboardNode.theme[theme+"Theme"].baseFont};
$("#nr-db-field-font").val(globalDashboardNode.theme[theme+"Theme"].baseFont);
}
for (var i=0; i<configurableStyles.length; i++) {
var styleID = configurableStyles[i];
var underscore = styleID.split("-").join("_");
if (!globalDashboardNode.theme.themeState.hasOwnProperty(styleID)) {
globalDashboardNode.theme.themeState[styleID] = {value:"#fff",edited:false};
}
if (!globalDashboardNode.theme.themeState[styleID].edited || globalDashboardNode.theme[theme+'Theme'].reset) {
var colour = colours['calculate_'+underscore](base);
globalDashboardNode.theme.themeState[styleID].value = colour;
}
setColourPickerColour(styleID, globalDashboardNode.theme.themeState[styleID].value, globalDashboardNode.theme.themeState[styleID].edited);
}
globalDashboardNode.theme[theme+'Theme'].reset = false;
}
var divThemeStyle = $('<div>',{class:"form-row"}).appendTo(themeTab);
$('<label class="nr-db-theme-label">').html(c_("theme.style")).appendTo(divThemeStyle);
var themeSelection = $('<select id="nr-db-field-theme">'+
'<option value="theme-light">'+c_("style.light")+'</option>'+
'<option value="theme-dark">'+c_("style.dark")+'</option>'+
'<option value="theme-custom">'+c_("style.custom")+'</option>'+
'</select>')
.css("width","100%")
.change(function() {
if (!globalDashboardNode || globalDashboardNode.theme.name !== $(this).val()) {
ensureDashboardNode(true);
var theme = globalDashboardNode.theme.name.split('-')[1];
var baseColour = globalDashboardNode.theme[theme+'Theme'].baseColor;
var baseFont = globalDashboardNode.theme[theme+'Theme'].baseFont;
globalDashboardNode.theme.name = $(this).val();
theme = globalDashboardNode.theme.name.split('-')[1];
if (theme !== "custom") {
baseColour = globalDashboardNode.theme[theme+'Theme'].default;
}
else { baseColour = globalDashboardNode.theme[theme+'Theme'].baseColor; }
setColourPickerColour("base-color", baseColour);
globalDashboardNode.theme.themeState['base-color'].value = baseColour;
globalDashboardNode.theme.themeState['base-color'].default = baseColour;
globalDashboardNode.theme.themeState['base-font'] = {value:baseFont};
$("#nr-db-field-font").val(baseFont);
globalDashboardNode.theme[theme+'Theme'].reset = true;
//generate colours for all colour settings from base colour
generateColours(baseColour);
RED.nodes.dirty(true);
}
$('#base-color-reset').remove();
if ($(this).val() === 'theme-custom') {
$("#custom-theme-library-container").show(); //TODO undo this at some point
$("#custom-theme-settings").show();
//addResetButton('base-color', baseSettingsUl.children());
}
else {
$("#custom-theme-library-container").hide();
$("#custom-theme-settings").hide();
addLightAndDarkResetButton('base-color', baseSettingsUl.children().first());
}
})
.appendTo(divThemeStyle);
var customThemeLibraryContainer = $('<div id="custom-theme-library-container">').appendTo(themeTab);
$('<label class="nr-db-theme-label">').html(c_("theme.custom-profile")).appendTo(customThemeLibraryContainer);
$('<input type="text" id="ui-sidebar-name" placeholder="profile name (not blank)">')
.val(c_("theme.custom-profile-name"))
.change(function() {
if (!globalDashboardNode || globalDashboardNode.theme.customTheme.name !== $(this).val()) {
ensureDashboardNode(true);
globalDashboardNode.theme.customTheme.name = $(this).val();
if (editor) {
editor.setValue(JSON.stringify({theme:globalDashboardNode.theme.themeState, site:globalDashboardNode.site}),1);
RED.nodes.dirty(true);
}
}
})
.keyup(function() {
if ($(this).val().length === 0) {
$("#custom-theme-library-container div").css("pointer-events","none");
}
else { $("#custom-theme-library-container div").css("pointer-events","inherit"); }
})
.appendTo(customThemeLibraryContainer);
$('<input type="hidden" id="nr-db-field-format">').appendTo(customThemeLibraryContainer);
$('<div style="display:none;" class="node-text-editor" id="nr-db-field-format-editor"></div>').appendTo(customThemeLibraryContainer);
var baseThemeSettingsContainer = $('<div id="base-theme-settings">').appendTo(themeTab);
var baseSettings = $('<div>',{class:"form-row"}).appendTo(baseThemeSettingsContainer);
$('<label class="nr-db-theme-label">').html(c_("theme.base-settings")).appendTo(baseSettings);
var baseSettingsUl = $('<ul id="base-settings-ul" class="red-ui-dashboard-theme-styles"></ul>').appendTo(baseSettings);
var baseColourItem = $('<li class="red-ui-dashboard-theme-item"><span>'+c_("base.colour")+'</span></li>').appendTo(baseSettingsUl);
var spanColorContainer = $('<span class="nr-db-color-pick-container"></span>').appendTo(baseColourItem);
$('<input id="base-color" class="nr-db-field-themeColor" type="color" value="#ffffff"/>')
.change(function() {
ensureDashboardNode(true);
var value = $(this).val();
var lightThemeMatch = globalDashboardNode.theme.lightTheme.baseColor === value;
var darkThemeMatch = globalDashboardNode.theme.darkTheme.baseColor === value;
var customThemeMatch = globalDashboardNode.theme.customTheme.baseColor === value;
if (!globalDashboardNode || !lightThemeMatch || !darkThemeMatch || !customThemeMatch) {
var theme = globalDashboardNode.theme.name.split('-')[1];
globalDashboardNode.theme[theme+'Theme'].baseColor = value;
if (globalDashboardNode.theme.name === 'theme-light' || globalDashboardNode.theme.name === 'theme-dark') {
//for light and dark themes, reset the colours
globalDashboardNode.theme[theme+'Theme'].reset = true;
}
generateColours(value);
editor.setValue(JSON.stringify({theme:globalDashboardNode.theme.themeState, site:globalDashboardNode.site}),1);
colourPickerChangeHandler($(this).attr('id'), value);
}
})
.appendTo(spanColorContainer);
var baseFontItem = $('<li class="red-ui-dashboard-theme-item"><span>'+c_("base.font")+'</span></li>').appendTo(baseSettingsUl);
var fontSelector = $('<select id="nr-db-field-font">'+
'<option value="'+baseFontName+'" style="font-fa