123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324 |
- <style>
- :root {
- --nr-db-dark-text: #444;
- --nr-db-light-text: #eee;
- --nr-db-disabled-text: #999;
- --nr-db-mid-grey: #7f7f7f;
- }
- .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: var(--red-ui-primary-text-color, var(--nr-db-dark-text));
- }
- .nr-db-sb-list-header {
- cursor: pointer;
- position:relative;
- color: var(--red-ui-header-text-color, var(--nr-db-dark-text));
- padding:3px;
- white-space: nowrap;
- }
- .nr-db-sb-list-header:hover {
- color: var(--red-ui-secondary-text-color-hover, var(--nr-db-dark-text));
- }
- .nr-db-sb-title-hidden {
- text-decoration: line-through;
- }
- .nr-db-sb-title-disabled {
- color: var(--red-ui-secondary-text-color-disabled, var(--nr-db-disabled-text));
- }
- .nr-db-sb-tab-list-header {
- background: var(--red-ui-secondary-background-selected, var(--nr-db-light-text));
- padding:5px;
- }
- .nr-db-sb-group-list-header:hover,
- .nr-db-sb-widget-list-header:hover {
- background: var(--red-ui-secondary-background-hover, var(--nr-db-light-text));
- }
- .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: var(--red-ui-tertiary-text-color, var(--nr-db-light-text));
- 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: var(--red-ui-secondary-border-color, var(--nr-db-light-text));
- }
- .nr-db-sb-group-list>li.ui-sortable-helper {
- border-top: 1px solid var(--red-ui-secondary-border-color, var(--nr-db-light-text));
- }
- .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: var(--red-ui-secondary-text-color, var(--nr-db-mid-grey));
- }
- span.nr-db-color-pick-container {
- max-width: 50px;
- border-radius: 3px;
- margin-left: 15px;
- }
- input.nr-db-field-themeColor[type="color"] {
- width: 60px !important;
- padding: 0px;
- height: 20px;
- 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;
- }
- ul.red-ui-dashboard-theme-styles {
- list-style: none;
- }
- ul.red-ui-dashboard-theme-styles li {
- margin-bottom: 6px;
- }
- .nr-db-resetIcon {
- margin: 3px 6px 0px 6px;
- float: right;
- color: var(--red-ui-secondary-text-color, var(--nr-db-mid-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>
-
- <!-- Dashboard layout tool -->
- <link rel="stylesheet" href="./ui_base/gs/gridstack.min.css">
- <link rel="stylesheet" href="./ui_base/css/gridstack-extra.min.css">
- <style>
- .grid-stack {
- background-color: #f8f8f8;
- border: solid 2px #C0C0C0;
- margin: auto;
- min-height: 42px;
- display: table-cell;
- background-image: linear-gradient(#C0C0C0 1px, transparent 0),
- linear-gradient(90deg, #C0C0C0 1px, transparent 0);
- background-size: 40px 43px;
- }
- .grid-stack>.grid-stack-item>.grid-stack-item-content {
- top: 3px;
- left: 5px;
- right: 5px;
- bottom: 3px;
- }
- .grid-stack-item-content {
- color: #2c3e50;
- text-align: center;
- background-color: #b0dfe3;
- border-radius: 2px;
- font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;
- white-space: nowrap;
- font-size: 12px;
- opacity: 0.7;
- }
- .grid-stack-item {
- cursor: move;
- }
- .nr-dashboard-layout-container-fluid {
- width: 100%;
- padding-right: 0px;
- padding-left: 0px;
- margin-right: 0px;
- margin-left: 0px;
- }
- .nr-dashboard-layout-row {
- width: 100%;
- display: -ms-flexbox;
- display: flex;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap;
- margin-right: 0px;
- margin-left: 0px;
- }
- .nr-dashboard-layout-span12 {
- width: 98.4%;
- padding: 2px;
- margin-left: 2px;
- }
- .nr-dashboard-layout-span6 {
- width: 49.2%;
- padding: 2px;
- margin-left: 2px;
- }
- .nr-dashboard-layout-span4 {
- width: 32.7%;
- padding: 2px;
- margin-left: 2px;
- }
- .nr-dashboard-layout-span3 {
- width: 24.3%;
- padding: 2px;
- margin-left: 2px;
- }
- .nr-dashboard-layout-span2 {
- width: 16.0%;
- padding: 2px;
- margin-left: 2px;
- }
- .nr-dashboard-layout-resize-disable {
- cursor: pointer;
- float: right;
- position: relative;
- z-index: 90;
- margin-right: 4px;
- }
- .nr-dashboard-layout-resize-enable {
- cursor: pointer;
- float: right;
- position: relative;
- z-index: 90;
- margin-right: 1px;
- }
- .grid-stack>.ui-state-disabled {
- opacity: 1;
- background-image: none;
- }
- .grid-stack>.grid-stack-item>.ui-resizable-handle {
- z-index: 90;
- margin-right: -7px;
- }
- </style>
-
-
- <script type="text/javascript">
- (function($) {
- var editSaveEventHandler;
- var nodesAddEventHandler;
- var nodesRemoveEventHandler;
- var layoutUpdateEventHandler; // Dashboard layout tool
- var uip = 'ui';
- var attemptedVendorLoad = false;
- var ensureDashboardNode;
-
- 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;
- }
- //console.log('Tiny Color Failed to load:',path);
- }
- });
- }
-
- // 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');
-
- // Dashboard layout tool
- // Load gridstack library
- var loadGsLib = function(path, callback) {
- $.ajax({ url: path,
- success: function (data) {
- var jsScript = document.createElement("script");
- jsScript.type = "application/javascript";
- jsScript.src = path;
- document.body.appendChild(jsScript);
- if (callback) { callback(); }
- },
- error: function (xhr, ajaxOptions, thrownError) {
- // TODO
- }
- });
- };
-
- loadGsLib('ui_base/gs/gridstack.min.js', function() {
- loadGsLib('ui_base/gs/gridstack.jQueryUI.min.js', null)
- });
-
- var tabDatas; // Layout editing tab data
- var oldSpacer; // Spacer not needed after editing
- var widthChange; // Group width change
- var widgetResize; // Change widget event
- var widgetDrag; // Drag wiget event
-
- var MAX_GROUP_WIDTH = 50; // The maximum width is 30
-
- /////////////////////////////////////////////////////////
- // Get widget under specified tab from node information
- /////////////////////////////////////////////////////////
- function getTabDataFromNodes(tabID) {
- var nodes = RED.nodes.createCompleteNodeSet(false);
- var tab = {};
- // Tab information
- for (var cnt = 0; cnt < nodes.length; cnt++) {
- if (nodes[cnt].type == "ui_tab" && nodes[cnt].id == tabID) {
- tab = {
- id: nodes[cnt].id,
- name: nodes[cnt].name,
- type: nodes[cnt].type,
- order: nodes[cnt].order,
- groups: []
- };
- break;
- }
- }
- // Group information
- for (var cnt = 0; cnt < nodes.length; cnt++) {
- if (nodes[cnt].type == "ui_group" && nodes[cnt].tab == tabID) {
- var group = {
- id: nodes[cnt].id,
- name: nodes[cnt].name,
- type: nodes[cnt].type,
- order: nodes[cnt].order,
- width: nodes[cnt].width,
- widgets: []
- };
- tab.groups.push(group);
- }
- }
- // Widget information
- var groupsIdx = {};
- for (var cnt = 0; cnt < tab.groups.length; cnt++) {
- groupsIdx[tab.groups[cnt].id] = tab.groups[cnt];
- }
- for (var cnt = 0; cnt < nodes.length; cnt++) {
- var group = groupsIdx[nodes[cnt].group];
- if (group != null && (/^ui_/.test(nodes[cnt].type) && nodes[cnt].type !== 'ui_link' && nodes[cnt].type !== 'ui_toast' && nodes[cnt].type !== 'ui_ui_control' && nodes[cnt].type !== 'ui_audio' && nodes[cnt].type !== 'ui_base' && nodes[cnt].type !== 'ui_group' && nodes[cnt].type !== 'ui_tab')) {
- var widget = {
- id: nodes[cnt].id,
- type: nodes[cnt].type,
- order: nodes[cnt].order,
- width: nodes[cnt].width,
- height: nodes[cnt].height,
- auto: nodes[cnt].width == 0 ? true : false
- };
- group.widgets.push(widget);
-
- if (!isLayoutToolSupported(nodes[cnt].type)) {
- console.log("LayoutTool warning: Unsupported widget. Widget="+JSON.stringify(widget));
- }
- }
- }
- return tab;
- }
-
- //////////////////////////////////////////////////
- // Update node information in the edited widget
- ////////////////////////////////////////////////////
- function putTabDataToNodes() {
- // Delete old flow spacer node
- for (var cnt = 0; cnt < oldSpacer.length; cnt++) {
- RED.nodes.remove(oldSpacer[cnt]);
- RED.nodes.dirty(true);
- RED.view.redraw(true);
- }
-
- var t_groups = tabDatas.groups;
- for (var cnt1 = 0; cnt1 < t_groups.length; cnt1++) {
- var n_group = RED.nodes.node(t_groups[cnt1].id);
- n_group.width = t_groups[cnt1].width;
- var t_widgets = t_groups[cnt1].widgets;
- for (var cnt2 = 0; cnt2 < t_widgets.length; cnt2++) {
- var n_widget = RED.nodes.node(t_widgets[cnt2].id);
- if (n_widget != null) {
- if (n_widget.group !== n_group.id) {
- var oldGroupNode = RED.nodes.node(n_widget.group);
- if (oldGroupNode) {
- var index = oldGroupNode.users.indexOf(n_widget);
- oldGroupNode.users.splice(index,1);
- }
- n_widget.group = n_group.id;
- n_group.users.push(n_widget);
- }
- n_widget.order = t_widgets[cnt2].order;
- if (t_widgets[cnt2].auto === true ) {
- n_widget.width = 0;
- n_widget.height = 0;
- } else {
- n_widget.width = t_widgets[cnt2].width;
- n_widget.height = t_widgets[cnt2].height;
- }
-
- n_widget.changed = true;
- n_widget.dirty = true;
- RED.editor.validateNode(n_widget);
- RED.events.emit("layout:update",n_widget);
- RED.nodes.dirty(true);
- RED.view.redraw(true);
- }
- else {
- // Add a spacer node
- if (t_widgets[cnt2].type === 'ui_spacer') {
- var spaceNode = {
- _def: RED.nodes.getType("ui_spacer"),
- type: "ui_spacer",
- hasUsers: false,
- users: [],
- id: RED.nodes.id(),
- tab: tabDatas.id,
- group: n_group.id,
- order: t_widgets[cnt2].order,
- name: "spacer",
- width: t_widgets[cnt2].width,
- height: t_widgets[cnt2].height,
- z: RED.workspaces.active(),
- label: function() { return this.name + " " + this.width + "x" + this.height; }
- };
- RED.nodes.add(spaceNode);
- RED.editor.validateNode(spaceNode);
- RED.nodes.dirty(true);
- RED.view.redraw(true);
- }
- }
- };
- }
- RED.sidebar.info.refresh();
- }
-
- ////////////////////////////////////////
- // Sort by order
- ////////////////////////////////////////
- function compareOrder(a, b) {
- var r = 0;
- if (a.order < b.order) { r = -1; }
- else if (a.order > b.order) { r = 1; }
- return r;
- }
-
- ////////////////////////////////////////
- // Sort by XY
- ////////////////////////////////////////
- function compareXY(a, b) {
- var r = 0;
- if (a.y < b.y) { r = -1; }
- else if (a.y > b.y) { r = 1; }
- else if (a.x < b.x) { r = -1; }
- else if (a.x > b.x) { r = 1; }
- return r;
- }
-
- ///////////////////////////////////////////////////////
- // Placeable location search (placed in the upper left)
- ///////////////////////////////////////////////////////
- function search_point(width, height, maxWidth, maxHeight, tbl) {
- for (var y=0; y < maxHeight; y++) {
- for (var x=0; x < maxWidth; x++) {
- if (check_matrix(x, y, width, height, maxWidth, tbl)) {
- fill_matrix(x, y, width, height, maxWidth, tbl);
- return {x:x, y:y};
- }
- }
- }
- return false;
- }
- // Check placement position
- function check_matrix(px, py, width, height, maxWidth, tbl) {
- if (px+width > maxWidth) return false;
- for (var y=py; y < py+height; y++) {
- for (var x=px; x<px+width; x++) {
- if (tbl[maxWidth*y+x]) return false;
- }
- }
- return true;
- }
- // Mark the placement position
- function fill_matrix(px, py, width, height, maxWidth, tbl) {
- for (var y=py; y < py+height; y++) {
- for (var x=px; x < px+width; x++) {
- tbl[maxWidth*y+x] = 1;
- }
- }
- }
-
- ////////////////////////////////////////////////////
- // Apply edit result to tab information for editing
- ////////////////////////////////////////////////////
- function saveGridDatas() {
- var groups = tabDatas.groups;
- for (var cnt = 0; cnt < groups.length; cnt++) {
- // Get layout editing results
- var gridID = '#grid'+cnt;
- var serializedData = [];
- $(gridID+'.grid-stack > .grid-stack-item:visible').each( function (index) {
- el = $(this);
- var node = el.data('_gridstack_node');
- serializedData.push({
- id: el[0].dataset.noderedid,
- type: el[0].dataset.noderedtype,
- group: groups[cnt].id,
- width: Number(node.width),
- height: Number(node.height),
- x: node.x,
- y: node.y,
- auto: (el[0].dataset.noderedsizeauto == 'true') ? true : false
- });
- });
-
- var width = Number(groups[cnt].width);
- var height = 0;
-
- // Search group height
- for (var i=0; i < serializedData.length; i++) {
- var wd = serializedData[i];
- if (height < wd.y + wd.height) {
- height = wd.y + wd.height;
- }
- }
-
- // Place widget on table
- var tbl = new Array(width * height);
- for (var i = 0; i< tbl.length; i++) {
- tbl[i]=0;
- }
- for (var i = 0; i < serializedData.length; i++) {
- var wd = serializedData[i];
- for (var y = wd.y; y < wd.y+wd.height; y++) {
- for (var x = wd.x; x < wd.x+wd.width; x++) {
- tbl[width*y+x]=1;
- }
- }
- }
-
- // Add Spacer to Blank
- for (var y = 0; y < height; y++) {
- var spacerAdded = false;
- for (var x = 0; x < width; x++) {
- if (tbl[width*y+x]===0) {
- if (!spacerAdded) {
- // Add 1x1 spacer
- serializedData.push({
- x: x,
- y: y,
- z: RED.workspaces.active(),
- width: 1,
- height: 1,
- name: 'spacer',
- type: 'ui_spacer'
- });
- spacerAdded = true;
- } else {
- // Extend the spacer width by 1
- serializedData[serializedData.length-1].width += 1;
- }
- } else {
- spacerAdded = false;
- }
- }
- }
-
- // Sort Gridstack objects by x, y information
- serializedData.sort(compareXY);
-
- // Delete x and y elements as information for sorting, and give order
- var order = 0;
- for (i in serializedData) {
- order++;
- delete serializedData[i].x;
- delete serializedData[i].y;
- serializedData[i].order = order;
- }
-
- // Update widget information in group with edited data
- var group = groups[cnt];
- delete group.widgets;
- group.widgets = serializedData;
- }
-
- // Save process call
- putTabDataToNodes();
- };
-
- ////////////////////////////////////////////////////
- // Get default height for automatic settings
- ////////////////////////////////////////////////////
- function getDefaultHeight(nodeID, groupWidth) {
- var redNode = RED.nodes.node(nodeID);
- var height = 1;
-
- if (redNode.type === 'ui_gauge') {
- if (redNode.gtype === 'gage') {
- height = Math.round(groupWidth/2)+1;
- } else if (redNode.gtype === 'wave') {
- if (groupWidth < 3) {
- height = 1;
- } else {
- height = Math.round(groupWidth*0.75);
- }
- } else { // donut or compass
- if (groupWidth < 3) {
- height = 1;
- } else if (groupWidth < 11) {
- height = groupWidth - 1;
- } else {
- height = Math.round(groupWidth*0.95);
- }
- }
- } else if (redNode.type === 'ui_chart') {
- height = Math.floor(groupWidth/2)+1;
- } else if (redNode.type === 'ui_form') {
- // var optNum = redNode.options.length; // Sub widget number
- // if (redNode.label) {
- // height = optNum + 2; // Label and Button
- // } else {
- // height = optNum + 1; // Button only
- // }
- height = redNode.rowCount
- } else if (redNode.type === 'ui_lineargauge') {
- if (redNode.unit && redNode.name) {
- height = 5;
- } else {
- height = 4;
- }
- } else if (redNode.type === 'ui_list') {
- height = 5;
- } else if (redNode.type === 'ui_vega') {
- height = 5;
- }
- return height;
- }
-
- /////////////////////////////
- // Grid width change
- ////////////////////////////
- var changeGroupWidth = function(id) {
- var widthID = '#change-width'+id;
- var gridID = '#grid'+id;
- $(widthID).spinner( {
- min: 1,
- max: MAX_GROUP_WIDTH,
- spin: function(event, ui) {
- // Search current maximum width
- var serializedData = [];
- $(gridID+'.grid-stack > .grid-stack-item:visible').each( function (index) {
- el = $(this);
- var node = el.data('_gridstack_node');
- serializedData.push({
- width: Number(node.width),
- x: node.x,
- auto: (el[0].dataset.noderedsizeauto == 'true') ? true : false
- });
- });
- var maxWidth = 0;
- for (var i=0; i < serializedData.length; i++) {
- var wd = serializedData[i];
- if (wd.auto == false) {
- if (maxWidth < wd.x + wd.width) {
- maxWidth = wd.x + wd.width;
- }
- }
- }
- var width = ui.value;
- if (width < maxWidth) {
- width = maxWidth;
- }
-
- var grid = $(gridID+'.grid-stack').data('gridstack');
- $(gridID+'.grid-stack').css("width", width * 40);
- $(gridID+'.grid-stack').css("background-size", 100/width+"% 43px");
- grid.setColumn(tabDatas.groups[id].width, true);
- grid.setColumn(width, true);
- tabDatas.groups[id].width = width;
-
- $(gridID+'.grid-stack > .grid-stack-item:visible').each( function(idx, el) {
- el = $(el);
- var node = el.data('_gridstack_node');
- var auto = (el[0].dataset.noderedsizeauto == 'true') ? true : false;
- var type = el[0].dataset.noderedtype;
- grid.resizable(el, !auto);
- if (auto === true) {
- grid.resize(el, width, getDefaultHeight(node.id, width));
- }
- });
-
- if (width !== ui.value) {
- event.stopPropagation();
- event.preventDefault();
- }
- }
- });
- };
-
- //////////////////////////////////
- // Move between groups of widgets
- //////////////////////////////////
- function handleMove(grid) {
- return function(ev, prevWidget, newWidget) {
- var elem = newWidget.el[0];
- if (elem.getAttribute("data-noderedsizeauto") === "true") {
- var id = elem.getAttribute("data-noderedid");
- var width = grid.grid.column;
- var height = getDefaultHeight(id, width);
- grid.move(elem, 0, newWidget.y);
- grid.resize(elem, width, height);
-
- var en = $(elem).find('.nr-dashboard-layout-resize-enable');
- en.off('click');
- en.on('click',layoutResizeEnable);
- en[0].setAttribute("title",c_("layout.auto"));
- }
- else {
- var ds = $(elem).find('.nr-dashboard-layout-resize-disable');
- ds.off('click');
- ds.on('click',layoutResizeDisable);
- ds[0].setAttribute("title",c_("layout.manual"));
- }
- };
- }
-
- //////////////////////////////////////////
- // Widget size change (start event)
- //////////////////////////////////////////
- var resizeGroupWidget = function(id) {
- var gridID = '#grid'+id;
- var grid = $(gridID+'.grid-stack').data('gridstack');
- $(gridID+'.grid-stack').on('resizestart', function(event, ui) {
- // Reset group width
- grid.setColumn(tabDatas.groups[id].width, true);
- });
- }
-
- //////////////////////////////////////////
- // Widget drag (start event)
- //////////////////////////////////////////
- var dragGroupWidget = function(id) {
- var gridID = '#grid'+id;
- var grid = $(gridID+'.grid-stack').data('gridstack');
- $(gridID+'.grid-stack').on('dragstart', function(event, ui) {
- // Reset group width
- grid.setColumn(tabDatas.groups[id].width, true);
- });
- }
-
- //////////////////////////////////////////
- // Layout resize Disable (Auto:false)
- //////////////////////////////////////////
- var layoutResizeDisable = function(e) {
- var target = $(e.target);
- var el = target.parents('.grid-stack-item:visible');
- var grid = target.parents('.grid-stack').data('gridstack');
- var node = el.data('_gridstack_node');
- var id = Number(target.parents('.grid-stack').attr('id').slice(4));
- var width = Number(tabDatas.groups[id].width);
- var nodeID = el[0].dataset.noderedid;
- var height = getDefaultHeight(nodeID, width);
-
- grid.move(el, 0, node.y);
- grid.resize(el, width, height);
- grid.resizable(el, false);
- el.find('.nr-dashboard-layout-resize-disable').off('click');
- el.attr({'data-noderedsizeauto':'true'});
- target.removeClass().addClass('fa fa-unlock nr-dashboard-layout-resize-enable');
- el.find('.nr-dashboard-layout-resize-enable')[0].setAttribute("title",c_("layout.auto"));
- el.find('.nr-dashboard-layout-resize-enable').on('click',layoutResizeEnable);
- }
-
- //////////////////////////////////////////
- // Layout resize Enable (Auto:true)
- //////////////////////////////////////////
- var layoutResizeEnable = function(e) {
- var target = $(e.target);
- var el = target.parents('.grid-stack-item:visible');
- var grid = target.parents('.grid-stack').data('gridstack');
-
- grid.resizable(el, true);
- el.find('.nr-dashboard-layout-resize-enable').off('click');
- el.attr({'data-noderedsizeauto':'false'});
- target.removeClass().addClass('fa fa-lock nr-dashboard-layout-resize-disable');
- el.find('.nr-dashboard-layout-resize-disable')[0].setAttribute("title",c_("layout.manual"));
- el.find('.nr-dashboard-layout-resize-disable').on('click',layoutResizeDisable);
- }
-
- //////////////////////////////////////////
- // Check dashboard layout tool supported
- //////////////////////////////////////////
- function isLayoutToolSupported(nodeType) {
- if (nodeType.indexOf("ui_") !== 0) {
- return false;
- }
- else {
- return true;
- }
- }
-
- 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);
- RED.events.off("layout:update",layoutUpdateEventHandler); // Dashboard layout tool
- },
- 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", palette:"light"};
- // 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) {
- if (this.whiteBlackLeastReadable(base) === "#000000") { return "#333333"; }
- else { return "#ffffff"; }
- },
- 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
- };
-
- ensureDashboardNode = function(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();
- console.log("Removing ui_base node "+n.id);
- 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);
- RED.editor.validateNode(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, "nr-dashboard") });
- }
- else {
- RED.actions.add("dashboard:show-dashboard",function() { window.open(document.location.protocol+"//"+lnk, "nr-dashboard") });
- RED.keyboard.add("*","ctrl-shift-d","dashboard:show-dashboard");
- }
- $('<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%")
- .on("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")
- .on("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") }))
- .append($('<option>', { value:"icon", text:c_("lock.locked-icon") }))
- .val("false")
- .on("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") }))
- .append($('<option>', { value:"mouse", text:c_("swipe.allow-swipe-mouse") }))
- .append($('<option>', { value:"menu", text:c_("swipe.show-menu") }))
- .val("false")
- .on("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")
- .on("change", function() {
- if (!globalDashboardNode || globalDashboardNode.site.allowTempTheme !== $(this).val()) {
- //ensureDashboardNode(true);
- globalDashboardNode.site.allowTempTheme = $(this).val();
- }
- 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");
- }
- RED.nodes.dirty(true);
- })
- .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%")
- .on("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">').text(c_("label.horizontal")).appendTo(divSetSizes);
- $('<span style="width:20%; display:inline-block; font-size:smaller">').text(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">').text(c_("label.widget-size")).appendTo(divSetSizes);
- $('<input type="number" name="sx" min="24" id="nr-db-field-sx">').val(48).css("width","20%")
- .on("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%")
- .on("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">').text(c_("label.widget-spacing")).appendTo(divSetSizes);
- $('<input type="number" name="cx" min="0" id="nr-db-field-cx">').val(6).css("width","20%")
- .on("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%")
- .on("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">').text(c_("label.group-padding")).appendTo(divSetSizes);
- $('<input type="number" name="px" min="0" id="nr-db-field-px">').val(0).css("width","20%")
- .on("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%")
- .on("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">').text(c_("label.group-spacing")).appendTo(divSetSizes);
- $('<input type="number" name="gx" min="0" id="nr-db-field-gx">').val(6).css("width","20%")
- .on("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%")
- .on("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)
- .on("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)
- .on("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)
- .on("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)
- .on("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)
- .on("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">').text(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%")
- .on("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">').text(c_("theme.custom-profile")).appendTo(customThemeLibraryContainer);
- $('<input type="text" id="ui-sidebar-name" style="vertical-align:top;" placeholder="profile name (not blank)">')
- .val(c_("theme.custom-profile-name"))
- .on("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">').text(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"/>')
- .on("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-family:'+baseFontName+'">'+c_("font.system")+'</option>'+
- '<option value="Arial,Arial,Helvetica,sans-serif" style="font-family:Arial,Arial,Helvetica,sans-serif">Arial</option>'+
- '<option value="Arial Black,Arial Black,Gadget,sans-serif" style="font-family:Arial Black,Arial Black,Gadget,sans-serif">Arial Black</option>'+
- '<option value="Arial Narrow,Nimbus Sans L,sans-serif" style="font-family:Arial Narrow,Nimbus Sans L,sans-serif">Arial Narrow</option>'+
- '<option value="Century Gothic,CenturyGothic,AppleGothic,sans-serif" style="font-family:Century Gothic,CenturyGothic,AppleGothic,sans-serif">Century Gothic</option>'+
- '<option value="Copperplate,Copperplate Gothic Light,fantasy" style="font-family:Copperplate,Copperplate Gothic Light,fantasy;">Copperplate</option>'+
- '<option value="Courier,monospace" style="font-family:Courier,monospace;">Courier</option>'+
- '<option value="Georgia,Georgia,serif" style="font-family:Georgia,Georgia,serif">Georgia</option>'+
- '<option value="Gill Sans,Geneva,sans-serif" style="font-family:Gill Sans,Geneva,sans-serif;">Gill Sans</option>'+
- //'<option value="Helvetica Neue,Helvetica,sans-serif" style="font-family:Helvetica Neue,Helvetica,sans-serif">Helvetica Neue</option>'+
- '<option value="Impact,Impact,Charcoal,sans-serif" style="font-family:Impact,Impact,Charcoal,sans-serif">Impact</option>'+
- '<option value="Lucida Sans Typewriter,Lucida Console,Monaco,monospace" style="font-family:Lucida Console,Monaco,monospace">Lucida Console</option>'+
- '<option value="Lucida Sans Unicode,Lucida Grande,sans-serif" style="font-family:Lucida Sans Unicode,Lucida Grande,sans-serif">Lucida Sans</option>'+
- '<option value="Palatino Linotype,Palatino,Book Antiqua,serif" style="font-family:Palatino Linotype,Palatino,Book Antiqua,serif">Palatino Linotype</option>'+
- '<option value="Tahoma,Geneva,sans-serif" style="font-family:Tahoma,Geneva,sans-serif">Tahoma</optionstyle="font-family:>'+
- '<option value="Times New Roman,Times,serif" style="font-family:Times New Roman,Times,serif">Times New Roman</option>'+
- '<option value="Trebuchet MS,Helvetica,sans-serif" style="font-family:Trebuchet MS,Helvetica,sans-serif">Trebuchet MS</option>'+
- '<option value="Verdana,Verdana,Geneva,sans-serif" style="font-family:Verdana,Verdana,Geneva,sans-serif">Verdana</option>'+
- '</select>')
- .on("change", function() {
- //ensureDashboardNode(true);
- var theme = globalDashboardNode.theme.name.split('-')[1];
- globalDashboardNode.theme[theme+'Theme'].baseFont = $(this).val();
- globalDashboardNode.theme.themeState['base-font'] = {value:$(this).val()};
- RED.nodes.dirty(true);
- })
- .appendTo(baseFontItem);
-
- var themeSettingsContainer = $('<div id="custom-theme-settings">').appendTo(themeTab);
-
- // Markup
- // Page styles
- var divPageStyle = $('<div>',{class:"form-row"}).appendTo(themeSettingsContainer);
- $('<label class="nr-db-theme-label">').text(c_("theme.page-settings")).appendTo(divPageStyle);
- var pageStyles = $('<ul class="red-ui-dashboard-theme-styles"></ul>').appendTo(themeSettingsContainer);
- addCustomisableStyle('page-titlebar-backgroundColor', c_("theme.page.title"), pageStyles);
- addCustomisableStyle('page-backgroundColor', c_("theme.page.page"), pageStyles);
- addCustomisableStyle('page-sidebar-backgroundColor', c_("theme.page.side"), pageStyles);
-
- // Group styles
- var divGroupStyle = $('<div>',{class:"form-row"}).appendTo(themeSettingsContainer);
- $('<label class="nr-db-theme-label">').text(c_("theme.group-settings")).appendTo(divGroupStyle);
- var groupStyles = $('<ul class="red-ui-dashboard-theme-styles"></ul>').appendTo(themeSettingsContainer);
- addCustomisableStyle('group-textColor', c_("theme.group.text"), groupStyles);
- addCustomisableStyle('group-borderColor', c_("theme.group.border"), groupStyles);
- addCustomisableStyle('group-backgroundColor', c_("theme.group.background"), groupStyles);
-
- // Widget styles
- var divWidgetStyle = $('<div>',{class:"form-row"}).appendTo(themeSettingsContainer);
- $('<label class="nr-db-theme-label">').text(c_("theme.widget-settings")).appendTo(divWidgetStyle);
- var widgetStyles = $('<ul class="red-ui-dashboard-theme-styles"></ul>').appendTo(themeSettingsContainer);
- addCustomisableStyle('widget-textColor', c_("theme.widget.text"), widgetStyles);
- addCustomisableStyle('widget-backgroundColor', c_("theme.widget.colour"), widgetStyles);
- addCustomisableStyle('widget-borderColor', c_("theme.widget.background"), widgetStyles);
-
- function addCustomisableStyle(id, name, parentUl) {
- var styleLi = $('<li class="red-ui-dashboard-theme-item"><span>'+name+'</span></li>').appendTo(parentUl);
- var spanColorContainer = $('<span class="nr-db-color-pick-container"></span>').appendTo(styleLi);
- $('<input id="'+id+'" class="nr-db-field-themeColor" type="color" value="#ffffff"/>')
- .on("change", function() {
- colourPickerChangeHandler($(this).attr('id'), $(this).val());
- })
- .appendTo(spanColorContainer);
- addResetButton(id, styleLi);
- }
-
- function colourPickerChangeHandler(id, value) {
- $("#"+id).css("background-color", value);
- $("#"+id+"-reset").css({opacity:1});
- globalDashboardNode.theme.themeState[id].edited = true;
- globalDashboardNode.theme.themeState[id].value = value;
- if (editor) {
- editor.setValue(JSON.stringify({theme:globalDashboardNode.theme.themeState, site:globalDashboardNode.site}),1);
- }
- RED.nodes.dirty(true);
- }
-
- function addResetButton(id, parent) {
- var resetToDefault = $('<i id="'+id+'-reset" class="fa fa-undo nr-db-resetIcon"></i>')
- .css({opacity:0.2})
- .click(function(e) { resetClick(e); })
- .appendTo(parent);
- }
-
- function addLightAndDarkResetButton(id, parent) {
- if ($("#" + id + "-reset").length === 0) {
- var resetToDefault = $('<i id="'+id+'-reset" class="fa fa-undo nr-db-resetIcon"></i>')
- .css({opacity:1})
- .click(function(e) { lightAndDarkResetClick(e); })
- .appendTo(parent);
- globalDashboardNode.theme[globalDashboardNode.theme.name.split('-')[1] + 'Theme'].edited = true;
- }
- }
-
- function lightAndDarkResetClick(e) {
- var elementID = e.target.id.split('-reset')[0];
- var key = globalDashboardNode.theme.name.split('-')[1] + 'Theme';
- //sanity check - light and dark only allow base-color-reset
- if (elementID === 'base-color') { // && globalDashboardNode.theme[key].edited) {
- var defaultColor = globalDashboardNode.theme[key].default;
- globalDashboardNode.theme[key].reset = true;
- generateColours(defaultColor);
- setColourPickerColour(elementID, defaultColor);
- $("#"+elementID+"-reset").css({opacity:0.2});
- globalDashboardNode.theme.themeState[elementID].value = defaultColor;
- globalDashboardNode.theme[key].baseColor = defaultColor;
- globalDashboardNode.theme[key].edited = false;
- RED.nodes.dirty(true);
- }
- }
-
- function resetClick(e) {
- //take off -reset
- var elementID = e.target.id.split('-reset')[0];
- if (globalDashboardNode.theme.themeState[elementID].edited) {
- var defaultColor = globalDashboardNode.theme.themeState['base-color'].value;
- var colour;
- //set colour
- if (elementID === 'base-color') {
- colour = defaultColor;
- generateColours(colour);
- }
- else {
- var underscore = elementID.split('-').join('_');
- colour = colours['calculate_'+underscore](defaultColor);
- }
- setColourPickerColour(elementID, colour);
- $("#"+elementID+"-reset").css({opacity:0.2});
- globalDashboardNode.theme.themeState[elementID].edited = false;
- globalDashboardNode.theme.themeState[elementID].value = colour;
- RED.nodes.dirty(true);
- }
- }
-
- function setColourPickerColour(id, val, ed) {
- $("#"+id).val(val);
- $("#"+id).css("background-color", val);
- //call mostReadableGreyWhite to set text colour
- var textColor = colours.whiteGreyMostReadable(val);
- $("#"+id).css("color", textColor);
- if (ed === true) { $("#"+id+"-reset").css({opacity:1}); }
- else { $("#"+id+"-reset").css({opacity:0.2}); }
- }
-
- //Layout Tab
- var divTabs = $('<div>',{class:"form-row",style:"position:relative"}).appendTo(layoutTab);
- $('<label>').html('<b>'+c_("layout.tab-and-link")+'</b>').appendTo(divTabs);
-
- var buttonGroup = $('<div>',{class:"nr-db-sb-list-button-group"}).appendTo(divTabs);
-
- //Toggle expand buttons
- $('<a href="#" class="editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-angle-double-up"></i></a>')
- .click(function(evt) {
- tabContainer.find(".nr-db-sb-group-list-container").slideUp().addClass('nr-db-sb-collapsed');
- tabContainer.find(".nr-db-sb-tab-list-header>.nr-db-sb-list-chevron").css({"transform":"rotate(-90deg)"});
- evt.preventDefault();
- })
- .appendTo(buttonGroup);
- $('<a href="#" class="editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-angle-double-down"></i></a>')
- .click(function(evt) {
- tabContainer.find(".nr-db-sb-group-list-container").slideDown().removeClass('nr-db-sb-collapsed');
- tabContainer.find(".nr-db-sb-tab-list-header>.nr-db-sb-list-chevron").css({"transform":""});
- evt.preventDefault();
- })
- .appendTo(buttonGroup);
-
- //Add item button
- $('<a href="#" class="editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-plus"></i> '+c_("layout.tab")+'</a>')
- .click(function(evt) {
- tabContainer.editableList('addItem',{type: 'ui_tab'});
- evt.preventDefault();
- })
- .appendTo(buttonGroup);
- $('<a href="#" class="editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-plus"></i> '+c_("layout.link")+'</a>')
- .click(function(evt) {
- tabContainer.editableList('addItem',{type: 'ui_link'});
- evt.preventDefault();
- })
- .appendTo(buttonGroup);
-
- var tabLists = {};
- var groupLists = {};
-
- // toggle slide tab group content
- var titleToggle = function (id,content,chevron) {
- return function(evt) {
- if (content.is(":visible")) {
- content.slideUp();
- chevron.css({"transform":"rotate(-90deg)"});
- content.addClass('nr-db-sb-collapsed');
- listStates[id] = false;
- }
- else {
- content.slideDown();
- chevron.css({"transform":""});
- content.removeClass('nr-db-sb-collapsed');
- listStates[id] = true;
- }
- };
- }
-
- var addTabOrLinkItem = function(container,i,item) {
- ensureDashboardNode(true);
- // create node if needed
- if (!item.node) {
- var defaultItem = {
- 'ui_tab': {
- _def: RED.nodes.getType('ui_tab'),
- type: 'ui_tab',
- users: [],
- icon: 'dashboard',
- name: 'Tab'
- },
- 'ui_link': {
- _def: RED.nodes.getType('ui_link'),
- type: 'ui_link',
- users: [],
- icon: 'open_in_browser',
- name: 'Link',
- target: 'newtab'
- }
- }
- item.node = defaultItem[item.type]
- item.node.id = RED.nodes.id()
- item.node.order = i+1
- item.node.name += ' '+item.node.order
- listElements[item.node.id] = container;
- if (item.type === 'ui_tab') {
- item.groups = [];
- }
- RED.nodes.add(item.node);
- RED.editor.validateNode(item.node);
- RED.history.push({
- t:'add',
- nodes:[item.node.id],
- dirty:RED.nodes.dirty()
- });
- RED.nodes.dirty(true);
- }
- else if (item.type === undefined) {
- item.type = item.node.type
- }
-
- listElements[item.node.id] = container;
- if (RED.nodes.hasOwnProperty('updateConfigNodeUsers')) {
- RED.nodes.updateConfigNodeUsers(item.node);
- }
-
- // title
- var titleRow = $('<div>',{class:"nr-db-sb-list-header nr-db-sb-tab-list-header"}).appendTo(container);
- switch (item.type) {
- case 'ui_tab': {
- container.addClass("nr-db-sb-tab-list-item");
- $('<i class="nr-db-sb-list-handle nr-db-sb-tab-list-handle fa fa-bars"></i>').appendTo(titleRow);
- var chevron = $('<i class="fa fa-angle-down nr-db-sb-list-chevron">',{style:"width:10px;"}).appendTo(titleRow);
- var tabicon = "fa-object-group";
- //var tabicon = item.node.disabled ? "fa-window-close-o" : item.node.hidden ? "fa-eye-slash" : "fa-object-group";
- $('<i>',{class:"nr-db-sb-icon nr-db-sb-tab-icon fa "+tabicon}).appendTo(titleRow);
- var tabhide = item.node.hidden ? " nr-db-sb-title-hidden" : "";
- var tabable = item.node.disabled ? " nr-db-sb-title-disabled" : "";
- $('<span>',{class:"nr-db-sb-title"+tabhide+tabable}).text(item.node.name||"").appendTo(titleRow);
- break;
- }
- case 'ui_link': {
- $('<i class="nr-db-sb-list-handle fa fa-bars"></i>').appendTo(titleRow);
- var title = $('<div class="nr-db-sb-link">').appendTo(titleRow);
- var nameContainer = $('<div class="nr-db-sb-link-name-container">').appendTo(title);
- $('<i class="fa fa-external-link"></i>').appendTo(nameContainer);
- $('<span class="nr-db-sb-link-name">').text(item.node.name||"untitled").appendTo(nameContainer);
- $('<div class="nr-db-sb-link-url">').text(item.node.link||"http://").appendTo(title);
- break;
- }
- }
- // buttons
- var buttonGroup = $('<div>',{class:"nr-db-sb-list-header-button-group",id: item.node.id}).appendTo(titleRow);
- if (item.type === 'ui_tab') {
- var addGroupButton = $('<a href="#" class="nr-db-sb-tab-add-group-button editor-button editor-button-small nr-db-sb-list-header-button" ><i class="fa fa-plus"></i> '+c_("layout.group")+'</a>').appendTo(buttonGroup);
- }
- var editButton = $('<a href="#" class="nr-db-sb-tab-edit-button editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-pencil"></i> '+c_("layout.edit")+'</a>').appendTo(buttonGroup);
- editButton.on('click',function(evt) {
- RED.editor.editConfig("", item.type, item.node.id);
- evt.stopPropagation();
- evt.preventDefault();
- });
-
- // Dashboard layout tool
- if (item.type === 'ui_tab') {
- var layoutButton = $('<a href="#" class="nr-db-sb-tab-edit-layout-button editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-pencil"></i> '+c_("layout.layout")+'</a>').appendTo(buttonGroup);
- layoutButton.on('click',function(evt) {
- var editTabName = item.node.name ? item.node.name : item.node.id;
- var trayOptions = {
- title: c_("layout.layout-editor") + " : " + editTabName,
- width: Infinity,
- buttons: [
- {
- id: "node-dialog-cancel",
- text: RED._("common.label.cancel"),
- click: function() {
- // clean editor
- RED.tray.close();
- }
- },
- {
- id: "node-dialog-ok",
- text: RED._("common.label.done"),
- class: "primary",
- click: function() {
- // Save data after editing
- saveGridDatas();
- RED.tray.close();
- }
- }
- ],
- resize: function(dimensions) {},
- open: function(tray) {
- // Get widget of specified tab from node information
- tabDatas = getTabDataFromNodes(item.node.id);
- // The width that can be handled by Layout is up to MAX_GROUP_WIDTH
- // Groups exceeding the maximum width are not supported.
- var tmpGroups = tabDatas.groups;
- tmpGroups.sort(compareOrder);
- var groups = [];
- for (var cnt = 0; cnt < tmpGroups.length; cnt++) {
- if (tmpGroups[cnt].width <= MAX_GROUP_WIDTH) {
- groups.push(tmpGroups[cnt]);
- }
- }
- tabDatas.groups = groups;
-
- var editor = $('<div></div>',{addClass: 'nr-dashboard-layout-container-fluid'});
- var row = $('<div></div>',{addClass: 'nr-dashboard-layout-row'});
- var span_num = Math.floor(12 / groups.length); // bootstrap grid 12 splits
- span_num = span_num < 2 ? 2 : span_num; // max 6 groups per row
- for (var cnt = 0; cnt < groups.length; cnt++) {
- if (cnt !=0 && (cnt % 6) == 0) {
- editor.append(row);
- editor.append('<div><br></div>');
- row = $('<div></div>',{addClass: 'nr-dashboard-layout-row'});
- }
- var span = $('<div></div>',{addClass: 'nr-dashboard-layout-span' + span_num});
- var groupName = groups[cnt].name ? groups[cnt].name : groups[cnt].id;
- var title = $('<div></div>', {
- style: "margin-top:2px; margin-bottom:2px;"
- });
- var title_group = $('<div></div>', {
- title: groupName,
- style: "margin-left:4px; margin-right:8px; overflow:hidden;"
- }).appendTo(title);
- $("<b/>").text(groupName).appendTo(title_group);
- var title_width = $('<div></div>', {
- style: "text-align:right; margin-right:8px;"
- }).appendTo(title);
- $("<span/>", {
- style: "margin_right: 8px;"
- }).text(c_("layout.width")+': ').appendTo(title_width);
- var changeWidth = $('<input>', {
- id: 'change-width' + cnt,
- value: groups[cnt].width,
- style: 'width:30px;',
- readonly: true,
- 'node-id': groups[cnt].id,
- });
- title_width.append(changeWidth);
-
- title.css('white-space','nowrap');
- title.css('overflow','hidden');
- var gridstack = $('<div></div>', {
- id: 'grid'+cnt,
- addClass: 'grid-stack'
- });
- span.append(title);
- span.append(gridstack);
- row.append(span);
- }
- if (groups.length != 0) {
- editor.append(row);
- }
-
- // Show layout editor in tray
- var trayBody = tray.find('.red-ui-tray-body, .editor-tray-body');
- trayBody.css('overflow','auto');
- trayBody.append(editor);
-
- /////////////////////////////////////////
- // Editor screen generation
- /////////////////////////////////////////
- oldSpacer = [];
- widthChange = [];
- widgetResize = [];
- widgetDrag = [];
- for (var cnt=0; cnt < groups.length; cnt++) {
- // Gridstack.js option
- var options = {
- acceptWidgets: true,
- alwaysShowResizeHandle: true,
- cellHeight: 42,
- disableOneColumnMode : true,
- float: true,
- verticalMargin: 1
- };
- var gridID='#grid' + cnt;
- // gridstack generation
- $(gridID).gridstack(options);
-
- // Clear the contents of Grid
- var grid = $(gridID+'.grid-stack').data('gridstack');
- grid.removeAll();
- $(gridID).on("dropped", handleMove(grid));
-
- // Set the width of the display area of gridstack
- var groupWidth = Number(groups[cnt].width);
- $(gridID+'.grid-stack').css("width", groupWidth * 40);
- $(gridID+'.grid-stack').css("background-size", 100/groupWidth+"% 43px");
- $(gridID+'.grid-stack').attr("node-id", groups[cnt].id);
- $(gridID+'.grid-stack').attr("grid-column", groups[cnt].width);
- grid.setColumn(groupWidth, true);
-
- // Determination of placement position of widget of Grid
- var widgets = groups[cnt].widgets;
- widgets.sort(compareOrder);
-
- var tbl = {};
- for (var cnt2 = 0; cnt2 < widgets.length; cnt2++) {
- // Set default value when there is auto width
- if (widgets[cnt2].auto == true) {
- widgets[cnt2].width = groupWidth;
- // Adjust to the group width
- } else if (widgets[cnt2].width > groupWidth) {
- widgets[cnt2].width = groupWidth;
- }
- // Auto support
- if (widgets[cnt2].auto === true || widgets[cnt2].type === 'ui_form') {
- widgets[cnt2].height = getDefaultHeight(widgets[cnt2].id, groupWidth);
- }
- // Calculate coordinates to be placed
- var point = search_point(Number(widgets[cnt2].width), Number(widgets[cnt2].height), groupWidth, 256, tbl);
- if (point) {
- widgets[cnt2].x = point.x;
- widgets[cnt2].y = point.y;
- }
- }
-
- var items = GridStackUI.Utils.sort(widgets);
- items.forEach(function (node) {
- var minHeight = null;
- var maxHeight = null;
- // ui_form is fixed to height 2
- if (node.type === 'ui_form') {
- minHeight = node.height;
- maxHeight = node.height;
- }
- if (node.type !== 'ui_spacer') {
- var dispNode = RED.nodes.node(node.id);
- var dispType = dispNode._def.paletteLabel;
- var dispLabel = dispNode._def.label;
- try {
- dispLabel = (typeof dispLabel === "function" ? dispLabel.call(dispNode) : dispLabel)||"";
- }
- catch(err) {
- console.log("Definition error: " + node.type + ".label",err);
- dispLabel = dispType;
- }
-
- var item = $('<div></div>', {
- 'data-noderedtype': node.type,
- 'data-noderedid': node.id,
- 'data-nodereddisptype': dispType,
- 'data-nodereddisplabel': dispLabel,
- 'data-noderedsizeauto': node.auto
- });
- var itemContent = $('<div></div>', {
- addClass: 'grid-stack-item-content',
- title: dispLabel + ':' + dispType
- });
-
- if (node.auto === true) {
- itemContent.append('<i class="fa fa-unlock nr-dashboard-layout-resize-enable" title="'+c_("layout.auto")+'"></i>');
- } else {
- itemContent.append('<i class="fa fa-lock nr-dashboard-layout-resize-disable" title="'+c_("layout.manual")+'"></i>');
- }
- itemContent.append('<b>'+ dispLabel +'</b><br/>'+ dispType);
- item.append(itemContent);
- grid.addWidget(
- item,
- node.x, node.y, node.width, node.height, false, null, null,
- minHeight, maxHeight, node.id);
- } else {
- // Record the spacer node ID to be deleted
- oldSpacer.push(node.id);
- }
- });
-
- $(gridID+'.grid-stack > .grid-stack-item:visible').each( function(idx, el) {
- el = $(el);
- var node = el.data('_gridstack_node');
- var auto = (el[0].dataset.noderedsizeauto == 'true') ? true : false;
- grid.resizable(el, !auto);
- });
-
- // Group width change
- widthChange.push(new changeGroupWidth(cnt));
- // Resize widget in group (start event)
- widgetResize.push(new resizeGroupWidget(cnt));
- // Dragging widgets in a group (start event)
- widgetDrag.push(new dragGroupWidget(cnt));
- }
- $('.grid-stack>.grid-stack-item>.grid-stack-item-content>.nr-dashboard-layout-resize-disable').on('click',layoutResizeDisable);
- $('.grid-stack>.grid-stack-item>.grid-stack-item-content>.nr-dashboard-layout-resize-enable').on('click',layoutResizeEnable);
- },
- close: function() {},
- show: function() {}
- }
- RED.tray.show(trayOptions);
- evt.stopPropagation();
- evt.preventDefault();
- });
- }
-
- if (item.type === 'ui_tab') {
- var content = $('<div>',{class:"nr-db-sb-group-list-container"}).appendTo(container);
-
- // ui_tab group chevron
- if (listStates.hasOwnProperty(item.node.id) && !listStates[item.node.id]) {
- content.hide();
- chevron.css({"transform":"rotate(-90deg)"});
- content.addClass('nr-db-sb-collapsed');
- listStates[item.node.id] = false;
- }
- else {
- listStates[item.node.id] = true;
- }
- titleRow.click(titleToggle(item.node.id,content,chevron));
-
- // ui_tab group list
- var ol = $('<ol>',{class:"nr-db-sb-group-list"}).appendTo(content).editableList({
- sortable:".nr-db-sb-group-list-header",
- addButton: false,
- height: 'auto',
- connectWith: ".nr-db-sb-group-list",
- addItem: function(container,i,group) {
- if (!group.node) {
- group.node = {
- id: RED.nodes.id(),
- _def: RED.nodes.getType("ui_group"),
- type: "ui_group",
- users: [],
- tab: item.node.id,
- order: i+1,
- name: "Group "+(i+1),
- width: 6,
- disp: true
- };
- listElements[group.node.id] = container;
- RED.nodes.add(group.node);
- RED.editor.validateNode(group.node);
- group.widgets = [];
- RED.history.push({
- t:'add',
- nodes:[group.node.id],
- dirty:RED.nodes.dirty()
- });
- RED.nodes.dirty(true);
- if (RED.nodes.hasOwnProperty('updateConfigNodeUsers')) {
- RED.nodes.updateConfigNodeUsers(group.node);
- }
- }
- else {
- if (group.node.order === undefined) {
- group.node.order = i+1;
- }
- }
- var groupNode = group.node;
- elementParents[groupNode] = item.node.id;
- var titleRow = $('<div>',{class:"nr-db-sb-list-header nr-db-sb-group-list-header"}).appendTo(container);
- $('<i class="nr-db-sb-list-handle nr-db-sb-group-list-handle fa fa-bars"></i>').appendTo(titleRow);
- var chevron = $('<i class="fa fa-angle-down nr-db-sb-list-chevron">',{style:"width:10px;"}).appendTo(titleRow);
- $('<i class="nr-db-sb-icon nr-db-sb-group-icon fa fa-table"></i>').appendTo(titleRow);
- var title = $('<span class="nr-db-sb-title">').text(groupNode.name||groupNode.id||"").appendTo(titleRow);
- listElements[groupNode.id] = container;
- var buttonGroup = $('<div>',{class:"nr-db-sb-list-header-button-group",id:groupNode.id}).appendTo(titleRow);
- var spacerButton = $('<a href="#" class="editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-plus"></i> '+c_("layout.spacer")+'</a>').appendTo(buttonGroup);
- spacerButton.on('click',function(evt) {
- var spaceNode = {
- _def: RED.nodes.getType("ui_spacer"),
- type: "ui_spacer",
- hasUsers: false,
- users: [],
- id: RED.nodes.id(),
- tab: item.node.name,
- group: group.node.id,
- order: i+1,
- name: "spacer",
- width: 1,
- height:1,
- z: RED.workspaces.active(),
- label: function() { return "spacer " + this.width + "x" + this.height; }
- };
- RED.nodes.add(spaceNode);
- RED.editor.validateNode(spaceNode);
- RED.history.push({
- t:'add',
- nodes:[spaceNode.id],
- dirty:RED.nodes.dirty()
- });
- RED.nodes.dirty(true);
- RED.view.redraw();
- evt.stopPropagation();
- evt.preventDefault();
- });
- var editButton = $('<a href="#" class="nr-db-sb-edit-group-button editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-pencil"></i> '+c_("layout.edit")+'</a>').appendTo(buttonGroup);
- var content = $('<div>',{class:"nr-db-sb-widget-list-container"}).appendTo(container);
- if (!listStates.hasOwnProperty(groupNode.id) || !listStates[groupNode.id]) {
- content.hide();
- chevron.css({"transform":"rotate(-90deg)"});
- content.addClass('nr-db-sb-collapsed');
- listStates[groupNode.id] = false;
- }
- else {
- listStates[groupNode.id] = true;
- }
-
- var ol = $('<ol>',{class:"nr-db-sb-widget-list"}).appendTo(content).editableList({
- sortable:".nr-db-sb-widget-list-header",
- addButton: false,
- height: 'auto',
- connectWith: ".nr-db-sb-widget-list",
- addItem: function(container,i,widgetNode) {
- elementParents[widgetNode.id] = groupNode.id;
- var titleRow = $('<div>',{class:"nr-db-sb-list-header nr-db-sb-widget-list-header"}).appendTo(container);
- $('<i class="nr-db-sb-list-handle nr-db-sb-widget-list-handle fa fa-bars"></i>').appendTo(titleRow);
- $('<i class="nr-db-sb-icon nr-db-sb-widget-icon fa fa-picture-o"></i>').click(function(e) { e.preventDefault(); RED.search.show(widgetNode.id); }).appendTo(titleRow);
- var l = widgetNode._def.label;
- try {
- l = (typeof l === "function" ? l.call(widgetNode) : l)||"";
- }
- catch(err) {
- console.log("Definition error: "+d.type+".label",err);
- l = d.type;
- }
- var title = $('<span class="nr-db-sb-title">').text(l).appendTo(titleRow);
- listElements[widgetNode.id] = container;
- var buttonGroup = $('<div>',{class:"nr-db-sb-list-header-button-group"}).appendTo(titleRow);
- var editButton = $('<a href="#" class="editor-button editor-button-small nr-db-sb-list-header-button"><i class="fa fa-pencil"></i> '+c_("layout.edit")+'</a>').appendTo(buttonGroup);
- container.on('mouseover',function() {
- widgetNode.highlighted = true;
- widgetNode.dirty = true;
- RED.view.redraw();
- });
- container.on('mouseout',function() {
- widgetNode.highlighted = false;
- widgetNode.dirty = true;
- RED.view.redraw();
- });
- editButton.on('click',function(evt) {
- RED.editor.edit(widgetNode);
- evt.stopPropagation();
- evt.preventDefault();
- });
- },
- sortItems: function(items) {
- var historyEvents = [];
- items.each(function(i,el) {
- var node = el.data('data');
- var hev = {
- t:'edit',
- node:node,
- changes:{
- order:node.order,
- group:node.group
- },
- dirty:node.dirty,
- changed:node.changed
- };
- historyEvents.push(hev);
- var changed = false;
- if (node.order !== i+1) {
- node.order = i+1;
- changed = true;
- }
- if (node.group !== group.node.id) {
- var oldGroupNode = RED.nodes.node(node.group);
- if (oldGroupNode) {
- var index = oldGroupNode.users.indexOf(node);
- oldGroupNode.users.splice(index,1);
- }
- node.group = group.node.id;
- group.node.users.push(node);
- changed = true;
- }
- if (changed) {
- node.dirty = true;
- node.changed = true;
- }
- })
- RED.history.push({
- t:'multi',
- events: historyEvents
- });
- RED.nodes.dirty(true);
- RED.view.redraw();
- }
- });
- ol.css("min-height","5px");
- if (groupNode.id) {
- groupLists[groupNode.id] = ol;
- }
- titleRow.click(titleToggle(groupNode.id,content,chevron));
- editButton.on('click',function(evt) {
- RED.editor.editConfig("", groupNode.type, groupNode.id);
- evt.stopPropagation();
- evt.preventDefault();
- });
- group.widgets.forEach(function(widget) {
- ol.editableList('addItem',widget);
- })
- },
- sortItems: function(items) {
- var historyEvents = [];
- items.each(function(i,el) {
- var groupData = el.data('data');
- var node = groupData.node;
- var hev = {
- t:'edit',
- node:node,
- changes:{
- order:node.order,
- tab:node.tab
- },
- dirty:node.dirty,
- changed:node.changed
- };
- historyEvents.push(hev);
- var changed = false;
- if (node.order !== i+1) {
- node.order = i+1;
- changed = true;
- }
- if (changed) {
- node.dirty = true;
- node.changed = true;
- }
- if (node.tab !== item.node.id) {
- var oldTabNode = RED.nodes.node(node.tab);
- if (oldTabNode) {
- var index = oldTabNode.users.indexOf(node);
- oldTabNode.users.splice(index,1);
- }
- node.tab = item.node.id;
- item.node.users.push(node);
- changed = true;
- }
- })
- RED.history.push({
- t:'multi',
- events: historyEvents
- });
- RED.nodes.dirty(true);
- RED.view.redraw();
- }
- })
- tabLists[item.node.id] = ol;
-
- addGroupButton.click(function(evt) {
- ol.editableList('addItem',{});
- evt.stopPropagation();
- evt.preventDefault();
- });
- item.groups.forEach(function(group) {
- ol.editableList('addItem',group);
- });
- }
- }
-
- var tabContainer = $('<ol>',{class:"nr-db-sb-tab-list"}).appendTo(divTabs).editableList({
- sortable:".nr-db-sb-tab-list-header",
- addButton: false,
- addItem: addTabOrLinkItem,
- sortItems: function(items) {
- var historyEvents = [];
- items.each(function(i,el) {
- var itemData = el.data('data');
- var node = itemData.node;
- var hev = {
- t:'edit',
- node:node,
- changes:{
- order:node.order
- },
- dirty:node.dirty,
- changed:node.changed
- }
- historyEvents.push(hev);
- var changed = false;
- if (node.order !== i+1) {
- node.order = i+1;
- changed = true;
- }
- if (changed) {
- node.dirty = true;
- node.changed = true;
- }
- })
- RED.history.push({
- t:'multi',
- events: historyEvents
- });
- RED.nodes.dirty(true);
- RED.view.redraw();
- }
- });
-
- var orphanedWidgets = $('<div>',{class:"form-row"}).appendTo(layoutTab);
- $('<span><i class="fa fa-info-circle"></i> There <span id="nr-db-missing-group-count"></span> not in a group. Click <a id="nr-db-add-missing-groups" href="#">here</a> to create the missing groups</span>').appendTo(orphanedWidgets);
- orphanedWidgets.find('a').click(function(event) {
- var unknownGroups = {};
- RED.nodes.eachNode(function(node) {
- if (/^ui_/.test(node.type) && node.type !== 'ui_link' && node.type !== 'ui_toast' && node.type !== 'ui_ui_control') {
- if (!RED.nodes.node(node.group)) {
- var g = node.group || "_BLANK_";
- unknownGroups[g] = unknownGroups[g] || [];
- unknownGroups[g].push(node);
- }
- }
- });
- var tab = null;
- var tabs = tabContainer.editableList('items');
- tabs.first().each(function(i,el) {
- var tabData = el.data('data');
- tab = tabData.node;
- });
-
- var hev = [];
- if (tab === null) {
- tab = {
- id: RED.nodes.id(),
- _def: RED.nodes.getType("ui_tab"),
- type: "ui_tab",
- users: [],
- order: 0,
- name: "Tab",
- icon: "dashboard"
- };
- RED.nodes.add(tab);
- RED.editor.validateNode(tab);
- hev.push(tab.id);
- }
- for (var groupId in unknownGroups) {
- if (unknownGroups.hasOwnProperty(groupId)) {
- var groupNode = {
- id: RED.nodes.id(),
- _def: RED.nodes.getType("ui_group"),
- type: "ui_group",
- users: [],
- tab: tab.id,
- order: i+1,
- name: (groupId==="_BLANK_"?"Group":groupId),
- width: 6,
- disp: true
- };
- hev.push(groupNode.id);
- RED.nodes.add(groupNode);
- RED.editor.validateNode(groupNode);
- if (RED.nodes.hasOwnProperty('updateConfigNodeUsers')) {
- RED.nodes.updateConfigNodeUsers(groupNode);
- }
- var widgets = unknownGroups[groupId];
- for (var i=0; i<widgets.length; i++) {
- widgets[i].group = groupNode.id;
- widgets[i].changed = true;
- widgets[i].dirty = true;
- if (RED.nodes.hasOwnProperty('updateConfigNodeUsers')) {
- RED.nodes.updateConfigNodeUsers(widgets[i]);
- }
- RED.editor.validateNode(widgets[i]);
- }
- }
- }
- RED.history.push({
- t:'add',
- nodes: hev,
- dirty:RED.nodes.dirty()
- });
- RED.nodes.dirty(true);
- refresh();
- refreshOrphanedWidgets();
- RED.view.redraw();
- event.preventDefault();
- });
-
- var listElements = {};
- var dashboard = [];
- var listStates = {};
- var elementParents = {};
- var awaitingGroups = {};
- var awaitingTabs = {};
-
- function getCurrentList() {
- var currentList = [];
- var tabs = tabContainer.editableList('items');
- var open = false;
- tabs.each(function(i,el) {
- var tabData = el.data('data');
- var tab = [];
- var groups = el.find('.nr-db-sb-group-list').editableList('items');
- groups.each(function(j,el) {
- var group = [];
- var groupData = el.data('data');
- var widgets = el.find('.nr-db-sb-widget-list').editableList('items');
- widgets.each(function(k,el) {
- var widgetData = el.data('data');
- group.push(widgetData.id);
- })
- tab.push({id:groupData.node.id, widgets:group});
- });
- currentList.push({id:tabData.node.id,groups:tab});
- });
- return currentList;
- }
-
- function refreshOrphanedWidgets() {
- var unknownGroups = {};
- var count = 0;
- RED.nodes.eachNode(function(node) {
- if (/^ui_/.test(node.type) && node.type !== 'ui_link' && node.type !== 'ui_toast' && node.type !== 'ui_ui_control' && (node.type === 'ui_template' && node.templateScope !== 'global')) {
- if (!RED.nodes.node(node.group)) {
- var g = node.group || "_BLANK_";
- unknownGroups[g] = unknownGroups[g] || [];
- unknownGroups[g].push(node);
- count++;
- }
- }
- });
-
- if (count > 0) {
- orphanedWidgets.show();
- $("#nr-db-missing-group-count").text((count===1?"is ":"are ")+count+" widget"+(count === 1?"":"s"))
- }
- else {
- orphanedWidgets.hide();
- }
- }
-
- function refresh() {
- var currentList = getCurrentList();
- dashboard = [];
- var tabs = {};
- var groups = {};
- var elements = [];
- var groupElements = {};
- var tabGroups = {};
- var groupId;
- var group;
- var tabId;
- var tab;
- var unknownGroups = 0;
- // Find all the tabs and groups
- RED.nodes.eachConfig(function(node) {
- switch (node.type) {
- case 'ui_tab':
- case 'ui_link': {
- tabs[node.id] = node;
- //tabContainer.editableList('addItem',node);
- break;
- }
- case 'ui_group': {
- groups[node.id] = node;
- break;
- }
- case 'ui_spacer': {
- if (groups.hasOwnProperty(node.group)) {
- groupElements[node.group] = groupElements[node.group]||[];
- groupElements[node.group].push(node);
- }
- break;
- }
- }
- });
- for (groupId in groups) {
- if (groups.hasOwnProperty(groupId)) {
- group = groups[groupId];
- if (tabs.hasOwnProperty(group.tab)) {
- // This group belongs to a tab
- tabGroups[group.tab] = tabGroups[group.tab]||[];
- tabGroups[group.tab].push(group);
- }
- else {
- unknownGroups++;
- }
- }
- }
- // Find all ui widgets - list them by their group id
- RED.nodes.eachNode(function(node) {
- if (/^ui_/.test(node.type)) {
- if (groups.hasOwnProperty(node.group)) {
- groupElements[node.group] = groupElements[node.group]||[];
- groupElements[node.group].push(node);
- }
- else if ((node.type !== 'ui_toast')&&(node.type !== 'ui_ui_control')&&(node.type === 'ui_template' && node.templateScope !== 'global')) {
- unknownGroups++;
- }
- }
- });
- if (unknownGroups > 0) {
- $("#nr-db-missing-group-count").text((unknownGroups===1?"is ":"are ")+unknownGroups+" widget"+(unknownGroups === 1?"":"s"))
- orphanedWidgets.show();
- }
- else {
- orphanedWidgets.hide();
- }
- // Sort each group's array of widgets
- for (groupId in groupElements) {
- if (groupElements.hasOwnProperty(groupId)) {
- group = groupElements[groupId];
- groupElements[groupId] = group.map(function(v,i) { return {n:v,i:i} }).sort(function(A,B) {
- if (A.n.order < B.n.order) { return A.n.order!==0?-1:1;}
- if (A.n.order > B.n.order) { return B.n.order!==0?1:-1;}
- return A.i - B.i;
- }).map(function(v) { return v.n})
- }
- }
- // Sort each tabs's array of groups
- for (tabId in tabGroups) {
- if (tabGroups.hasOwnProperty(tabId)) {
- tab = tabGroups[tabId];
- tabGroups[tabId] = tab.map(function(v,i) { return {n:v,i:i} }).sort(function(A,B) {
- if (A.n.order < B.n.order) { return -1;}
- if (A.n.order > B.n.order) { return 1;}
- return A.i - B.i;
- }).map(function(v) { return v.n})
- }
- }
- var tabIds = Object.keys(tabs).map(function(v,i) { return {n:tabs[v],i:i} }).sort(function(A,B) {
- if (A.n.order < B.n.order) { return -1;}
- if (A.n.order > B.n.order) { return 1;}
- return A.i - B.i;
- }).map(function(v) { return v.n.id});
- tabIds.forEach(function(tabId) {
- var tab = {node:tabs[tabId],groups:[]};
- if (tabGroups[tabId]) {
- tabGroups[tabId].forEach(function(groupNode) {
- var group = {node:groupNode,widgets:[]};
- if (groupElements[groupNode.id]) {
- group.widgets = groupElements[groupNode.id];
- }
- tab.groups.push(group);
- });
- }
- dashboard.push(tab);
- });
- var newList = dashboard.map(function(t) {
- return {
- id: t.node.id,
- groups: t.groups.map(function(g) {
- return {
- id: g.node.id,
- widgets: g.widgets.map(function(w) {
- return w.id;
- })
- }
- })
- }
- });
- if (JSON.stringify(newList)!=JSON.stringify(currentList)) {
- listElements = {};
- groupLists = {};
- tabLists = {};
- tabs = {};
- groups = {};
- elementParents = {};
- tabContainer.empty();
- dashboard.forEach(function(tab) {
- tabContainer.editableList('addItem',tab);
- });
- }
- //ensureDashboardNode(true);
- if (globalDashboardNode) {
- $("#nr-db-field-title").val(globalDashboardNode.site.name);
- $("#nr-db-field-allowSwipe").val(globalDashboardNode.site.allowSwipe || "false");
- $("#nr-db-field-allowTempTheme").val(globalDashboardNode.site.allowTempTheme || "true");
- $("#nr-db-field-hideToolbar").val(globalDashboardNode.site.hideToolbar || "false");
- $("#nr-db-field-dateFormat").val(globalDashboardNode.site.dateFormat);
-
- if (typeof globalDashboardNode.site.sizes !== "object") {
- globalDashboardNode.site.sizes = sizes;
- }
- $("#nr-db-field-sx").val(globalDashboardNode.site.sizes.sx);
- $("#nr-db-field-sy").val(globalDashboardNode.site.sizes.sy);
- $("#nr-db-field-px").val(globalDashboardNode.site.sizes.px);
- $("#nr-db-field-py").val(globalDashboardNode.site.sizes.py);
- $("#nr-db-field-cx").val(globalDashboardNode.site.sizes.cx);
- $("#nr-db-field-cy").val(globalDashboardNode.site.sizes.cy);
- $("#nr-db-field-gx").val(globalDashboardNode.site.sizes.gx);
- $("#nr-db-field-gy").val(globalDashboardNode.site.sizes.gy);
-
- if (typeof globalDashboardNode.theme.angularTheme !== "object") {
- globalDashboardNode.theme.angularTheme = aTheme;
- }
- $("#nr-db-field-angPrimary").val(globalDashboardNode.theme.angularTheme.primary || "indigo");
- $("#nr-db-field-angAccents").val(globalDashboardNode.theme.angularTheme.accents || "blue");
- $("#nr-db-field-angWarn").val(globalDashboardNode.theme.angularTheme.warn || "red");
- $("#nr-db-field-angBackground").val(globalDashboardNode.theme.angularTheme.background || "grey");
- $("#nr-db-field-angLook").val(globalDashboardNode.theme.angularTheme.palette || "light");
-
- $("#nr-db-field-theme").val(globalDashboardNode.theme.name);
- $("#ui-sidebar-name").val(globalDashboardNode.theme.customTheme.name);
- if (globalDashboardNode.theme.name === 'theme-custom') {
- $("#custom-theme-library-container").show();
- $("#custom-theme-settings").show();
- }
- else {
- $("#custom-theme-library-container").hide();
- $("#custom-theme-settings").hide();
- }
- 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");
- }
-
- //set colour start
- if (typeof globalDashboardNode.theme.name !== "string") {
- globalDashboardNode.theme.name = "theme-light";
- }
- var currentTheme = globalDashboardNode.theme.name.split("-")[1];
- var startingValue = globalDashboardNode.theme[currentTheme+"Theme"].baseColor;
- setColourPickerColour("base-color", startingValue);
- $("#nr-db-field-font").val(globalDashboardNode.theme[currentTheme+"Theme"].baseFont);
- generateColours(startingValue);
- if (globalDashboardNode.theme.name === 'theme-light' || globalDashboardNode.theme.name === 'theme-dark') {
- addLightAndDarkResetButton('base-color', $('#base-settings-ul').children().first());
- }
-
- if (editor === undefined) {
- editor = RED.editor.createEditor({
- id: 'nr-db-field-format-editor',
- mode: 'ace/mode/javascript',
- value: JSON.stringify({theme:globalDashboardNode.theme.themeState, site:globalDashboardNode.site})
- });
-
- RED.library.create({
- url:"themes", // where to get the data from
- type:"theme", // the type of object the library is for
- editor: editor, // the field name the main text body goes to
- mode:"ace/mode/javascript",
- fields:['name'],
- elementPrefix:"ui-sidebar-"
- });
- }
-
- editor.on('input', function() {
- // Check for any changes on the editor object
- // i.e. has the theme been customised compared
- // to what is stored
- var editorObject = JSON.parse(editor.getValue());
-
- //Update theme object if necessary
- if (JSON.stringify(editorObject.theme) !== JSON.stringify(globalDashboardNode.theme.themeState)) {
- globalDashboardNode.theme.themeState = editorObject.theme;
- if ($("#ui-sidebar-name").val() !== globalDashboardNode.theme.customTheme.name) {
- globalDashboardNode.theme.customTheme.name = $("#ui-sidebar-name").val();
- globalDashboardNode.theme.customTheme.baseColor = globalDashboardNode.theme.themeState["base-color"].value;
- setColourPickerColour("base-color", globalDashboardNode.theme.customTheme.baseColor);
- generateColours(globalDashboardNode.theme.themeState["base-color"].value);
- RED.nodes.dirty(true);
- }
- }
- if (JSON.stringify(aTheme) !== JSON.stringify(globalDashboardNode.theme.angularTheme)) {
- globalDashboardNode.theme.angularTheme = aTheme;
- }
-
- //Update site object if necessary
- if (JSON.stringify(editorObject.site) !== JSON.stringify(globalDashboardNode.site)) {
- globalDashboardNode.site = editorObject.site;
- $("#nr-db-field-title").val(globalDashboardNode.site.name);
- $("#nr-db-field-hideToolbar").val(globalDashboardNode.site.hideToolbar);
- $("#nr-db-field-allowSwipe").val(globalDashboardNode.site.allowSwipe);
- $("#nr-db-field-allowTempTheme").val(globalDashboardNode.site.allowTempTheme);
- $("#nr-db-field-dateFormat").val(globalDashboardNode.site.dateFormat);
- $("#nr-db-field-sx").val(globalDashboardNode.site.sizes.sx);
- $("#nr-db-field-sy").val(globalDashboardNode.site.sizes.sy);
- $("#nr-db-field-px").val(globalDashboardNode.site.sizes.px);
- $("#nr-db-field-py").val(globalDashboardNode.site.sizes.py);
- $("#nr-db-field-gx").val(globalDashboardNode.site.sizes.gx);
- $("#nr-db-field-gy").val(globalDashboardNode.site.sizes.gy);
- $("#nr-db-field-cx").val(globalDashboardNode.site.sizes.cx);
- $("#nr-db-field-cy").val(globalDashboardNode.site.sizes.cy);
- RED.nodes.dirty(true);
- }
- });
- }
- awaitingGroups = {};
- awaitingTabs = {};
- }
-
- RED.sidebar.addTab({
- id: "dashboard",
- label: c_("label.dashboard"),
- name: "Dashboard",
- content: content,
- closeable: true,
- pinned: true,
- iconClass: "fa fa-bar-chart",
- disableOnEdit: true,
- onchange: function() { refresh(); }
- });
-
- editSaveEventHandler = function(node) {
- if (/^ui_/.test(node.type)) {
- if (node.type === "ui_tab" || node.type === "ui_group") {
- if (listElements[node.id]) {
- // Existing element
- listElements[node.id].children(".nr-db-sb-list-header").find(".nr-db-sb-title").text(node.name||node.id);
- if (node.type === "ui_group") {
- refresh();
- }
- else {
- if (node.hidden === true) { listElements[node.id].children(".nr-db-sb-list-header").find(".nr-db-sb-title").addClass('nr-db-sb-title-hidden'); }
- else { listElements[node.id].children(".nr-db-sb-list-header").find(".nr-db-sb-title").removeClass('nr-db-sb-title-hidden'); }
- if (node.disabled === true) { listElements[node.id].children(".nr-db-sb-list-header").find(".nr-db-sb-title").addClass('nr-db-sb-title-disabled'); }
- else { listElements[node.id].children(".nr-db-sb-list-header").find(".nr-db-sb-title").removeClass('nr-db-sb-title-disabled'); }
- }
- }
- else if (node.type === "ui_tab") {
- // Adding a tab
- tabContainer.editableList('addItem',{node:node,groups:[]})
- }
- else {
- // Adding a group
- if (tabLists[node.tab]) {
- tabLists[node.tab].editableList('addItem',{node:node,widgets:[]})
- }
- }
- }
- else if (node.type === "ui_link") {
- if (listElements[node.id]) {
- var container = listElements[node.id];
- container.find(".nr-db-sb-link-name").text(node.name||"untitled");
- container.find(".nr-db-sb-link-url").text(node.link);
- }
- }
- else {
- refreshOrphanedWidgets();
- if (listElements[node.id]) {
- if (node.group != elementParents[node.id]) {
- // Moved to a different group
- if (groupLists[elementParents[node.id]]) {
- groupLists[elementParents[node.id]].editableList('removeItem',listElements[node.id].data('data'))
- }
- if (groupLists[node.group]) {
- groupLists[node.group].editableList('removeItem',node)
- groupLists[node.group].editableList('addItem',node);
- }
- }
- else {
- var l = node._def.label;
- try {
- l = (typeof l === "function" ? l.call(node) : l)||"";
- }
- catch(err) {
- console.log("Definition error: "+d.type+".label",err);
- l = d.type;
- }
- listElements[node.id].children(".nr-db-sb-list-header").find(".nr-db-sb-title").text(l);
- }
- }
- else {
- if (groupLists[node.group]) {
- if (node.order === 0) { node.order = groupLists[node.group].editableList('length'); }
- groupLists[node.group].editableList('addItem',node);
- }
- }
- }
- }
- };
- RED.events.on("editor:save",editSaveEventHandler);
-
- // Dashboard layout tool
- layoutUpdateEventHandler = function(node) {
- if (/^ui_/.test(node.type) && node.type !== 'ui_link' && node.type !== 'ui_toast' && node.type !== 'ui_ui_control' && node.type !== 'ui_audio' && node.type !== 'ui_base' && node.type !== 'ui_group' && node.type !== 'ui_tab') {
- if (listElements[node.id]) {
- if (node.group != elementParents[node.id]) {
- // Moved to a different group
- if (groupLists[elementParents[node.id]]) {
- groupLists[elementParents[node.id]].editableList('removeItem',listElements[node.id].data('data'))
- }
- if (groupLists[node.group]) {
- groupLists[node.group].editableList('removeItem',node)
- groupLists[node.group].editableList('addItem',node);
- groupLists[node.group].editableList('sort',function(a,b) {return a.order-b.order;});
- }
- }
- else {
- groupLists[node.group].editableList('sort',function(a,b) {return a.order-b.order;});
- }
- }
- }
- };
- RED.events.on("layout:update",layoutUpdateEventHandler);
-
- var pendingAdd = [];
- var pendingAddTimer = null;
-
- function handlePendingAdds() {
- var hasTabs = false;
- var hasGroups = false;
- pendingAdd.sort(function(A,B) {
- hasTabs = hasTabs || A.type === "ui_tab" || B.type === "ui_tab";
- hasGroups = hasGroups || A.type === "ui_group" || B.type === "ui_group";
- if (A.type === B.type) {
- return 0;
- }
- if (A.type === "ui_tab") {
- return -1;
- }
- else if (B.type === "ui_tab") {
- return 1;
- }
- else if (A.type === "ui_group") {
- return -1;
- }
- else if (B.type === "ui_group") {
- return 1;
- }
- return 0
- });
- var updateList = {};
- for (var i=0; i<pendingAdd.length; i++) {
- var node = pendingAdd[i];
- if (listElements[node.id]) {
- continue;
- }
- if (node.type === "ui_tab") {
- tabContainer.editableList('addItem',{node:node,groups:[]});
- }
- else {
- if (hasTabs) {
- // We've added some tabs, need to give jquery time to add the lists
- pendingAdd = pendingAdd.slice(i);
- pendingAddTimer = setTimeout(handlePendingAdds,50);
- return;
- }
- if (node.type === "ui_group") {
- if (tabLists[node.tab]) {
- tabLists[node.tab].editableList('addItem',{node:node,widgets:[]});
- }
- }
- else {
- if (hasGroups) {
- // We've added some tabs, need to give jquery time to add the lists
- pendingAdd = pendingAdd.slice(i);
- pendingAddTimer = setTimeout(handlePendingAdds,50);
- return;
- }
- if (groupLists[node.group]) {
- groupLists[node.group].editableList('addItem',node)
- if (node.order >= 0) {
- updateList[node.group] = true;
- }
- }
- else {
- refreshOrphanedWidgets();
- }
- }
- }
- }
- Object.keys(updateList).forEach(function (group) {
- var list = groupLists[group];
- if (list) {
- list.editableList("sort", function(a,b) {return a.order-b.order;});
- }
- });
- pendingAdd = [];
- }
-
- nodesAddEventHandler = function(node) {
- if (/^ui_/.test(node.type) && !listElements[node.id]) {
- pendingAdd.push(node);
- clearTimeout(pendingAddTimer);
- pendingAddTimer = setTimeout(handlePendingAdds,100);
- }
- };
- RED.events.on("nodes:add", nodesAddEventHandler);
-
- nodesRemoveEventHandler = function(node) {
- if (/^ui_/.test(node.type)) {
- if (node.type === "ui_tab" || node.type === "ui_link") {
- if (listElements[node.id]) {
- tabContainer.editableList('removeItem',listElements[node.id].data('data'));
- delete tabLists[node.id];
- }
- }
- else if (node.type === "ui_group") {
- if (tabLists[node.tab] && listElements[node.id]) {
- tabLists[node.tab].editableList('removeItem',listElements[node.id].data('data'));
- }
- delete groupLists[node.id];
- }
- else {
- if (groupLists[node.group]) {
- groupLists[node.group].editableList('removeItem',node)
- }
- }
- refreshOrphanedWidgets();
- delete listElements[node.id];
- }
- };
- RED.events.on("nodes:remove", nodesRemoveEventHandler);
- }
- });
-
- $.widget("nodereddashboard.elementSizerByNum", {
- _create: function() {
- var that = this;
- var has_height = this.options.has_height;
- var pos = this.options.pos;
- var c_width = has_height ? '15%' : '6%';
- var container = $('<div>').css({
- position: 'absolute',
- background: 'white',
- padding: '10px 10px 10px 10px',
- border: '1px solid grey',
- zIndex: '20',
- borderRadius: "4px",
- display:"none",
- width: c_width
- }).appendTo(document.body);
- var box0 = $("<div>").css({
- fontSize: '13px',
- color: '#aaa',
- float: 'left',
- paddingTop: '1px'
- }).appendTo(container);
-
- var width = $(this.options.width).val();
- var height = has_height ? $(this.options.height).val() : undefined;
- var max_w = '';
- var groupNode = this.options.groupNode;
- if(groupNode) {
- max_w = 'max="'+groupNode.width+'"';
- }
- width = (width > 0) ? width : 1;
- height = (height > 0) ? height : 1;
- var in0 = $('<input type="number" min="1" '+max_w+'>')
- .css("width", has_height ? "40%" : "100%")
- .val(width)
- .appendTo(box0);
- if(has_height) {
- var pad = $('<span>')
- .text(" x ")
- .appendTo(box0);
- var in1 = $('<input type="number" min="1">')
- .css("width", "40%")
- .val(height)
- .appendTo(box0);
- }
- var closeTimer;
- var closeFunc = function() {
- var w = in0.val();
- var h = has_height ? in1.val() : undefined;
- var label = that.options.label;
- label.text(w+(has_height ? (' x '+h) : ''));
- $(that.options.width).val(w).change();
- if(has_height) {
- $(that.options.height).val(h).change();
- }
- that.destroy();
- };
- container.keypress(function(e) {
- if(e.which === 13) { // pressed ENTER
- container.fadeOut(100, closeFunc);
- }
- });
- container.on('mouseleave', function(e) {
- closeTimer = setTimeout(function() {
- container.fadeOut(200, closeFunc);
- }, 100);
- });
- container.on('mouseenter', function(e) {
- clearTimeout(closeTimer);
- });
- container.css({
- top: (pos.top -10)+"px",
- left: (pos.left +10)+"px"
- });
- container.fadeIn(200);
- }
- });
-
- $.widget( "nodereddashboard.elementSizer", {
- _create: function() {
- var that = this;
- var gridWidth = 6;
- var width = parseInt($(this.options.width).val()||0);
- var height = parseInt(this.options.hasOwnProperty('height')?$(this.options.height).val():"1")||0;
- var hasAuto = (!this.options.hasOwnProperty('auto') || this.options.auto);
-
- this.element.css({
- minWidth: this.element.height()+4
- });
- var auto_text = c_("auto");
- var sizeLabel = (width === 0 && height === 0)?auto_text:width+(this.options.hasOwnProperty('height')?" x "+height:"");
- this.element.text(sizeLabel).on('mousedown',function(evt) {
- evt.stopPropagation();
- evt.preventDefault();
-
- var width = parseInt($(that.options.width).val()||0);
- var height = parseInt(that.options.hasOwnProperty('height')?$(that.options.height).val():"1")||0;
- var maxWidth = 0;
- var maxHeight;
- var fixedWidth = false;
- var fixedHeight = false;
- var group = $(that.options.group).val();
- if (group) {
- var groupNode = RED.nodes.node(group);
- if (groupNode) {
- gridWidth = Math.max(6,groupNode.width,+width);
- maxWidth = groupNode.width || gridWidth;
- fixedWidth = true;
- }
- maxHeight = Math.max(6,+height+1);
- }
- else {
- gridWidth = Math.max(12,+width);
- maxWidth = gridWidth;
- maxHeight = 1;
- fixedHeight = true;
- }
-
- var pos = $(this).offset();
- var container = $('<div>').css({
- position: 'absolute',
- background: 'white',
- padding: '5px 10px 10px 10px',
- border: '1px solid grey',
- zIndex: '20',
- borderRadius: "4px",
- display:"none"
- }).appendTo(document.body);
-
- var closeTimer;
- container.on('mouseleave',function(evt) {
- closeTimer = setTimeout(function() {
- container.fadeOut(200, function() { $(this).remove(); });
- },100)
- });
- container.on('mouseenter',function() {
- clearTimeout(closeTimer);
- })
-
- var label = $("<div>").css({
- fontSize: '13px',
- color: '#aaa',
- float: 'left',
- paddingTop: '1px'
- }).appendTo(container).text((width === 0 && height === 0)?auto_text:(width+(that.options.hasOwnProperty('height')?" x "+height:"")));
- label.hover(function() {
- $(this).css('text-decoration', 'underline');
- }, function() {
- $(this).css('text-decoration', 'none');
- });
-
- label.click(function(e) {
- var group = $(that.options.group).val();
- var groupNode = null;
- if(group) {
- groupNode = RED.nodes.node(group);
- if(groupNode === null) {
- return;
- }
- }
- $(that).elementSizerByNum({
- width: that.options.width,
- height: that.options.height,
- groupNode: groupNode,
- pos: pos,
- label: that.element,
- has_height: that.options.hasOwnProperty('height')
- });
- closeTimer = setTimeout(function() {
- container.fadeOut(200, function() {
- $(this).remove();
- });
- },100)
- });
-
- var buttonRow = $('<div>',{style:"text-align:right; height:25px;"}).appendTo(container);
-
- if (hasAuto) {
- var button = $('<a>',{href:"#",class:"editor-button editor-button-small",style:"margin-bottom:5px"})
- .text(auto_text)
- .appendTo(buttonRow)
- .on('mouseup',function(evt) {
- that.element.text(auto_text)
- $(that.options.width).val(0).change();
- $(that.options.height).val(0).change();
- evt.preventDefault();
- container.fadeOut(200, function() { $(this).remove(); });
- });
- }
-
- var cellBorder = "1px dashed lightGray";
- var cellBorderExisting = "1px solid gray";
- var cellBorderHighlight = "1px dashed black";
- var rows = [];
- function addRow(i) {
- var row = $('<div>').css({padding:0,margin:0,height:"25px","box-sizing":"border-box"}).appendTo(container);
- rows.push(row);
- cells.push([])
- for (var j=0; j<gridWidth; j++) {
- addCell(i,j);
- }
- }
- function addCell(i,j) {
- var row = rows[i];
- var cell = $('<div>').css({
- display:"inline-block",
- width: "25px",
- height: "25px",
- borderRight: (j===(width-1)&&i<height)?cellBorderExisting:cellBorder,
- borderBottom: (i===(height-1)&&j<width)?cellBorderExisting:cellBorder,
- boxSizing: "border-box",
- cursor:"pointer",
- background: (j<maxWidth)?"#fff":"#eee"
- }).appendTo(row);
- cells[i].push(cell);
- if (j===0) {
- cell.css({borderLeft:((i<=height-1)?cellBorderExisting:cellBorder)});
- }
- if (i===0) {
- cell.css({borderTop:((j<=width-1)?cellBorderExisting:cellBorder)});
- }
- if (j<maxWidth) {
- cell.data("w",j);
- cell.data("h",i);
- cell.on("mouseup",function() {
- that.element.text(($(this).data("w")+1)+(that.options.hasOwnProperty('height')?" x "+($(this).data("h")+1):""))
- $(that.options.width).val($(this).data("w")+1).change();
- $(that.options.height).val($(this).data("h")+1).change();
- container.fadeOut(200, function() { $(this).remove(); });
- });
- cell.on("mouseover",function() {
- var w = $(this).data("w");
- var h = $(this).data("h");
- label.text((w+1)+(that.options.hasOwnProperty('height')?" x "+(h+1):""));
- for (var y = 0; y<maxHeight; y++) {
- for (var x = 0; x<maxWidth; x++) {
- cells[y][x].css({
- background: (y<=h && x<=w)?'#ddd':'#fff',
- borderLeft: (x===0&&y<=h)?cellBorderHighlight:(x===0)?((y<=height-1)?cellBorderExisting:cellBorder):'',
- borderTop: (y===0&&x<=w)?cellBorderHighlight:(y===0)?((x<=width-1)?cellBorderExisting:cellBorder):'',
- borderRight: (x===w&&y<=h)?cellBorderHighlight:((x===width-1&&y<=height-1)?cellBorderExisting:cellBorder),
- borderBottom: (y===h&&x<=w)?cellBorderHighlight:((y===height-1&&x<=width-1)?cellBorderExisting:cellBorder)
- })
- }
- }
- if (!fixedHeight && h === maxHeight-1) {
- addRow(maxHeight++)
- }
- if (!fixedWidth && w === maxWidth-1) {
- maxWidth++;
- gridWidth++;
- for (var r=0; r<maxHeight; r++) {
- addCell(r,maxWidth-1);
- }
- }
- })
- }
- }
- var cells = [];
- for (var i=0; i<maxHeight; i++) {
- addRow(i);
- }
- container.css({
- top:(pos.top)+"px",
- left:(pos.left)+"px"
- });
- container.fadeIn(200);
- })
- }
- });
- })(jQuery);
- </script>
-
- <script type="text/html" data-template-name="ui_base">
- <div class='form-row'>
- This <i>ui_base</i> node is the main node that all<br/>other dashboard widget nodes communicate to.<br/>
- <br/>One instance is required to support the dashboard.<br/>
- <br/>If you have no dashboard you can delete this node.<br/>
- It will be re-created automatically if required.<br/>
- </div>
- </script>
|