UNPKG

node-red-dashboard

Version:
968 lines (918 loc) 125 kB
<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