├── .gitattributes ├── .gitignore ├── .jscsrc ├── .jshintignore ├── .jshintrc ├── .npmignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Charts.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── angular-chart.js-1.1.1-patched.tgz ├── config-fields.md ├── dist ├── css │ ├── app.min.css │ ├── app.min.less │ └── gridstack-extra.min.css ├── dashboard.appcache ├── fonts │ ├── MaterialIcons-Regular.woff │ ├── MaterialIcons-Regular.woff2 │ ├── fontawesome-webfont.woff │ ├── fontawesome-webfont.woff2 │ ├── weather-icons-lite.woff │ └── weather-icons-lite.woff2 ├── i18n.js ├── icon120x120.png ├── icon192x192.png ├── icon64x64.png ├── index.html └── js │ ├── app.min.js │ └── tinycolor-min.js ├── fixfa.js ├── fixgrid.js ├── gulpfile.js ├── gulpfile.old ├── index.js ├── license.js ├── nodes ├── icons │ ├── ui_button.png │ ├── ui_chart.png │ ├── ui_colour_picker.png │ ├── ui_date_picker.png │ ├── ui_dropdown.png │ ├── ui_form.png │ ├── ui_gauge.png │ ├── ui_numeric.png │ ├── ui_slider.png │ ├── ui_switch.png │ ├── ui_template.png │ ├── ui_text.png │ └── ui_toast.png ├── locales │ ├── de │ │ ├── ui_base.json │ │ ├── ui_button.json │ │ ├── ui_chart.html │ │ ├── ui_chart.json │ │ ├── ui_form.html │ │ ├── ui_form.json │ │ ├── ui_group.json │ │ ├── ui_link.json │ │ ├── ui_tab.json │ │ ├── ui_template.html │ │ ├── ui_template.json │ │ ├── ui_ui_control.html │ │ └── ui_ui_control.json │ ├── en-US │ │ ├── ui_audio.html │ │ ├── ui_base.html │ │ ├── ui_base.json │ │ ├── ui_button.html │ │ ├── ui_button.json │ │ ├── ui_chart.html │ │ ├── ui_chart.json │ │ ├── ui_colour_picker.html │ │ ├── ui_date_picker.html │ │ ├── ui_dropdown.html │ │ ├── ui_form.html │ │ ├── ui_form.json │ │ ├── ui_gauge.html │ │ ├── ui_group.html │ │ ├── ui_group.json │ │ ├── ui_link.html │ │ ├── ui_link.json │ │ ├── ui_numeric.html │ │ ├── ui_slider.html │ │ ├── ui_spacer.html │ │ ├── ui_switch.html │ │ ├── ui_tab.html │ │ ├── ui_tab.json │ │ ├── ui_template.html │ │ ├── ui_template.json │ │ ├── ui_text.html │ │ ├── ui_text_input.html │ │ ├── ui_toast.html │ │ ├── ui_ui_control.html │ │ └── ui_ui_control.json │ └── ja │ │ ├── ui_base.json │ │ ├── ui_chart.html │ │ ├── ui_chart.json │ │ ├── ui_form.html │ │ ├── ui_form.json │ │ ├── ui_group.json │ │ ├── ui_link.json │ │ ├── ui_tab.json │ │ ├── ui_template.html │ │ ├── ui_template.json │ │ ├── ui_ui_control.html │ │ └── ui_ui_control.json ├── ui_audio.html ├── ui_audio.js ├── ui_base.html ├── ui_base.js ├── ui_button.html ├── ui_button.js ├── ui_chart.html ├── ui_chart.js ├── ui_colour_picker.html ├── ui_colour_picker.js ├── ui_date_picker.html ├── ui_date_picker.js ├── ui_dropdown.html ├── ui_dropdown.js ├── ui_form.html ├── ui_form.js ├── ui_gauge.html ├── ui_gauge.js ├── ui_group.html ├── ui_group.js ├── ui_link.html ├── ui_link.js ├── ui_numeric.html ├── ui_numeric.js ├── ui_slider.html ├── ui_slider.js ├── ui_spacer.html ├── ui_spacer.js ├── ui_switch.html ├── ui_switch.js ├── ui_tab.html ├── ui_tab.js ├── ui_template.html ├── ui_template.js ├── ui_text.html ├── ui_text.js ├── ui_text_input.html ├── ui_text_input.js ├── ui_toast.html ├── ui_toast.js ├── ui_ui_control.html └── ui_ui_control.js ├── package.json ├── src ├── components │ ├── ui-card-panel │ │ ├── ui-card-panel-ctrl.js │ │ ├── ui-card-panel.css │ │ ├── ui-card-panel.html │ │ ├── ui-card-panel.js │ │ ├── ui-card-size.js │ │ └── ui-masonry.js │ ├── ui-chart-js │ │ ├── ui-chart-js.html │ │ └── ui-chart-js.js │ ├── ui-component │ │ ├── templates │ │ │ ├── button.css │ │ │ ├── button.html │ │ │ ├── chart.css │ │ │ ├── chart.html │ │ │ ├── colour-picker.css │ │ │ ├── colour-picker.html │ │ │ ├── date-picker.css │ │ │ ├── date-picker.html │ │ │ ├── dropdown.css │ │ │ ├── dropdown.html │ │ │ ├── form.css │ │ │ ├── form.html │ │ │ ├── gauge.css │ │ │ ├── gauge.html │ │ │ ├── numeric.css │ │ │ ├── numeric.html │ │ │ ├── slider.css │ │ │ ├── slider.html │ │ │ ├── spacer.css │ │ │ ├── spacer.html │ │ │ ├── switch.css │ │ │ ├── switch.html │ │ │ ├── template.css │ │ │ ├── template.html │ │ │ ├── text-input-CR.html │ │ │ ├── text-input.css │ │ │ ├── text-input.html │ │ │ ├── text.css │ │ │ └── text.html │ │ ├── ui-component-ctrl.js │ │ └── ui-component.js │ ├── ui-gauge │ │ ├── liquidFillGauge.js │ │ ├── ui-gauge.html │ │ └── ui-gauge.js │ └── ui-icon │ │ ├── ui-icon.html │ │ └── ui-icon.js ├── dashboard.appcache ├── directives │ ├── ui-colour-picker.js │ ├── ui-highlight.js │ ├── ui-template.js │ └── ui-touchend.js ├── filters │ ├── chartGetRange.js │ ├── spaceToUnderscore.js │ └── trusted.js ├── gridstack-extra.scss ├── i18n.js ├── icon120x120.png ├── icon192x192.png ├── icon64x64.png ├── index.html ├── logout.html ├── main.js ├── main.less ├── partials │ ├── main.html │ └── toast.html ├── services │ ├── events.js │ └── sizes.js ├── socket.io │ └── socket.io.js ├── theme.less └── wheel.png └── ui.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | node-*.tgz 3 | package-lock.json 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "fileExtensions": [ ".js", "jscs" ], 3 | "excludeFiles": [ "node_modules/**" ], 4 | "validateIndentation": 4, 5 | "disallowKeywordsOnNewLine": [], 6 | "disallowMixedSpacesAndTabs": true, 7 | "disallowMultipleSpaces": {"allowEOLComments": true}, 8 | "disallowNewlineBeforeBlockStatements": true, 9 | "disallowTabs": true, 10 | "disallowTrailingWhitespace": true, 11 | "requireCurlyBraces": true, 12 | //"requireKeywordsOnNewLine": ["else", "catch"], 13 | //"requireSemicolons": true, 14 | //"requireSpaceAfterBinaryOperators": true, 15 | //"requireSpaceAfterComma": {"allExcept": ["trailing"]}, 16 | "requireSpaceAfterKeywords": ["do","for","if","else","switch","case","try","while"], 17 | "requireSpaceBeforeBlockStatements": 1, 18 | "requireSpaceBeforeObjectValues": false, 19 | "requireSpacesInForStatement": true, 20 | "requireSpacesInFunction": { "beforeOpeningCurlyBrace": true }, 21 | //"validateParameterSeparator": ", ", 22 | //"validateQuoteMarks": false, 23 | "maximumLineLength": 300 24 | } 25 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "asi": true, // allow missing semicolons 3 | "curly": true, // require braces 4 | "eqnull": true, // ignore ==null 5 | //"eqeqeq": true, // enforce === 6 | "freeze": true, // don't allow override 7 | "indent": 4, // default indent of 4 8 | "forin": true, // require property filtering in "for in" loops 9 | "immed": true, // require immediate functions to be wrapped in ( ) 10 | "nonbsp": true, // warn on unexpected whitespace breaking chars 11 | //"strict": true, // commented out for now as it causes 100s of warnings, but want to get there eventually 12 | //"unused": true, // Check for unused functions and variables 13 | "loopfunc": true, // allow functions to be defined in loops 14 | //"expr": true, // allow ternery operator syntax... 15 | "shadow": true, // allow variable shadowing (re-use of names...) 16 | "sub": true, // don't warn that foo['bar'] should be written as foo.bar 17 | "proto": true, // allow setting of __proto__ in node < v0.12, 18 | "esversion": 11 // allow es11(ES2020) 19 | } 20 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /src 3 | gulpfile.js 4 | .gitignore 5 | .npmignore 6 | node*.tgz 7 | ang*.tgz 8 | *.bak 9 | package-lock.json 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Node-RED-Dashboard 2 | 3 | We welcome contributions, but request you follow these guidelines. 4 | 5 | - [Raising issues](#raising-issues) 6 | - [Feature requests](#feature-requests) 7 | - [Pull-Requests](#pull-requests) 8 | - [Contributor License Agreement](#contributor-license-agreement) 9 | 10 | This project adheres to the [Contributor Covenant 1.4](http://contributor-covenant.org/version/1/4/). 11 | By participating, you are expected to uphold this code. Please report unacceptable 12 | behaviour to any of the [project's core team](https://github.com/orgs/node-red/teams/core). 13 | 14 | ## Raising issues 15 | 16 | Please raise any bug reports on the relevant project's issue tracker. Be sure to 17 | search the list to see if your issue has already been raised. 18 | 19 | A good bug report is one that make it easy for us to understand what you were 20 | trying to do and what went wrong. 21 | 22 | Provide as much context as possible so we can try to recreate the issue. 23 | If possible, include the relevant part of your flow. To do this, select the 24 | relevant nodes, press Ctrl-E and copy the flow data from the Export dialog. 25 | 26 | At a minimum, please include: 27 | 28 | - Version of Node-RED-Dashboard - either release number if you downloaded a zip, or the first few lines of `git log` if you are cloning the repository directly. 29 | - Version of Node-RED - either release number if you downloaded a zip, or the first few lines of `git log` if you are cloning the repository directly. 30 | - Version of node.js - what does `node -v` say? 31 | 32 | ## Feature requests 33 | 34 | For feature requests, please raise them on the [mailing list](https://groups.google.com/forum/#!forum/node-red). 35 | 36 | ## Pull-Requests 37 | 38 | If you want to raise a pull-request with a new feature, or a refactoring 39 | of existing code, it may well get rejected if you haven't discussed it on 40 | the [mailing list](https://groups.google.com/forum/#!forum/node-red) first. 41 | 42 | ### Contributor License Agreement 43 | 44 | All contributors need to sign the JS Foundation's Contributor License Agreement. 45 | It is an online process and quick to do. You can read the details of the agreement 46 | here: https://cla.js.foundation/node-red/node-red. 47 | 48 | If you raise a pull-request without having signed the CLA, you will be prompted 49 | to do so automatically. 50 | 51 | ### Coding standards 52 | 53 | Please ensure you follow the coding standards used through-out the existing 54 | code base. Some basic rules include: 55 | 56 | - indent with 4-spaces, no tabs. No arguments. 57 | - opening brace on same line as `if`/`for`/`function` and so on, closing brace 58 | on its own line. 59 | - There are **.jshintrc** and **.jscsrc** files included in the project which 60 | should be used to help formatting. 61 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 20 | 21 | ### What are the steps to reproduce? 22 | 23 | ### What happens? 24 | 25 | ### What do you expect to happen? 26 | 27 | ### Please tell us about your environment: 28 | 29 | - [ ] Node-RED-Dashboard version: 30 | - [ ] Node-RED version: 31 | - [ ] node.js version: 32 | - [ ] npm version: 33 | - [ ] Platform/OS: 34 | - [ ] Browser: 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016,2020 JS Foundation and other contributors, https://js.foundation/ 2 | Copyright 2016 IBM Corp. 3 | Copyright 2015 Andrei Tatar 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /angular-chart.js-1.1.1-patched.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/angular-chart.js-1.1.1-patched.tgz -------------------------------------------------------------------------------- /dist/dashboard.appcache: -------------------------------------------------------------------------------- 1 | CACHE MANIFEST 2 | # Time: Tue Mar 12 2024 15:31:00 GMT+0000 (Greenwich Mean Time) 3 | 4 | CACHE: 5 | i18n.js 6 | icon120x120.png 7 | icon192x192.png 8 | icon64x64.png 9 | css/app.min.css 10 | css/app.min.less 11 | css/gridstack-extra.min.css 12 | js/app.min.js 13 | js/tinycolor-min.js 14 | socket.io/socket.io.js 15 | fonts/MaterialIcons-Regular.woff 16 | fonts/MaterialIcons-Regular.woff2 17 | fonts/fontawesome-webfont.woff 18 | fonts/fontawesome-webfont.woff2 19 | fonts/weather-icons-lite.woff 20 | fonts/weather-icons-lite.woff2 21 | gs/gridstack.jQueryUI.min.js 22 | gs/gridstack.min.css 23 | gs/gridstack.min.js 24 | loading.html 25 | 26 | NETWORK: 27 | * 28 | 29 | # hash: 87be8dffba3951bcf42145449686dd474231b08260117d82c7fe94178f6cddc9 30 | -------------------------------------------------------------------------------- /dist/fonts/MaterialIcons-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/dist/fonts/MaterialIcons-Regular.woff -------------------------------------------------------------------------------- /dist/fonts/MaterialIcons-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/dist/fonts/MaterialIcons-Regular.woff2 -------------------------------------------------------------------------------- /dist/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/dist/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /dist/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/dist/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /dist/fonts/weather-icons-lite.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/dist/fonts/weather-icons-lite.woff -------------------------------------------------------------------------------- /dist/fonts/weather-icons-lite.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/dist/fonts/weather-icons-lite.woff2 -------------------------------------------------------------------------------- /dist/i18n.js: -------------------------------------------------------------------------------- 1 | // Placeholder only - This is NOT a sustainable solution to i18n localisation 2 | // Replace/overwrite this file with an angular-locale_... file of your choice from the npm angular-i18n project 3 | // Then edit dashboard.appcache - (for example add a digit to the hash) 4 | // Stop, start Node-RED and refresh the browser page twice to flush the cache. 5 | -------------------------------------------------------------------------------- /dist/icon120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/dist/icon120x120.png -------------------------------------------------------------------------------- /dist/icon192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/dist/icon192x192.png -------------------------------------------------------------------------------- /dist/icon64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/dist/icon64x64.png -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 |

Welcome to the Node-RED Dashboard

Please add some UI nodes to your flow and redeploy.
18 | -------------------------------------------------------------------------------- /fixfa.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Patch to fix Font-Awesome urls for loading font 4 | // and to add in fa-sm(all) and fa-xs(extra small) modifiers 5 | var fs = require("fs"); 6 | fs.readFile("node_modules/font-awesome/css/font-awesome.css", 'utf8', function (err, file) { 7 | if (err) { return; } 8 | else { 9 | console.log("Fixing up Font-Awesome css"); 10 | var res1 = file.replace(/\?v=4\.7\../g, ''); 11 | var res2 = res1.replace(/\&v=4\.7\../g, ''); 12 | var res3; 13 | if (res2.indexOf("fa-sm ") === -1) { 14 | res3 = res2.replace(/fa-lg/, 'fa-sm {font-size:0.875em;}\n.fa-xs {font-size:0.75em;}\n.fa-lg'); 15 | } 16 | else { res3 = res2; } 17 | fs.writeFile("node_modules/font-awesome/css/font-awesome.css", res3, 'utf8', function (err) { 18 | if (err) { console.log("Failed to re-write file."); } 19 | else { 20 | console.log("Fixed up Font-Awesome css"); 21 | } 22 | }); 23 | } 24 | }); 25 | 26 | // Google-Material-Font 27 | // Fix relative path of fonts from `./fonts/` to `../fonts/` in css file. 28 | fs.readFile('node_modules/material-design-icons-iconfont/dist/material-design-icons.css', 'utf8', function (err, file) { 29 | if (err) { return; } 30 | else { 31 | console.log('Fixing up Google-Material-Font css'); 32 | const res1 = file 33 | .replace(/"\.\/fonts\//g, '"../fonts/') 34 | .replace(/'\.\/fonts\//g, '\'../fonts/'); 35 | fs.writeFile('node_modules/material-design-icons-iconfont/dist/material-design-icons.css', res1, 'utf8', function (err) { 36 | if (err) { 37 | console.log('Failed to re-write file.'); 38 | } else { 39 | console.log('Fixed up Google-Material-Font css'); 40 | } 41 | }); 42 | } 43 | }); 44 | 45 | // GridStack layout css patches for sass 46 | fs.readFile('src/gridstack-extra.scss', 'utf8', function (err, file) { 47 | if (err) { return; } 48 | else { 49 | console.log('Fixing up GridStack scss'); 50 | const res1 = file 51 | .replace(/ \(100% \/ \$columns\)/g, ' calc(100% \/ \$columns)') 52 | fs.writeFile('src/gridstack-extra.scss', res1, 'utf8', function (err) { 53 | if (err) { 54 | console.log('Failed to re-write file.'); 55 | } else { 56 | console.log('Fixed up GridStack scss'); 57 | } 58 | }); 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /fixgrid.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require("fs"); 4 | 5 | // Remove jquery old versions from gridstack dist 6 | try { fs.rmSync('../gridstack/dist/jquery-ui.js'); } 7 | catch(e) { console.log("unable to delete jquery-ui.js") }; 8 | try { fs.rmSync('../gridstack/dist/jquery-ui.min.js');} 9 | catch(e) { console.log("unable to delete jquery-ui.min.js") }; 10 | try { fs.rmSync('../gridstack/dist/jquery.js'); } 11 | catch(e) { console.log("unable to delete jquery.js") }; 12 | try { fs.rmSync('../gridstack/dist/jquery.min.js'); } 13 | catch(e) { console.log("unable to delete jquery.min.js") }; -------------------------------------------------------------------------------- /license.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | /* Copyright 2016,2020 JS Foundation and other contributors, https://js.foundation/ */ 3 | /* Copyright 2016 IBM Corp. */ 4 | /* Copyright 2015 Andrei Tatar */ 5 | /* */ 6 | /* Licensed under the Apache License, Version 2.0 (the "License"); */ 7 | /* you may not use this file except in compliance with the License. */ 8 | /* You may obtain a copy of the License at */ 9 | /* */ 10 | /* http://www.apache.org/licenses/LICENSE-2.0 */ 11 | /* */ 12 | /* Unless required by applicable law or agreed to in writing, software */ 13 | /* distributed under the License is distributed on an "AS IS" BASIS, */ 14 | /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ 15 | /* See the License for the specific language governing permissions and */ 16 | /* limitations under the License. */ 17 | /* */ 18 | -------------------------------------------------------------------------------- /nodes/icons/ui_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_button.png -------------------------------------------------------------------------------- /nodes/icons/ui_chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_chart.png -------------------------------------------------------------------------------- /nodes/icons/ui_colour_picker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_colour_picker.png -------------------------------------------------------------------------------- /nodes/icons/ui_date_picker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_date_picker.png -------------------------------------------------------------------------------- /nodes/icons/ui_dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_dropdown.png -------------------------------------------------------------------------------- /nodes/icons/ui_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_form.png -------------------------------------------------------------------------------- /nodes/icons/ui_gauge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_gauge.png -------------------------------------------------------------------------------- /nodes/icons/ui_numeric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_numeric.png -------------------------------------------------------------------------------- /nodes/icons/ui_slider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_slider.png -------------------------------------------------------------------------------- /nodes/icons/ui_switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_switch.png -------------------------------------------------------------------------------- /nodes/icons/ui_template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_template.png -------------------------------------------------------------------------------- /nodes/icons/ui_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_text.png -------------------------------------------------------------------------------- /nodes/icons/ui_toast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/nodes/icons/ui_toast.png -------------------------------------------------------------------------------- /nodes/locales/de/ui_base.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_base": { 3 | "label": { 4 | "dashboard": "Dashboard", 5 | "category": "Dashboard", 6 | "title": "Titel", 7 | "options": "Optionen", 8 | "date-format": "Datumsformat", 9 | "sizes": "Größen", 10 | "horizontal": "Horizontal", 11 | "vertical": "Vertikal", 12 | "widget-size": "1x1 Widget-Größe", 13 | "widget-spacing": "Widget-Abstände", 14 | "group-padding": "Gruppenabstände innen", 15 | "group-spacing": "Gruppenabstände außen", 16 | "layout": "Layout", 17 | "angular": "Angular", 18 | "theme": "Theme", 19 | "site": "Site" 20 | }, 21 | "auto": "Auto", 22 | "title": "Node-RED Dashboard", 23 | "layout": { 24 | "tab-and-link": "Tabs & Links", 25 | "tab": "Tab", 26 | "link": "Link", 27 | "group": "Gruppe", 28 | "edit": "Bearbeiten", 29 | "spacer": "Abstand", 30 | "layout": "Layout", 31 | "layout-editor": "Dashboard Layout-Editor", 32 | "width": "Breite", 33 | "auto": "Automatische Größenanpassung", 34 | "manual": "Manuelle Größenanpassung" 35 | }, 36 | "theme": { 37 | "style": "Stil", 38 | "custom-profile": "Benutzerdefiniertes Profil", 39 | "custom-profile-name": "Erscheinungsbild ohne Titel 1", 40 | "base-settings": "Basiseinstellungen", 41 | "page-settings": "Seiteneinstellungen", 42 | "page": { 43 | "title": "Hintergrund Titelleiste", 44 | "page": "Hintergrund Seite", 45 | "side": "Hintergrund Seitenleiste" 46 | }, 47 | "group-settings": "Gruppeneinstellungen", 48 | "group": { 49 | "text": "Gruppentext", 50 | "border": "Gruppenrand", 51 | "background": "Gruppenhintergrund" 52 | }, 53 | "widget-settings": "Widget-Einstellungen", 54 | "widget": { 55 | "text": "Widget-Text", 56 | "colour": "Widget-Farbe", 57 | "background": "Widget-Hintergrund" 58 | } 59 | }, 60 | "style": { 61 | "light": "Hell (Standard)", 62 | "dark": "Dunkel", 63 | "custom": "Benutzerdefiniert", 64 | "primary": "Primär", 65 | "accents": "Akzente", 66 | "background": "Hintergrund", 67 | "warnings": "Warnungen", 68 | "palette": "Hell / Dunkel" 69 | }, 70 | "base": { 71 | "colour": "Farbe", 72 | "font": "Schriftart" 73 | }, 74 | "font": { 75 | "system": "System-Schriftart (Standard)" 76 | }, 77 | "site": { 78 | "title": "Node-RED Dashboard", 79 | "date-format": "DD.MM.YYYY" 80 | }, 81 | "title-bar": { 82 | "show": "Titelleiste anzeigen", 83 | "hide": "Titelleiste verbergen" 84 | }, 85 | "swipe": { 86 | "no-swipe": "Kein Wischen zwischen Tabs", 87 | "allow-swipe": "Wischen zwischen Tabs zulassen" 88 | }, 89 | "lock": { 90 | "clicked": "Klicken, um das Seitenmenü anzuzeigen", 91 | "locked": "Seitenmenü immer anzeigen", 92 | "locked-icon": "Nur Icons anzeigen" 93 | }, 94 | "temp": { 95 | "allow-theme": "Node-RED-Erscheinungsbild", 96 | "no-theme": "Angular-Erscheinungsbild in ui_template", 97 | "none": "Angular-Erscheinungsbild" 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_button.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_button": { 3 | "label": { 4 | "group": "Gruppe", 5 | "size": "Größe", 6 | "icon": "Icon", 7 | "optionalIcon": "Optionales Icon", 8 | "label": "Beschriftung", 9 | "optionalLabel": "Optionale Beschriftung", 10 | "tooltip": "Tooltipp", 11 | "optionalTooltip": "Optionaler Tooltipp", 12 | "color": "Farbe", 13 | "optionalColor": "Optionale Text/Icon-Farbe", 14 | "background": "Hintergrund", 15 | "optionalBackgroundColor": "Optionale Hintergrundfarbe", 16 | "whenClicked": "Sende beim Klicken:", 17 | "payload": "Payload", 18 | "topic": "Topic", 19 | "emulateClick": "Emuliere einen Klick bei einer eingehenden Nachricht:", 20 | "className": "Klasse", 21 | "classNamePlaceholder": "Optionale(r) CSS-Klassenname(n) für das Widget" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_chart.html: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_chart.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_chart": { 3 | "label": { 4 | "group": "Gruppe", 5 | "size": "Größe", 6 | "label": "Beschriftung", 7 | "optionalChartTitle": "Optionaler Diagrammtitel", 8 | "type": "Typ", 9 | "lineChart": "  Liniendiagramm", 10 | "barChart": "  Balkendiagramm", 11 | "barChartH": "  Balkendiagramm (H)", 12 | "pieChart": "  Kreisdiagramm", 13 | "polarAreaChart": "  Polargebietskarte", 14 | "radarChart": "  Radarkarte", 15 | "enlargePoints": "Punkte vergrößern", 16 | "xAxis": "X-Achse", 17 | "last": "Letzten", 18 | "seconds": "Sekunden", 19 | "minutes": "Minuten", 20 | "hours": "Stunden", 21 | "days": "Tage", 22 | "weeks": "Wochen", 23 | "or": "oder", 24 | "points": "Punkte", 25 | "xAxisLabel": "X-Beschriftung", 26 | "HHmmss": "HH:mm:ss", 27 | "HHmm": "HH:mm", 28 | "yearMonthDate": "Jahr-Monat-Tag", 29 | "dateMonth": "Tag/Monat", 30 | "dayHHmm": "Wochentag HH:mm", 31 | "custom": "benutzerdefiniert", 32 | "automatic": "automatisch", 33 | "asUTC": "als UTC", 34 | "yAxis": "Y-Achse", 35 | "min": "min", 36 | "max": "max", 37 | "legend": "Legende", 38 | "none": "Keine", 39 | "show": "Anzeigen", 40 | "interpolate": "Interpolation", 41 | "linear": "Linear", 42 | "step": "Stufen", 43 | "bezier": "Bezier", 44 | "cubic": "Kubisch", 45 | "cubicMono": "Kubisch-Mono", 46 | "cutout": "Ausschnitt", 47 | "useFirstColourForAllBars": "Erste Farbe für alle Balken verwenden", 48 | "seriesColours": "Serienfarben", 49 | "blankLabel": "Leer-Text", 50 | "displayThisTextBeforeValidDataArrives": "Anzuzeigender Text bevor gültige Daten eintreffen", 51 | "useDifferentColor": "Unterschiedliche Farben für Datenserie verwenden", 52 | "className": "Klasse", 53 | "classNamePlaceholder": "Optionale(r) CSS-Klassenname(n) für das Widget" 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_form.html: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_form.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_form": { 3 | "label": { 4 | "group": "Gruppe", 5 | "size": "Größe", 6 | "label": "Beschriftung", 7 | "optionalLabel": "Optionale Beschriftung", 8 | "formElements": "Formular- elemente", 9 | "type": "Typ", 10 | "required": "Erforderlich", 11 | "rows": "UiZeilen", 12 | "remove": "Entfernen", 13 | "egName": "z.B. Name", 14 | "egName2": "z.B. Name", 15 | "text": "Text", 16 | "multiline": "Mehrzeilig", 17 | "number": "Zahl", 18 | "email": "E-Mail", 19 | "password": "Kennwort", 20 | "checkbox": "Auswahlkästchen", 21 | "switch": "Schalter", 22 | "date": "Datum", 23 | "time": "Zeit", 24 | "element": "Element", 25 | "buttons": "Schaltflächen", 26 | "submitButtonText": "Text Absenden-Schaltfläche", 27 | "cancelButtonText": "Text Abbrechen-Schaltfläche", 28 | "topic": "Topic", 29 | "optionalMsgTopic": "Optionaler msg.topic", 30 | "splitLayout": "Platzieren sie die formularelemente in 2 spalten", 31 | "className": "Klasse", 32 | "classNamePlaceholder": "Optionale(r) CSS-Klassenname(n) für das Widget" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_group.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_group": { 3 | "label": { 4 | "name": "Name", 5 | "tab": "Tab", 6 | "width": "Breite", 7 | "default": "Standard", 8 | "group": "Gruppe", 9 | "unassigned": "nicht zugewiesen", 10 | "className": "Klasse", 11 | "classNamePlaceholder": "Optionale(r) CSS-Klassenname(n) für das Widget" 12 | }, 13 | "display-name": "Gruppenname anzeigen", 14 | "collapse-name": "Gruppenreduzierung zulassen" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_link.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_link": { 3 | "label": { 4 | "name": "Name", 5 | "link": "Link", 6 | "icon": "Icon", 7 | "open-in": "Öffnen im", 8 | "new-tab": "neuen Tab", 9 | "this-tab": "selben Tab", 10 | "iframe": "iframe", 11 | "className": "Klasse", 12 | "classNamePlaceholder": "Optionale(r) CSS-Klassenname(n) für das Widget" 13 | }, 14 | "tip": "Das Icon kann entweder ein Material-Design-Icon (z.B. check oder close), ein Font-Awesome-Icon (z.B. fa-fire) oder ein Wetter-Icon (z.B. wi-wu-sunny) sein.

Des Weiteren können alle Google-Material-Icons verwendet werden, indem dem Icon-Namen mi- vorangestellt wird (z.B. mi-videogame_asset).

" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_tab.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_tab": { 3 | "label": { 4 | "home": "Home", 5 | "tab": "Tab", 6 | "name": "Name", 7 | "icon": "Icon", 8 | "state": "Status", 9 | "navmenu": "Nav. Menü", 10 | "enabled": "Aktiviert", 11 | "disabled": "Deaktivert", 12 | "visible": "Sichtbar", 13 | "hidden": "Versteckt" 14 | }, 15 | "info": { 16 | "disabled": " Tab im Dashboard deaktiviert.", 17 | "hidden": " Tab im Nav.-Menü versteckt." 18 | }, 19 | "tip": "Das Icon kann entweder ein Material-Design-Icon (z.B. check oder close), ein Font-Awesome-Icon (z.B. fa-fire) oder ein Wetter-Icon (z.B. wi-wu-sunny) sein.

Des Weiteren können alle Google-Material-Icons verwendet werden, indem dem Icon-Namen mi- vorangestellt wird (z.B. mi-videogame_asset).

" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_template.html: -------------------------------------------------------------------------------- 1 | 49 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_template": { 3 | "label": { 4 | "type": "Vorlagentyp", 5 | "local": "Widget in Gruppe", 6 | "global": "Hinzugefügt zur -Sektion der Seite", 7 | "group": "Gruppe", 8 | "size": "Größe", 9 | "name": "Name", 10 | "pass-through": "Nachrichten vom Eingang weiterleiten", 11 | "store-state": "Ausgehende Nachrichten speichern", 12 | "template": "Vorlage", 13 | "expand": "Erweitern", 14 | "resend": "Letzten Wert beim Aktualisieren neuladen", 15 | "className": "Klasse", 16 | "classNamePlaceholder": "Optionale(r) CSS-Klassenname(n) für das Widget" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_ui_control.html: -------------------------------------------------------------------------------- 1 | 30 | -------------------------------------------------------------------------------- /nodes/locales/de/ui_ui_control.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_ui_control": { 3 | "label": { 4 | "name": "Name" 5 | }, 6 | "placeholder": { 7 | "name": "Name" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_audio.html: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_base.html: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_base.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_base": { 3 | "label": { 4 | "dashboard": "dashboard", 5 | "category": "dashboard", 6 | "title": "Title", 7 | "options": "Options", 8 | "date-format": "Date Format", 9 | "sizes": "Sizes", 10 | "horizontal": "Horizontal", 11 | "vertical": "Vertical", 12 | "widget-size": "1x1 Widget Size", 13 | "widget-spacing": "Widget Spacing", 14 | "group-padding": "Group Padding", 15 | "group-spacing": "Group Spacing", 16 | "layout": "Layout", 17 | "angular": "Angular", 18 | "theme": "Theme", 19 | "site": "Site" 20 | }, 21 | "auto": "auto", 22 | "title": "Node-RED Dashboard", 23 | "layout": { 24 | "tab-and-link": "Tabs & Links", 25 | "tab": "tab", 26 | "link": "link", 27 | "group": "group", 28 | "edit": "edit", 29 | "spacer": "spacer", 30 | "layout": "layout", 31 | "layout-editor": "Dashboard layout editor", 32 | "width": "Width", 33 | "auto": "auto-sizing", 34 | "manual": "manual resize" 35 | }, 36 | "theme": { 37 | "style": "Style", 38 | "custom-profile": "Custom Profile", 39 | "custom-profile-name": "Untitled Theme 1", 40 | "base-settings": "Base Settings", 41 | "page-settings": "Page Settings", 42 | "page": { 43 | "title": "Title Bar Background", 44 | "page": "Page Background", 45 | "side": "Side Bar Background" 46 | }, 47 | "group-settings": "Group Settings", 48 | "group": { 49 | "text": "Group Text", 50 | "border": "Group Border", 51 | "background": "Group Background" 52 | }, 53 | "widget-settings": "Widget Settings", 54 | "widget": { 55 | "text": "Widget Text", 56 | "colour": "Widget Colour", 57 | "background": "Widget Background" 58 | } 59 | }, 60 | "style": { 61 | "light": "Light (default)", 62 | "dark": "Dark", 63 | "custom": "Custom", 64 | "primary": "Primary", 65 | "accents": "Accents", 66 | "background": "Background", 67 | "warnings": "Warnings", 68 | "palette": "Light / Dark" 69 | }, 70 | "base": { 71 | "colour": "Colour", 72 | "font": "Font" 73 | }, 74 | "font": { 75 | "system": "System Font (default)" 76 | }, 77 | "site": { 78 | "title": "Node-RED Dashboard", 79 | "date-format": "DD/MM/YYYY" 80 | }, 81 | "title-bar": { 82 | "show": "Show the title bar", 83 | "hide": "Hide the title bar" 84 | }, 85 | "swipe": { 86 | "no-swipe": "No swipe between tabs", 87 | "allow-swipe": "Allow swipe between tabs", 88 | "allow-swipe-mouse": "Allow swipe (+mouse) between tabs", 89 | "show-menu": "Swipe to open/close menu" 90 | }, 91 | "lock": { 92 | "clicked": "Click to show side menu", 93 | "locked": "Always show side menu", 94 | "locked-icon": "Always show icons only" 95 | }, 96 | "temp": { 97 | "allow-theme": "Node-RED theme everywhere", 98 | "no-theme": "Use Angular theme in ui_template", 99 | "none": "Angular theme everywhere" 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_button.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_button.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_button": { 3 | "label": { 4 | "group": "Group", 5 | "size": "Size", 6 | "icon": "Icon", 7 | "optionalIcon": "optional icon", 8 | "label": "Label", 9 | "optionalLabel": "optional label", 10 | "tooltip": "Tooltip", 11 | "optionalTooltip": "optional tooltip", 12 | "color": "Color", 13 | "optionalColor": "optional text/icon color", 14 | "background": "Background", 15 | "optionalBackgroundColor": "optional background color", 16 | "whenClicked": "When clicked, send:", 17 | "payload": "Payload", 18 | "topic": "Topic", 19 | "emulateClick": "If msg arrives on input, emulate a button click:", 20 | "className": "Class", 21 | "classNamePlaceholder": "Optional CSS class name(s) for widget" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_chart.html: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_chart.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_chart": { 3 | "label": { 4 | "group": "Group", 5 | "size": "Size", 6 | "label": "Label", 7 | "optionalChartTitle": "optional chart title", 8 | "type": "Type", 9 | "lineChart": "  Line chart", 10 | "barChart": "  Bar chart", 11 | "barChartH": "  Bar chart (H)", 12 | "pieChart": "  Pie chart", 13 | "polarAreaChart": "  Polar area chart", 14 | "radarChart": "  Radar chart", 15 | "enlargePoints": "enlarge points", 16 | "xAxis": "X-axis", 17 | "last": "last", 18 | "seconds": "seconds", 19 | "minutes": "minutes", 20 | "hours": "hours", 21 | "days": "days", 22 | "weeks": "weeks", 23 | "or": "OR", 24 | "points": "points", 25 | "xAxisLabel": "X-axis Label", 26 | "HHmmss": "HH:mm:ss", 27 | "HHmm": "HH:mm", 28 | "yearMonthDate": "Year-Month-Date", 29 | "dateMonth": "Date/Month", 30 | "dayHHmm": "Day HH:mm", 31 | "custom": "custom", 32 | "automatic": "automatic", 33 | "asUTC": "as UTC", 34 | "yAxis": "Y-axis", 35 | "min": "min", 36 | "max": "max", 37 | "legend": "Legend", 38 | "none": "None", 39 | "show": "Show", 40 | "interpolate": "Interpolate", 41 | "linear": "linear", 42 | "step": "step", 43 | "bezier": "bezier", 44 | "cubic": "cubic", 45 | "cubicMono": "cubic-mono", 46 | "cutout": "Cutout", 47 | "useFirstColourForAllBars": "Use first colour for all bars", 48 | "seriesColours": "Series Colours", 49 | "blankLabel": "Blank label", 50 | "displayThisTextBeforeValidDataArrives": "display this text before valid data arrives", 51 | "useDifferentColor": "Use different colour for series data", 52 | "className": "Class", 53 | "classNamePlaceholder": "Optional CSS class name(s) for widget" 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_colour_picker.html: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_date_picker.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_dropdown.html: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_form.html: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_form.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_form": { 3 | "label": { 4 | "group": "Group", 5 | "size": "Size", 6 | "label": "Label", 7 | "optionalLabel": "optional label", 8 | "formElements": "Form elements", 9 | "type": "Type", 10 | "required": "Required", 11 | "rows": "UiRows", 12 | "remove": "Remove", 13 | "egName": "e.g. Name", 14 | "egName2": "e.g. name", 15 | "text": "Text", 16 | "multiline": "Multiline", 17 | "number": "Number", 18 | "email": "E-mail", 19 | "password": "Password", 20 | "checkbox": "Checkbox", 21 | "switch": "Switch", 22 | "date": "Date", 23 | "time": "Time", 24 | "element": "element", 25 | "buttons": "Buttons", 26 | "submitButtonText": "submit button text", 27 | "cancelButtonText": "cancel button text", 28 | "topic": "Topic", 29 | "optionalMsgTopic": "optional msg.topic", 30 | "splitLayout":"Place the form elements in two columns", 31 | "className": "Class", 32 | "classNamePlaceholder": "Optional CSS class name(s) for widget" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_gauge.html: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_group.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_group.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_group" : { 3 | "label" : { 4 | "name" : "Name", 5 | "tab" : "Tab", 6 | "width" : "Width", 7 | "default" : "Default", 8 | "group" : "Group", 9 | "unassigned" : "unassigned", 10 | "className": "Class", 11 | "classNamePlaceholder": "Optional CSS class name(s) for widget" 12 | }, 13 | "display-name" : "Display group name", 14 | "collapse-name" : "Allow group to be collapsed" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_link.html: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_link.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_link" : { 3 | "label" : { 4 | "name" : "Name", 5 | "link" : "Link", 6 | "icon" : "Icon", 7 | "open-in" : "Open in", 8 | "new-tab" : "New Tab", 9 | "this-tab" : "This Tab", 10 | "iframe" : "iframe", 11 | "className": "Class", 12 | "classNamePlaceholder": "Optional CSS class name(s) for widget" 13 | }, 14 | "tip" : "The Icon field can be either a Material Design icon (e.g. 'check', 'close') or a Font Awesome icon (e.g. 'fa-fire'), or a Weather icon (e.g. 'wi-wu-sunny').

You can use the full set of google material icons if you add 'mi-' to the icon name. e.g. 'mi-videogame_asset'.

" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_numeric.html: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_slider.html: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_spacer.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_switch.html: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_tab.html: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_tab.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_tab" : { 3 | "label" : { 4 | "home" : "Home", 5 | "tab" : "Tab", 6 | "name" : "Name", 7 | "icon" : "Icon", 8 | "state" : "State", 9 | "navmenu" : "Nav. Menu", 10 | "enabled" : "Enabled", 11 | "disabled" : "Disabled", 12 | "visible" : "Visible", 13 | "hidden" : "Hidden" 14 | }, 15 | "info": { 16 | "disabled": " Tab is inactive in Dashboard.", 17 | "hidden": " Tab is not shown in Navigation Menu." 18 | }, 19 | "tip" : "The Icon field can be either a Material Design icon (e.g. 'check', 'close') or a Font Awesome icon (e.g. 'fa-fire'), or a Weather icon (e.g. 'wi-wu-sunny').

You can use the full set of google material icons if you add 'mi-' to the icon name. e.g. 'mi-videogame_asset'.

" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_template.html: -------------------------------------------------------------------------------- 1 | 50 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_template": { 3 | "label": { 4 | "type": "Template type", 5 | "local": "Widget in group", 6 | "global": "Added to site section", 7 | "group": "Group", 8 | "size": "Size", 9 | "name": "Name", 10 | "pass-through": "Pass through messages from input.", 11 | "store-state": "Add output messages to stored state.", 12 | "template": "Template", 13 | "expand": "Expand", 14 | "resend": "Reload last value on refresh.", 15 | "className": "Class", 16 | "classNamePlaceholder": "Optional CSS class name(s) for widget" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_text.html: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_text_input.html: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_toast.html: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_ui_control.html: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /nodes/locales/en-US/ui_ui_control.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_ui_control": { 3 | "label": { 4 | "name": "Name", 5 | "output": "Output" 6 | }, 7 | "placeholder": { 8 | "name": "Name" 9 | }, 10 | "events": { 11 | "all": "Connect, lost, change tab or group events", 12 | "change": "Change tab or group events only", 13 | "connect": "Connect event only" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_base.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_base" : { 3 | "label" : { 4 | "dashboard" : "ダッシュボード", 5 | "title" : "タイトル", 6 | "options" : "オプション", 7 | "date-format" : "日付形式", 8 | "sizes" : "サイズ", 9 | "horizontal" : "横", 10 | "vertical" : "縦", 11 | "widget-size" : "最小Widgetサイズ", 12 | "widget-spacing" : "Widget間隔", 13 | "group-padding" : "グループパディング", 14 | "group-spacing" : "グループ間隔", 15 | "layout" : "配置", 16 | "angular": "Angular", 17 | "theme" : "テーマ", 18 | "site" : "サイト" 19 | }, 20 | "auto" : "自動", 21 | "title" : "Node-REDダッシュボード", 22 | "layout" : { 23 | "tab-and-link" : "タブ & リンク", 24 | "tab" : "タブ", 25 | "link" : "リンク", 26 | "group" : "グループ", 27 | "edit" : "編集", 28 | "spacer": "スペーサ", 29 | "layout" : "レイアウト", 30 | "layout-editor" : "ダッシュボードレイアウトエディタ", 31 | "width" : "幅", 32 | "auto": "自動サイズ調整", 33 | "manual": "手動サイズ変更" 34 | }, 35 | "theme" : { 36 | "style" : "スタイル", 37 | "custom-profile" : "カスタムプロファイル", 38 | "custom-profile-name" : "名称未設定テーマ 1", 39 | "base-settings" : "基本設定", 40 | "page-settings" : "ページ設定", 41 | "page" : { 42 | "title" : "タイトルバー背景色", 43 | "page" : "ページ背景色", 44 | "side" : "サイドバー背景色" 45 | }, 46 | "group-settings" : "グループ設定", 47 | "group" : { 48 | "text" : "グループ文字色", 49 | "border" : "グループボーダー色", 50 | "background" : "グループ背景色" 51 | }, 52 | "widget-settings" : "Widget設定", 53 | "widget" : { 54 | "text" : "Widget文字色", 55 | "colour" : "Widget色", 56 | "background" : "Widget背景色" 57 | } 58 | }, 59 | "style" : { 60 | "light" : "ライト (デフォルト)", 61 | "dark" : "ダーク", 62 | "custom" : "カスタム", 63 | "primary" : "プライマリ", 64 | "accents" : "アクセント", 65 | "background" : "背景", 66 | "warnings" : "警告", 67 | "palette": "ライト/ダーク" 68 | }, 69 | "base" : { 70 | "colour" : "色", 71 | "font" : "フォント" 72 | }, 73 | "font" : { 74 | "system" : "システムフォント (デフォルト)" 75 | }, 76 | "site" : { 77 | "title" : "Node-RED ダッシュボード", 78 | "date-format" : "YYYY/MM/DD" 79 | }, 80 | "title-bar" : { 81 | "show" : "タイトルバー表示", 82 | "hide" : "タイトルバー非表示" 83 | }, 84 | "swipe" : { 85 | "no-swipe" : "スワイプによるタブ切り替えをしない", 86 | "allow-swipe" : "スワイプによるタブ切り替えをする" 87 | }, 88 | "lock" : { 89 | "clicked" : "サイドメニューをクリックで表示", 90 | "locked" : "サイドメニューを表示したままにする", 91 | "locked-icon": "常にアイコンのみを表示" 92 | }, 93 | "temp" : { 94 | "no-theme" : "ui_templateでテーマ設定を許可しない", 95 | "allow-theme" : "ui_templateでテーマ設定を許可する", 96 | "none" : "Angularテーマを全ての箇所で使用" 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_chart.html: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_chart.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_chart": { 3 | "label": { 4 | "group": "グループ", 5 | "size": "サイズ", 6 | "label": "ラベル", 7 | "optionalChartTitle": "任意のグラフタイトル", 8 | "type": "種類", 9 | "lineChart": "  折れ線グラフ", 10 | "barChart": "  棒グラフ", 11 | "barChartH": "  棒グラフ(横)", 12 | "pieChart": "  円グラフ", 13 | "polarAreaChart": "  鶏頭図", 14 | "radarChart": "  レーダーチャート", 15 | "enlargePoints": "ポイントを表示", 16 | "xAxis": "X軸", 17 | "last": "直近", 18 | "seconds": "秒", 19 | "minutes": "分", 20 | "hours": "時間", 21 | "days": "日", 22 | "weeks": "週", 23 | "or": "又は", 24 | "points": "ポイント", 25 | "xAxisLabel": "X軸ラベル", 26 | "HHmmss": "HH:mm:ss", 27 | "HHmm": "HH:mm", 28 | "yearMonthDate": "年-月-日", 29 | "dateMonth": "日/月", 30 | "dayHHmm": "曜日 HH:mm", 31 | "custom": "カスタム", 32 | "automatic": "自動", 33 | "asUTC": "UTCを使用", 34 | "yAxis": "Y軸", 35 | "min": "最小", 36 | "max": "最大", 37 | "legend": "凡例", 38 | "none": "非表示", 39 | "show": "表示", 40 | "interpolate": "補完", 41 | "linear": "直線", 42 | "step": "段階", 43 | "bezier": "ベジェ", 44 | "cubic": "3次補間", 45 | "cubicMono": "単調3次補間", 46 | "cutout": "中心の切抜き率", 47 | "useFirstColourForAllBars": "最初の色を全グラフで使用", 48 | "seriesColours": "配色", 49 | "blankLabel": "初期ラベル", 50 | "displayThisTextBeforeValidDataArrives": "有効なデータが届く前に本文字列を表示", 51 | "useDifferentColor": "シリーズに別の色を使用", 52 | "className": "種類", 53 | "classNamePlaceholder": "ウィジェット用のCSSクラス名(オプション)" 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_form.html: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_form.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_form": { 3 | "label": { 4 | "group": "グループ", 5 | "size": "サイズ", 6 | "label": "ラベル", 7 | "optionalLabel": "任意のラベル", 8 | "formElements": "フォームの要素", 9 | "type": "種類", 10 | "required": "必須", 11 | "rows": "行数", 12 | "remove": "削除", 13 | "egName": "例) 名前", 14 | "egName2": "例) name", 15 | "text": "文字列", 16 | "multiline": "複数行", 17 | "number": "数値", 18 | "email": "E-メール", 19 | "password": "パスワード", 20 | "checkbox": "チェックボックス", 21 | "switch": "スイッチ", 22 | "date": "日付", 23 | "time": "時間", 24 | "element": "要素", 25 | "buttons": "ボタン", 26 | "submitButtonText": "送信ボタンの文字列", 27 | "cancelButtonText": "キャンセルボタンの文字列", 28 | "topic": "トピック", 29 | "optionalMsgTopic": "任意のmsg.topic", 30 | "splitLayout": "フォーム要素を2列に配置", 31 | "className": "種類", 32 | "classNamePlaceholder": "ウィジェット用のCSSクラス名(オプション)" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_group.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_group" : { 3 | "label" : { 4 | "name" : "名前", 5 | "tab" : "タブ", 6 | "width" : "幅", 7 | "default" : "デフォルト", 8 | "group" : "グループ", 9 | "unassigned" : "未設定", 10 | "className": "種類", 11 | "classNamePlaceholder": "ウィジェット用のCSSクラス名(オプション)" 12 | }, 13 | "display-name" : "グループ名を表示する", 14 | "collapse-name" : "グループの折りたたみを有効にする" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_link.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_link" : { 3 | "label" : { 4 | "name" : "名前", 5 | "link" : "リンク", 6 | "icon" : "アイコン", 7 | "open-in" : "開く方法", 8 | "new-tab" : "新規タブ", 9 | "this-tab" : "このタブ", 10 | "iframe" : "iframe", 11 | "className": "種類", 12 | "classNamePlaceholder": "ウィジェット用のCSSクラス名(オプション)" 13 | }, 14 | "tip" : "アイコンフィールドには Material Design icon (例: 'check', 'close')Font Awesome icon (例: 'fa-fire')、もしくは Weather icon (例: 'wi-wu-sunny')を指定できます。

" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_tab.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_tab" : { 3 | "label" : { 4 | "home" : "ホーム", 5 | "tab" : "タブ", 6 | "name" : "名前", 7 | "icon" : "アイコン", 8 | "state" : "状態", 9 | "navmenu" : "メニュー", 10 | "enabled" : "有効", 11 | "disabled" : "無効", 12 | "visible" : "表示", 13 | "hidden" : "非表示" 14 | }, 15 | "info": { 16 | "disabled": " タブを無効化します", 17 | "hidden": " タブを移動メニューに表示しません" 18 | }, 19 | "tip" : "アイコンフィールドには Material Design icon (例: 'check', 'close')Font Awesome icon (例: 'fa-fire')、もしくは Weather icon (例: 'wi-wu-sunny')を指定できます。

" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_template.html: -------------------------------------------------------------------------------- 1 | 45 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_template" : { 3 | "label" : { 4 | "type" : "コード種別", 5 | "local" : "グループ内のWidget", 6 | "global" : "ヘッドセクションへ追加", 7 | "group" : "グループ", 8 | "size" : "サイズ", 9 | "name" : "名前", 10 | "pass-through" : "入力メッセージをそのまま渡す", 11 | "store-state" : "出力メッセージを状態として保存", 12 | "template" : "HTMLコード", 13 | "expand": "展開する", 14 | "resend": "更新時に最後の値を再度読み込む", 15 | "className": "種類", 16 | "classNamePlaceholder": "ウィジェット用のCSSクラス名(オプション)" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_ui_control.html: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /nodes/locales/ja/ui_ui_control.json: -------------------------------------------------------------------------------- 1 | { 2 | "ui_ui_control" : { 3 | "label" : { 4 | "name" : "名前", 5 | "output": "出力" 6 | }, 7 | "placeholder" : { 8 | "name" : "名前" 9 | }, 10 | "events": { 11 | "all": "connect, lost, タブ変更もしくはグループイベント", 12 | "change": "タブ変更もしくはグループイベントのみ", 13 | "connect": "Connectイベントのみ" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodes/ui_audio.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 50 | 51 | 70 | -------------------------------------------------------------------------------- /nodes/ui_audio.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function uiAudioNode(config) { 5 | RED.nodes.createNode(this,config); 6 | this.voice = config.voice; 7 | this.group = config.group; 8 | this.always = config.always || false; 9 | if (this.group && RED.nodes.getNode(this.group).hasOwnProperty("config")) { 10 | this.tabname = RED.nodes.getNode(RED.nodes.getNode(this.group).config.tab).name; 11 | } 12 | var node = this; 13 | node.status({}); 14 | 15 | this.on('input', function(msg) { 16 | if (msg.hasOwnProperty("level") && (isNaN(msg.level) || msg.level > 300 || msg.level < 0)) { 17 | delete msg.level; 18 | } 19 | if (msg.reset == true) { 20 | ui.emitSocket('ui-audio', { reset:true, tabname:node.tabname, always:node.always, socketid:msg.socketid }); 21 | } 22 | else if (Buffer.isBuffer(msg.payload)) { 23 | ui.emitSocket('ui-audio', { audio:msg.payload, tabname:node.tabname, always:node.always, vol:msg.level, socketid:msg.socketid }); 24 | } 25 | else if (typeof msg.payload === "string") { 26 | ui.emitSocket('ui-audio', { tts:msg.payload, voice:(node.voice || msg.voice || 0), tabname:node.tabname, always:node.always, vol:msg.level, socketid:msg.socketid }); 27 | } 28 | }); 29 | 30 | var updateStatus = function(audioStatus) { 31 | if (audioStatus === "complete") { 32 | // When the audio or speech has played completely, clear the node status 33 | node.status({}); 34 | } 35 | else if (audioStatus.indexOf("error") === 0) { 36 | node.status({shape:"ring",fill:"red",text:audioStatus}); 37 | } 38 | else { 39 | node.status({shape:"dot",fill:"blue",text:audioStatus}); 40 | } 41 | }; 42 | ui.ev.on('audiostatus', updateStatus); 43 | 44 | this.on('close', function() { 45 | ui.ev.removeListener('audiostatus', updateStatus); 46 | }) 47 | } 48 | RED.nodes.registerType("ui_audio", uiAudioNode); 49 | } 50 | -------------------------------------------------------------------------------- /nodes/ui_button.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function ButtonNode(config) { 5 | RED.nodes.createNode(this, config); 6 | var node = this; 7 | 8 | var group = RED.nodes.getNode(config.group); 9 | if (!group) { return; } 10 | var tab = RED.nodes.getNode(group.config.tab); 11 | if (!tab) { return; } 12 | 13 | var payloadType = config.payloadType; 14 | var payload = config.payload; 15 | 16 | if (payloadType === 'flow' || payloadType === 'global') { 17 | try { 18 | var parts = RED.util.normalisePropertyExpression(payload); 19 | if (parts.length === 0) { 20 | throw new Error(); 21 | } 22 | } 23 | catch(err) { 24 | node.warn("Invalid payload property expression - defaulting to node id") 25 | payload = node.id; 26 | payloadType = 'str'; 27 | } 28 | } 29 | else { 30 | payload = payload || node.id; 31 | } 32 | 33 | node.on("input", function(msg) { 34 | try { 35 | node.topi = RED.util.evaluateNodeProperty(config.topic,config.topicType || "str",node,msg); 36 | } 37 | catch(e) { } 38 | }); 39 | 40 | var done = ui.add({ 41 | node: node, 42 | tab: tab, 43 | group: group, 44 | emitOnlyNewValues: false, 45 | forwardInputMessages: config.passthru || false, 46 | storeFrontEndInputAsState: false, 47 | control: { 48 | type: 'button', 49 | label: config.label, 50 | tooltip: config.tooltip, 51 | color: config.color, 52 | bgcolor: config.bgcolor, 53 | className: config.className, 54 | icon: config.icon, 55 | order: config.order, 56 | value: payload, 57 | format: config.bgcolor, 58 | width: config.width || group.config.width || 3, 59 | height: config.height || 1 60 | }, 61 | beforeSend: function (msg,m2) { 62 | var t = undefined; 63 | try { 64 | t = RED.util.evaluateNodeProperty(config.topic,config.topicType || "str",node,msg) 65 | } 66 | catch(e) { } 67 | if (typeof t === "undefined") { t = node.topi; } 68 | if (t !== undefined) { msg.topic = t; } 69 | if (((config.topicType || "str") === "str") && t == "") { delete msg.topic; } 70 | if (m2 !== undefined) { msg.event = m2.event; } 71 | }, 72 | convertBack: function (value) { 73 | if (payloadType === "date") { 74 | value = Date.now(); 75 | } 76 | else { 77 | try { 78 | value = RED.util.evaluateNodeProperty(payload,payloadType,node); 79 | } 80 | catch(e) { 81 | if (payloadType === "bin") { node.error("Badly formatted buffer"); } 82 | else { node.error(e,payload); } 83 | } 84 | } 85 | return value; 86 | } 87 | }); 88 | node.on("close", done); 89 | } 90 | RED.nodes.registerType("ui_button", ButtonNode); 91 | }; 92 | -------------------------------------------------------------------------------- /nodes/ui_colour_picker.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | var tc = require('../dist/js/tinycolor-min'); 4 | 5 | function ColourPickerNode(config) { 6 | RED.nodes.createNode(this, config); 7 | this.format = config.format; 8 | this.outformat = config.outformat; 9 | var node = this; 10 | 11 | var group = RED.nodes.getNode(config.group); 12 | if (!group) { return; } 13 | var tab = RED.nodes.getNode(group.config.tab); 14 | if (!tab) { return; } 15 | 16 | node.on("input", function(msg) { 17 | node.topi = msg.topic; 18 | }); 19 | 20 | var done = ui.add({ 21 | node: node, 22 | tab: tab, 23 | group: group, 24 | forwardInputMessages: config.passthru, 25 | control: { 26 | type: 'colour-picker', 27 | label: config.label, 28 | format: config.format, 29 | showPicker: config.showPicker, 30 | showSwatch: config.showSwatch, 31 | showValue: config.showValue, 32 | showHue: config.showHue, 33 | showAlpha: config.showAlpha, 34 | showLightness: config.showLightness, 35 | square: (config.square == 'true') || false, 36 | dynOutput: config.dynOutput, 37 | allowEmpty: true, 38 | order: config.order, 39 | value: '', 40 | width: config.width || group.config.width || 6, 41 | height: config.height || 1, 42 | className: config.className || '', 43 | }, 44 | beforeSend: function (msg) { 45 | if (node.outformat === 'object') { 46 | var pay = tc(msg.payload); 47 | if (node.format === 'rgb') { msg.payload = pay.toRgb(); } 48 | if (node.format === 'hsl') { msg.payload = pay.toHsl(); } 49 | if (node.format === 'hsv') { msg.payload = pay.toHsv(); } 50 | } 51 | var t = undefined; 52 | try { 53 | t = RED.util.evaluateNodeProperty(config.topic,config.topicType || "str",node,msg) || node.topi; 54 | } 55 | catch(e) { } 56 | if (t !== undefined) { msg.topic = t; } 57 | }, 58 | convert: function(p,o,m) { 59 | if (m.payload === undefined || m.payload === null) { return; } 60 | var colour = tc(m.payload); 61 | return colour.toString(config.format); 62 | } 63 | }); 64 | node.on("close", done); 65 | } 66 | RED.nodes.registerType("ui_colour_picker", ColourPickerNode); 67 | }; 68 | -------------------------------------------------------------------------------- /nodes/ui_date_picker.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function DatePickerNode(config) { 5 | RED.nodes.createNode(this, config); 6 | var node = this; 7 | 8 | var group = RED.nodes.getNode(config.group); 9 | if (!group) { return; } 10 | var tab = RED.nodes.getNode(group.config.tab); 11 | if (!tab) { return; } 12 | 13 | node.on("input", function(msg) { 14 | node.topi = msg.topic; 15 | }); 16 | 17 | var done = ui.add({ 18 | node: node, 19 | tab: tab, 20 | group: group, 21 | forwardInputMessages: config.passthru, 22 | emitOnlyNewValues: false, 23 | control: { 24 | type: 'date-picker', 25 | label: config.label, 26 | order: config.order, 27 | ddd : new Date().setUTCHours(0,0,0,0), 28 | width: config.width || group.config.width || 6, 29 | height: config.height || 1, 30 | className: config.className || '', 31 | }, 32 | convert: function (p,o,m) { 33 | var d = new Date(m.payload); 34 | this.control.ddd = d; 35 | return m.payload; 36 | }, 37 | beforeEmit: function (msg, value) { 38 | if (value === undefined) { return; } 39 | value = new Date(value); 40 | return { msg:msg, value:value }; 41 | }, 42 | convertBack: function (value) { 43 | var d = new Date(value).valueOf(); 44 | return d; 45 | }, 46 | beforeSend: function (msg) { 47 | var t = RED.util.evaluateNodeProperty(config.topic,config.topicType || "str",node,msg) || node.topi; 48 | if (t !== undefined) { msg.topic = t; } 49 | } 50 | }); 51 | node.on("close", done); 52 | } 53 | RED.nodes.registerType("ui_date_picker", DatePickerNode); 54 | }; 55 | -------------------------------------------------------------------------------- /nodes/ui_form.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function FormNode(config) { 5 | RED.nodes.createNode(this, config); 6 | var node = this; 7 | var group = RED.nodes.getNode(config.group); 8 | if (!group) { return; } 9 | var tab = RED.nodes.getNode(group.config.tab); 10 | if (!tab) { return; } 11 | 12 | node.on("input", function(msg) { 13 | node.topi = msg.topic; 14 | }); 15 | 16 | var done = ui.add({ 17 | node: node, 18 | tab: tab, 19 | group: group, 20 | forwardInputMessages: false, 21 | storeFrontEndInputAsState: false, 22 | control: { 23 | type: 'form', 24 | label: config.label, 25 | order: config.order, 26 | value: config.payload || node.id, 27 | width: config.width || group.config.width || 6, 28 | height: config.height || config.splitLayout == true ? Math.ceil(config.options.length/2) : config.options.length, 29 | options: config.options, 30 | formValue: config.formValue, 31 | submit: config.submit, 32 | cancel: config.cancel, 33 | splitLayout: config.splitLayout || false, 34 | sy: ui.getSizes().sy, 35 | cy: ui.getSizes().cy, 36 | className: config.className || '', 37 | }, 38 | beforeSend: function (msg) { 39 | var t = undefined; 40 | try { 41 | t = RED.util.evaluateNodeProperty(config.topic,config.topicType || "str",node,msg) || node.topi; 42 | } 43 | catch(e) { } 44 | if (t !== undefined) { msg.topic = t; } 45 | } 46 | }); 47 | node.on("close", done); 48 | } 49 | RED.nodes.registerType("ui_form", FormNode); 50 | }; 51 | -------------------------------------------------------------------------------- /nodes/ui_group.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | 3 | function GroupNode(config) { 4 | RED.nodes.createNode(this, config); 5 | this.config = { 6 | name: config.name, 7 | disp: config.disp, 8 | width: config.width, 9 | order: config.order, 10 | tab: config.tab, 11 | collapse: config.collapse || false, 12 | className: config.className || '' 13 | }; 14 | if (!this.config.hasOwnProperty("disp")) { this.config.disp = true; } 15 | if (this.config.disp !== false) { this.config.disp = true; } 16 | if (!this.config.hasOwnProperty("collapse")) { this.config.collapse = false; } 17 | } 18 | 19 | RED.nodes.registerType("ui_group", GroupNode); 20 | }; 21 | -------------------------------------------------------------------------------- /nodes/ui_link.html: -------------------------------------------------------------------------------- 1 | 37 | 38 | 66 | -------------------------------------------------------------------------------- /nodes/ui_link.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function LinkNode(config) { 5 | RED.nodes.createNode(this, config); 6 | var node = this; 7 | var done = ui.addLink(config.name, config.link, config.icon, config.order, config.target, config.className); 8 | node.on("close", done); 9 | } 10 | 11 | RED.nodes.registerType("ui_link", LinkNode); 12 | }; 13 | -------------------------------------------------------------------------------- /nodes/ui_numeric.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function NumericNode(config) { 5 | RED.nodes.createNode(this, config); 6 | this.pt = config.passthru; 7 | this.state = [" "," "]; 8 | var node = this; 9 | node.status({}); 10 | 11 | var group = RED.nodes.getNode(config.group); 12 | if (!group) { return; } 13 | var tab = RED.nodes.getNode(group.config.tab); 14 | if (!tab) { return; } 15 | 16 | node.on("input", function(msg) { 17 | node.topi = msg.topic; 18 | }); 19 | 20 | var done = ui.add({ 21 | node: node, 22 | tab: tab, 23 | group: group, 24 | forwardInputMessages: config.passthru, 25 | control: { 26 | type: 'numeric', 27 | label: config.label, 28 | tooltip: config.tooltip, 29 | order: config.order, 30 | format: config.format, 31 | pre: config.format.split('{{')[0] || "", 32 | post: config.format.split('}}')[1] || "", 33 | value: Number(config.min), 34 | min: Number(config.min), 35 | max: Number(config.max), 36 | step: Number(config.step || 1), 37 | wrap: config.wrap || false, 38 | width: config.width || group.config.width || 6, 39 | height: config.height || 1, 40 | ed: (config.format.includes("value") ? false : true), 41 | className: config.className || '', 42 | }, 43 | beforeSend: function (msg) { 44 | msg.payload = parseFloat(msg.payload); 45 | var t = undefined; 46 | try { 47 | t = RED.util.evaluateNodeProperty(config.topic,config.topicType || "str",node,msg) || node.topi; 48 | } 49 | catch(e) { } 50 | if (t !== undefined) { msg.topic = t; } 51 | if (node.pt) { 52 | node.status({shape:"dot",fill:"grey",text:msg.payload}); 53 | } 54 | else { 55 | node.state[1] = msg.payload; 56 | node.status({shape:"dot",fill:"grey",text:node.state[1] + " | " + node.state[1]}); 57 | } 58 | }, 59 | convert: ui.toFloat.bind(this, config) 60 | }); 61 | if (!node.pt) { 62 | node.on("input", function(msg) { 63 | node.state[0] = msg.payload; 64 | node.status({shape:"dot",fill:"grey",text:node.state[0] + " | " + node.state[1]}); 65 | }); 66 | } 67 | node.on("close", done); 68 | } 69 | RED.nodes.registerType("ui_numeric", NumericNode); 70 | }; 71 | -------------------------------------------------------------------------------- /nodes/ui_slider.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function SliderNode(config) { 5 | RED.nodes.createNode(this, config); 6 | this.pt = config.passthru; 7 | this.state = [" "," "]; 8 | var node = this; 9 | node.status({}); 10 | 11 | var group = RED.nodes.getNode(config.group); 12 | if (!group) { return; } 13 | var tab = RED.nodes.getNode(group.config.tab); 14 | if (!tab) { return; } 15 | 16 | node.on("input", function(msg) { 17 | node.topi = msg.topic; 18 | }); 19 | 20 | var done = ui.add({ 21 | node: node, 22 | tab: tab, 23 | group: group, 24 | forwardInputMessages: config.passthru, 25 | control: { 26 | type: 'slider', 27 | label: config.label, 28 | tooltip: config.tooltip, 29 | order: config.order, 30 | value: config.min, 31 | min: Math.min(config.min, config.max), 32 | max: Math.max(config.max, config.min), 33 | invert: (parseFloat(config.min) > parseFloat(config.max)) ? true : undefined, 34 | step: Math.abs(config.step) || 1, 35 | outs: config.outs || "all", 36 | width: config.width || group.config.width || 6, 37 | height: config.height || 1, 38 | className: config.className || '', 39 | }, 40 | beforeSend: function (msg) { 41 | var t = undefined; 42 | try { 43 | t = RED.util.evaluateNodeProperty(config.topic,config.topicType || "str",node,msg) || node.topi; 44 | } 45 | catch(e) { } 46 | if (t !== undefined) { msg.topic = t; } 47 | if (node.pt) { 48 | node.status({shape:"dot",fill:"grey",text:msg.payload}); 49 | } 50 | else { 51 | node.state[1] = msg.payload; 52 | node.status({shape:"dot",fill:"grey",text:node.state[1] + " | " + node.state[1]}); 53 | } 54 | }, 55 | convert: ui.toFloat.bind(this, config) 56 | }); 57 | if (!node.pt) { 58 | node.on("input", function(msg) { 59 | node.state[0] = msg.payload; 60 | node.status({shape:"dot",fill:"grey",text:node.state[0] + " | " + node.state[1]}); 61 | }); 62 | } 63 | else if (node._wireCount === 0) { 64 | node.on("input", function(msg) { 65 | node.status({shape:"dot",fill:"grey",text:msg.payload}); 66 | }); 67 | } 68 | node.on("close", done); 69 | } 70 | RED.nodes.registerType("ui_slider", SliderNode); 71 | }; 72 | -------------------------------------------------------------------------------- /nodes/ui_spacer.html: -------------------------------------------------------------------------------- 1 | 42 | 43 | 59 | -------------------------------------------------------------------------------- /nodes/ui_spacer.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function SpacerNode(config) { 5 | RED.nodes.createNode(this, config); 6 | var node = this; 7 | 8 | var group = RED.nodes.getNode(config.group); 9 | if (!group) { return; } 10 | var tab = RED.nodes.getNode(group.config.tab); 11 | if (!tab) { return; } 12 | 13 | var done = ui.add({ 14 | node: node, 15 | tab: tab, 16 | group: group, 17 | control: { 18 | type: 'spacer', 19 | order: config.order, 20 | width: config.width || group.config.width || 6, 21 | height: config.height || 1, 22 | className: config.className || '' 23 | } 24 | }); 25 | node.on("close", done); 26 | } 27 | RED.nodes.registerType("ui_spacer", SpacerNode); 28 | }; 29 | -------------------------------------------------------------------------------- /nodes/ui_tab.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | 3 | function TabNode(config) { 4 | RED.nodes.createNode(this, config); 5 | this.config = { 6 | name: config.name, 7 | order: config.order || 0, 8 | icon: config.icon || '', 9 | disabled: config.disabled || false, 10 | hidden: config.hidden || false 11 | }; 12 | } 13 | 14 | RED.nodes.registerType("ui_tab", TabNode); 15 | }; 16 | -------------------------------------------------------------------------------- /nodes/ui_template.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function TemplateNode(config) { 5 | RED.nodes.createNode(this, config); 6 | var node = this; 7 | 8 | var group = RED.nodes.getNode(config.group); 9 | if (!group && config.templateScope !== 'global') { return; } 10 | var tab = null; 11 | if (config.templateScope !== 'global') { 12 | tab = RED.nodes.getNode(group.config.tab); 13 | if (!tab) { return; } 14 | if (!config.width) { 15 | config.width = group.config.width; 16 | } 17 | } 18 | var hei = Number(config.height|| 0); 19 | var previousTemplate = null 20 | var theme = ui.getTheme(); 21 | var colortheme = {}; 22 | for (var i in theme) { 23 | if (theme.hasOwnProperty(i)) { 24 | colortheme[i.replace(/-/g, "_")] = theme[i].value; 25 | } 26 | } 27 | 28 | var done = ui.add({ 29 | forwardInputMessages: config.fwdInMessages, 30 | storeFrontEndInputAsState: config.storeOutMessages, 31 | persistantFrontEndValue: config.resendOnRefresh, 32 | emitOnlyNewValues: false, 33 | node: node, 34 | tab: tab, 35 | group: group, 36 | control: { 37 | type: 'template', 38 | order: config.order, 39 | width: config.width || 6, 40 | height: hei, 41 | format: config.format, 42 | templateScope: config.templateScope, 43 | theme: colortheme, 44 | className: config.className || '', 45 | }, 46 | beforeEmit: function(msg) { 47 | var properties = Object.getOwnPropertyNames(msg).filter(function (p) { return p[0] != '_'; }); 48 | var clonedMsg = { 49 | templateScope: config.templateScope 50 | }; 51 | for (var i=0; i 0)) { 7 | try { this.displayTime = parseFloat(config.displayTime) * 1000; } 8 | catch(e) { this.displayTime = 3000; } 9 | } 10 | this.position = config.position || "top right"; 11 | this.highlight = config.highlight; 12 | this.ok = config.ok; 13 | this.cancel = config.cancel; 14 | this.className = config.className; 15 | this.topic = config.topic; 16 | if (config.sendall === undefined) { this.sendall = true; } 17 | else { this.sendall = config.sendall; } 18 | this.raw = config.raw || false; 19 | var node = this; 20 | 21 | // var noscript = function (content) { 22 | // if (typeof content === "object") { return null; } 23 | // content = '' + content; 24 | // content = content.replace(/<.*cript.*/ig, ''); 25 | // content = content.replace(/.on\w+=.*".*"/g, ''); 26 | // content = content.replace(/.on\w+=.*\'.*\'/g, ''); 27 | // return content; 28 | // } 29 | 30 | var done = ui.add({ 31 | node: node, 32 | control: {}, 33 | storeFrontEndInputAsState: false, 34 | forwardInputMessages: false, 35 | beforeSend: function (msg) { 36 | var m = msg.payload.msg; 37 | m.topic = node.topic || m.topic; 38 | return m; 39 | } 40 | }); 41 | 42 | node.on('input', function(msg) { 43 | if (node.sendall === true) { delete msg.socketid; } 44 | var dt = node.displayTime || msg.timeout * 1000 || 3000; 45 | if (dt <= 0) { dt = 1; } 46 | //msg.payload = noscript(msg.payload); 47 | ui.emitSocket('show-toast', { 48 | title: node.topic || msg.topic, 49 | toastClass: node.className || msg.className, 50 | message: msg.payload, 51 | highlight: node.highlight || msg.highlight, 52 | displayTime: dt, 53 | position: node.position, 54 | id: node.id, 55 | dialog: (node.position === "dialog" || node.position === "prompt") || false, 56 | prompt: (node.position === "prompt") || false, 57 | ok: node.ok, 58 | cancel: node.cancel, 59 | socketid: msg.socketid, 60 | raw: node.raw, 61 | msg: msg 62 | }); 63 | }); 64 | 65 | node.on("close", done); 66 | } 67 | RED.nodes.registerType("ui_toast", ToastNode); 68 | }; 69 | -------------------------------------------------------------------------------- /nodes/ui_ui_control.html: -------------------------------------------------------------------------------- 1 | 35 | 36 | 47 | -------------------------------------------------------------------------------- /nodes/ui_ui_control.js: -------------------------------------------------------------------------------- 1 | module.exports = function(RED) { 2 | var ui = require('../ui')(RED); 3 | 4 | function UiControlNode(config) { 5 | RED.nodes.createNode(this, config); 6 | this.events = config.events || "all"; 7 | var node = this; 8 | 9 | this.on('input', function(msg) { 10 | if (typeof msg.payload !== "object") { msg.payload = {tab:msg.payload}; } 11 | // show/hide or enable/disable tabs 12 | if (msg.payload.hasOwnProperty("tabs")) { 13 | ui.emit('ui-control', {tabs:msg.payload.tabs, socketid:msg.socketid}); 14 | } 15 | // switch to tab name (or number) 16 | if (msg.payload.hasOwnProperty("tab")) { 17 | ui.emit('ui-control', {tab:msg.payload.tab, socketid:msg.socketid}); 18 | } 19 | // show or hide ui groups 20 | if (msg.payload.hasOwnProperty("group")) { 21 | ui.emit('ui-control', {group:msg.payload.group, socketid:msg.socketid}); 22 | } 23 | }); 24 | 25 | var sendconnect = function(id, ip) { 26 | node.send({payload:"connect", socketid:id, socketip:ip}); 27 | }; 28 | 29 | var sendlost = function(id, ip) { 30 | node.send({payload:"lost", socketid:id, socketip:ip}); 31 | }; 32 | 33 | var sendchange = function(index, name, id, ip, p) { 34 | node.send({payload:"change", tab:index, name:name, socketid:id, socketip:ip, params:p}); 35 | } 36 | 37 | var sendcollapse = function(group, state, id, ip) { 38 | node.send({payload:"group", group:group, open:state, socketid:id, socketip:ip,}); 39 | } 40 | 41 | if (node.events === "connect") { 42 | ui.ev.on('newsocket', sendconnect); 43 | } 44 | else if (node.events === "change") { 45 | ui.ev.on('changetab', sendchange); 46 | ui.ev.on('collapse', sendcollapse); 47 | } 48 | else { 49 | ui.ev.on('newsocket', sendconnect); 50 | ui.ev.on('changetab', sendchange); 51 | ui.ev.on('collapse', sendcollapse); 52 | ui.ev.on('endsocket', sendlost); 53 | } 54 | 55 | this.on('close', function() { 56 | if (node.events === "connect") { 57 | ui.ev.removeListener('newsocket', sendconnect); 58 | } 59 | else if (node.events === "change") { 60 | ui.ev.removeListener('changetab', sendchange); 61 | ui.ev.removeListener('collapse', sendcollapse); 62 | } 63 | else { 64 | ui.ev.removeListener('newsocket', sendconnect); 65 | ui.ev.removeListener('changetab', sendchange); 66 | ui.ev.removeListener('collapse', sendcollapse); 67 | ui.ev.removeListener('endsocket', sendlost); 68 | } 69 | }) 70 | } 71 | RED.nodes.registerType("ui_ui_control", UiControlNode); 72 | }; 73 | -------------------------------------------------------------------------------- /src/components/ui-card-panel/ui-card-panel.css: -------------------------------------------------------------------------------- 1 | .masonry-container { 2 | position: relative; 3 | width: 100%; 4 | margin: 0 auto; 5 | } 6 | 7 | .masonry-container > * { 8 | position: absolute; 9 | opacity: 0; 10 | } 11 | 12 | .masonry-container > .visible { 13 | opacity: 1; 14 | } 15 | 16 | .nr-dashboard-cardpanel { 17 | box-sizing: border-box; 18 | } 19 | 20 | .nr-dashboard-cardpanel > p { 21 | max-height: 32px; 22 | min-height: 32px; 23 | margin-left: 12px; 24 | margin-top: 10px; 25 | margin-bottom: 12px; 26 | font-weight: 500; 27 | font-size: larger; 28 | } 29 | 30 | .nr-dashboard-cardcarat:focus { 31 | outline: 0; 32 | } 33 | 34 | .nr-dashboard-cardcarat { 35 | float: right; 36 | vertical-align: baseline; 37 | margin-right: 12px; 38 | } 39 | 40 | .nr-dashboard-cardcontainer { 41 | position: relative; 42 | } 43 | 44 | .nr-dashboard-cardcontainer > * { 45 | margin: 0 !important; 46 | position: absolute; 47 | opacity: 0; 48 | } 49 | 50 | .nr-dashboard-cardcontainer > .visible { 51 | opacity: 1; 52 | } 53 | -------------------------------------------------------------------------------- /src/components/ui-card-panel/ui-card-panel.html: -------------------------------------------------------------------------------- 1 |
5 |

{{group.header.name}} 6 | 7 | 8 | 9 |

10 |
11 |
12 | -------------------------------------------------------------------------------- /src/components/ui-card-panel/ui-card-panel.js: -------------------------------------------------------------------------------- 1 | /* global angular $ */ 2 | 3 | angular.module('ui').directive('uiCardPanel', ['$timeout', '$rootScope', 4 | function($timeout, $rootScope) { 5 | return { 6 | restrict: 'E', 7 | transclude: true, 8 | templateUrl: 'components/ui-card-panel/ui-card-panel.html', 9 | controller: 'uiCardPanelController', 10 | controllerAs: 'ctrl', 11 | link: function (scope, element, attrs, controller) { 12 | scope.collapsed = ((((typeof localStorage !== 'undefined') && localStorage.getItem(attrs.id)) || false) == 'true'); 13 | var root = element.find(".nr-dashboard-cardcontainer"); 14 | var slideDuration = 0; 15 | controller.init(root); 16 | scope.collapseCard = function() { 17 | scope.collapsed = !scope.collapsed; 18 | if (typeof localStorage !== 'undefined') { localStorage.setItem(attrs.id,scope.collapsed); } 19 | root.slideToggle(slideDuration); 20 | $timeout(function() { $(window).trigger('resize'); }, slideDuration); 21 | slideDuration = parseInt(attrs.slideToggleDuration, 10) || 150; 22 | $rootScope.$emit("collapse", attrs.id, !scope.collapsed); 23 | } 24 | if (scope.collapsed === true) { 25 | scope.collapsed = false; 26 | $timeout(function() { 27 | element.find(".nr-dashboard-cardcarat").trigger('click'); 28 | },20); 29 | } 30 | } 31 | }; 32 | } 33 | ]); 34 | -------------------------------------------------------------------------------- /src/components/ui-card-panel/ui-card-size.js: -------------------------------------------------------------------------------- 1 | /* global angular */ 2 | angular.module('ui').directive('uiCardSize', ['uiSizes', 3 | function() { 4 | return { 5 | restrict: 'A', 6 | require: ['^uiCardPanel', '^?uiMasonry'], 7 | link: function(scope, element, attrs, ctrls) { 8 | attrs.$observe('uiCardSize', function () { 9 | ctrls[0].refreshLayout(function() { 10 | if (ctrls[1]) { ctrls[1].refreshLayout(); } 11 | }); 12 | }); 13 | } 14 | } 15 | } 16 | ]); 17 | -------------------------------------------------------------------------------- /src/components/ui-chart-js/ui-chart-js.html: -------------------------------------------------------------------------------- 1 |
2 | 11 | 12 | 21 | 22 | 31 | 32 | 41 | 42 | 51 | 52 | 61 | 62 |
63 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/button.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-button { 2 | background: none; 3 | } 4 | 5 | .nr-dashboard-button .md-button { 6 | box-shadow: none; 7 | width: 100%; 8 | height: 100%; 9 | margin: 0px; 10 | min-width: 0px; 11 | min-height: 0px; 12 | } 13 | 14 | md-card .nr-dashboard-button { 15 | padding: 2px; 16 | } 17 | 18 | .nr-dashboard-button i { 19 | vertical-align: middle; 20 | width: unset; 21 | } 22 | 23 | .nr-dashboard-button .fa-2x { 24 | vertical-align: middle; 25 | padding-bottom: 2px; 26 | } 27 | 28 | .nr-dashboard-button .fa-3x { 29 | vertical-align: middle; 30 | padding-bottom: 1px; 31 | } 32 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/button.html: -------------------------------------------------------------------------------- 1 | 7 | 13 | 17 | 18 | 19 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/chart.css: -------------------------------------------------------------------------------- 1 | p.nr-dashboard-chart-title { 2 | padding: 10px 10px 4px 10px; 3 | margin: 0px 0px 0px 0px; 4 | text-align: center; 5 | z-index: 1; 6 | min-height: 10px; 7 | } 8 | 9 | p.blank-label { 10 | color: #c3c3c3; 11 | left: 50%; 12 | top: 50%; 13 | -webkit-transform: translate(-50%, -50%); 14 | -moz-transform: translate(-50%, -50%); 15 | transform: translate(-50%, -50%); 16 | position: absolute; 17 | z-index: 2; 18 | } 19 | 20 | .nr-dashboard-chart-container { 21 | width: 100%; 22 | height: 100%; 23 | } 24 | 25 | canvas.chart.chart-line { 26 | /* full height - label_padding - label_height - nr-dashboard-chart_padding */ 27 | height: calc(100% + 22px) !important; 28 | width: calc(100%) !important; 29 | } 30 | 31 | .nr-dashboard-chart { 32 | /* full height - label_padding - label_height - nr-dashboard-chart_padding */ 33 | height: calc(100% - 55px); 34 | width: calc(100% - 10px); 35 | padding: 5px; 36 | } 37 | .nr-dashboard-chart-nolabel { 38 | /* full height - label_padding - nr-dashboard-chart_padding */ 39 | height: calc(100% - 40px); 40 | } 41 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/chart.html: -------------------------------------------------------------------------------- 1 | 6 |
7 |

10 |

11 | 16 | 17 |

{{ me.item.nodata }} 19 |

20 |
21 |
22 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/colour-picker.css: -------------------------------------------------------------------------------- 1 | /* 2 | overwrite the default md-errors-spacer min-height 3 | reason: https://github.com/angular/material/issues/6214 4 | */ 5 | 6 | .nr-dashboard-colour-picker p { 7 | padding: 0 0 0 12px; 8 | } 9 | 10 | .color-picker-wrapper { 11 | padding-right: 12px; 12 | } 13 | 14 | .color-picker-wrapper.color-picker-open { 15 | border-width:0; 16 | } 17 | 18 | .color-picker-wrapper.color-picker-swatch-only.color-picker-open { 19 | width: 32px; 20 | border-width: 0px; 21 | z-index:2; 22 | } 23 | 24 | /* color-picker { 25 | z-index:2; 26 | } */ 27 | 28 | .color-picker-wrapper.color-picker-swatch-only.color-picker-open .color-picker-panel.color-picker-panel-right.color-picker-show-inline { 29 | right: 121px; 30 | } 31 | .color-picker-wrapper.color-picker-swatch-only.color-picker-open .color-picker-panel.color-picker-panel-right.color-picker-show-inline.color-picker-show-lightness { 32 | right: 141px; 33 | } 34 | .color-picker-wrapper.color-picker-swatch-only.color-picker-open .color-picker-panel.color-picker-panel-right.color-picker-show-inline.color-picker-show-alpha { 35 | right: 141px; 36 | } 37 | .color-picker-wrapper.color-picker-swatch-only.color-picker-open .color-picker-panel.color-picker-panel-right.color-picker-show-inline.color-picker-show-hue { 38 | right: 141px; 39 | } 40 | .color-picker-wrapper.color-picker-swatch-only.color-picker-open .color-picker-panel.color-picker-panel-right.color-picker-show-inline.color-picker-show-hue.color-picker-show-alpha { 41 | right: 161px; 42 | } 43 | .color-picker-wrapper.color-picker-swatch-only.color-picker-open .color-picker-panel.color-picker-panel-right.color-picker-show-inline.color-picker-show-hue.color-picker-show-lightness { 44 | right: 161px; 45 | } 46 | .color-picker-wrapper.color-picker-swatch-only.color-picker-open .color-picker-panel.color-picker-panel-right.color-picker-show-inline.color-picker-show-alpha.color-picker-show-lightness { 47 | right: 161px; 48 | } 49 | .color-picker-wrapper.color-picker-swatch-only.color-picker-open .color-picker-panel.color-picker-panel-right.color-picker-show-inline.color-picker-show-hue.color-picker-show-alpha.color-picker-show-lightness { 50 | right: 181px; 51 | } 52 | 53 | .color-picker-wrapper .input-group .input-group-addon { 54 | padding: 12px 12px; 55 | border-width: 0px; 56 | } 57 | 58 | .color-picker-wrapper.color-picker-swatch-only .input-group .input-group-addon { 59 | width: 0px; 60 | } 61 | 62 | .color-picker-wrapper.color-picker-swatch-only .input-group .input-group-addon:last-child { 63 | border-left-width: 0px; 64 | } 65 | 66 | .color-picker-wrapper .input-group .input-group-addon:last-child { 67 | border-width: 0px; 68 | width: 1px; 69 | } 70 | 71 | .color-picker-wrapper .input-group .color-picker-input { 72 | position: relative; 73 | width: 122px; 74 | height: 20px; 75 | text-indent: 6px; 76 | text-align: center; 77 | font-size: smaller; 78 | padding-right: 4px; 79 | } 80 | 81 | .color-picker-input-wrapper.input-group > span{ 82 | border-radius: 3px; 83 | } 84 | 85 | .color-picker-wrapper .color-picker-swatch:not(.input-group-addon).color-picker-swatch-right { 86 | /* right: -1px; */ 87 | } 88 | 89 | .color-picker-input-wrapper { 90 | width: 100%; 91 | } 92 | 93 | .color-picker-input-wrapper > input { 94 | width: 164px; 95 | height: 22px; 96 | text-indent: 6px; 97 | font-size: smaller; 98 | border-width: 0px; 99 | } 100 | 101 | .color-picker-wrapper .color-picker-input-wrapper { 102 | display: flex; 103 | } 104 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/colour-picker.html: -------------------------------------------------------------------------------- 1 | 8 |

9 | 12 | 13 |

14 | 22 | 23 |
24 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/date-picker.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-date-picker { 2 | padding: 0 0px; 3 | width: 100%; 4 | margin-top: 8px; 5 | margin-right: 0px; 6 | } 7 | 8 | .nr-dashboard-date-picker-label { 9 | margin-left: 8px; 10 | } 11 | 12 | .md-button.md-icon-button { 13 | margin: 0 0px; 14 | } 15 | 16 | .md-icon-button+.md-datepicker-input-container { 17 | /* margin-left: 12px; */ 18 | } 19 | 20 | .md-icon-button+.md-datepicker-input-container { 21 | width: calc(100% - 55px); 22 | margin-left: 0px; 23 | } 24 | 25 | ._md-datepicker-floating-label>md-datepicker .md-datepicker-button { 26 | float: left; 27 | margin-top: -15px; 28 | } 29 | 30 | .nr-dashboard-date-picker .md-datepicker-triangle-button.md-button.md-icon-button { 31 | height: 40px; 32 | width: 40px; 33 | top: -5px; 34 | } 35 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/date-picker.html: -------------------------------------------------------------------------------- 1 | 9 | 10 |

13 |

14 | 20 | 21 |
22 |
23 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/dropdown.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-dropdown md-input-container { 2 | width: 100%; 3 | height: 90%; 4 | padding-left: 8px; 5 | padding-right: 4px; 6 | margin: 0px; 7 | margin-right: 4px; 8 | } 9 | 10 | .nr-dashboard-dropdown md-input-container>md-select { 11 | overflow: hidden; 12 | /* margin-left: 4px !important; */ 13 | margin-top: 6px; 14 | } 15 | 16 | .nr-dashboard-theme .nr-dashboard-dropdown md-select-value { 17 | min-width: 16px; 18 | } 19 | 20 | .nr-dashboard-theme .nr-dashboard-dropdown .md-select-value .md-select-icon { 21 | margin: 0px; 22 | width: 12px; 23 | } 24 | 25 | .nr-dashboard-dropdown .layout-row>.flex-100 { 26 | flex: 1 1 50%; 27 | max-width: 100%; 28 | max-height: 100%; 29 | box-sizing: border-box; 30 | } 31 | 32 | .nr-dashboard-dropdown p.label { 33 | margin: 0px; 34 | line-height: 34px; 35 | margin-right: 4px; 36 | margin-top: 3px; 37 | padding-right: 2px; 38 | white-space: normal; 39 | overflow: hidden; 40 | min-width: 20%; 41 | } 42 | 43 | .nr-dashboard-dropdown-header { 44 | padding-top: 6px; 45 | padding-left: 6px; 46 | padding-right: 8px; 47 | height: 34px; 48 | cursor: pointer; 49 | position: relative; 50 | display: flex; 51 | align-items: center; 52 | width: auto; 53 | } 54 | 55 | .nr-dashboard-dropdown-header input { 56 | padding-left: 8px; 57 | } 58 | 59 | .nr-dashboard-dropdown-header ng-md-icon { 60 | right: 0px; 61 | left: inherit; 62 | } 63 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/dropdown.html: -------------------------------------------------------------------------------- 1 | 8 | 9 |

13 |

14 | 19 | 20 | 27 | 30 | 34 | 40 | 41 | 42 | 43 | {{ opt.label }} 46 | 47 | 48 | 57 | 60 | 61 | 65 | 70 | 71 | 72 | 73 | {{ opt.label }} 76 | 77 | 78 |
79 |
80 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/form.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-form { 2 | display: inline-block; 3 | width: 100%; 4 | overflow-y: auto; 5 | } 6 | .nr-dashboard-form form { 7 | padding: 0px 6px 0px 6px; 8 | display: flex; 9 | flex-direction: row; 10 | flex-wrap: wrap; 11 | justify-content: flex-start; 12 | } 13 | 14 | .nr-dashboard-form .formlabel { 15 | font-size: large; 16 | font-weight: 500; 17 | margin-top: 12px; 18 | margin-bottom: 6px; 19 | padding: 0 6px; 20 | width: 100%; 21 | } 22 | .nr-dashboard-form .formElement { 23 | width: calc(100% - 12px); 24 | margin-left: 6px; 25 | margin-right: 6px 26 | } 27 | .nr-dashboard-form .formElementSplit { 28 | width: calc(50% - 12px); 29 | margin-left: 6px; 30 | margin-right: 6px 31 | } 32 | .nr-dashboard-form .form-control { 33 | width: 100%; 34 | display: flex; 35 | justify-content:flex-start; 36 | margin-top:-20px; 37 | } 38 | .nr-dashboard-form .form-control-single { 39 | justify-content:space-around; 40 | } 41 | .nr-dashboard-form .form-control-single > .nr-dashboard-form-button { 42 | width:100% 43 | } 44 | .nr-dashboard-form .form-control-no-label { 45 | margin-top:-10px; 46 | } 47 | .nr-dashboard-form md-input-container { 48 | display: inline-block; 49 | margin-top: 0px; 50 | margin-bottom: 0px; 51 | padding-top: 1px; 52 | padding-bottom: 1px; 53 | } 54 | 55 | md-input-container label:not(.md-container-ignore) { 56 | position: absolute; 57 | bottom: 94%; 58 | left: 0; 59 | right: auto; 60 | } 61 | 62 | .nr-dashboard-form form md-input-container input { 63 | margin-top: 2px; 64 | } 65 | 66 | .nr-dashboard-form md-input-container.md-input-focused label:not(.md-no-float), md-input-container.md-input-has-placeholder label:not(.md-no-float), md-input-container.md-input-has-value label:not(.md-no-float) { 67 | -webkit-transform: translate3d(0,10px,0) scale(.75); 68 | transform: translate3d(0,10px,0) scale(.75); 69 | -webkit-transition: width .4s cubic-bezier(.25,.8,.25,1),-webkit-transform .4s cubic-bezier(.25,.8,.25,1); 70 | transition: width .4s cubic-bezier(.25,.8,.25,1),-webkit-transform .4s cubic-bezier(.25,.8,.25,1); 71 | transition: transform .4s cubic-bezier(.25,.8,.25,1),width .4s cubic-bezier(.25,.8,.25,1); 72 | transition: transform .4s cubic-bezier(.25,.8,.25,1),width .4s cubic-bezier(.25,.8,.25,1),-webkit-transform .4s cubic-bezier(.25,.8,.25,1); 73 | } 74 | .nr-dashboard-form md-datepicker { 75 | padding-bottom: 10px; 76 | } 77 | .nr-dashboard-form md-switch { 78 | margin-top: 0px; 79 | margin-bottom: 0px; 80 | } 81 | .nr-dashboard-form input[type="checkbox"] { 82 | margin-top: 0px; 83 | margin-bottom: 0px; 84 | } 85 | .nr-dashboard-form md-input-container .md-errors-spacer { 86 | float: right; 87 | min-height: 0px; 88 | min-width: 1px; 89 | } 90 | .nr-dashboard-form-button { 91 | width: 50%; 92 | margin-bottom: 0px; 93 | margin-top: 0px; 94 | min-height: 28px; 95 | } 96 | .nr-dashboard-form form md-input-container md-checkbox .md-label { 97 | position: unset; 98 | top: unset; 99 | } 100 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/form.html: -------------------------------------------------------------------------------- 1 | 8 |
9 |

10 |
11 | 12 | 13 | 17 | 22 | 27 | 32 | 37 | {{opt.label}} 38 | {{opt.label}} 39 | 40 | 41 |
42 |
43 | {{me.item.submit}} 44 | {{me.item.cancel}} 45 |
46 |
47 |
48 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/gauge.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-gauge text { 2 | /* font-weight: 500;*/ 3 | } 4 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/gauge.html: -------------------------------------------------------------------------------- 1 | 6 |

10 |

11 |

14 |

15 |

18 |

19 | 22 | 23 |
24 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/numeric.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-numeric { 2 | padding: 0 0 0 12px; 3 | } 4 | 5 | .nr-dashboard-numeric .value { 6 | font-weight: bold; 7 | text-align: center; 8 | border: 0px; 9 | } 10 | 11 | .nr-dashboard-numeric .md-button { 12 | margin: 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/numeric.html: -------------------------------------------------------------------------------- 1 | 9 |

11 |

12 | 17 | 18 |
19 | 26 | 27 | 28 |
29 |

33 |

34 | 35 | 36 | 37 | 38 | 39 |
40 | 47 | 48 | 49 |
50 |
51 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/slider.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-slider { 2 | padding: 0 12px; 3 | } 4 | 5 | .nr-dashboard-slider-v { 6 | flex-direction: column; 7 | padding: 0; 8 | font-size: small; 9 | } 10 | 11 | .nr-dashboard-slider p.label { 12 | margin-right: 15px; 13 | white-space: nowrap; 14 | } 15 | 16 | .nr-dashboard-slider p.label-v { 17 | margin-top: 6px; 18 | white-space: nowrap; 19 | overflow: hidden; 20 | padding-bottom: 4px; 21 | } 22 | 23 | md-slider[md-vertical] .md-slider-wrapper { 24 | width: unset; 25 | } 26 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/slider.html: -------------------------------------------------------------------------------- 1 | 10 |

13 |

14 | 19 | 20 | 33 | 34 | 51 | 52 |

55 |

56 |
57 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/spacer.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-spacer { 2 | } 3 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/spacer.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/switch.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-switch:focus { 2 | outline: 0px; 3 | } 4 | 5 | .nr-dashboard-switch:hover { 6 | cursor: -webkit-grab; 7 | cursor: grab; 8 | } 9 | 10 | .nr-dashboard-switch p { 11 | padding: 0 0 0 12px; 12 | } 13 | 14 | .nr-dashboard-switch md-switch { 15 | padding: 0 8px 0 8px; 16 | } 17 | 18 | .nr-dashboard-switch md-switch:hover { 19 | cursor: -webkit-grab; 20 | cursor: grab; 21 | } 22 | 23 | .nr-dashboard-switch md-switch.center{ 24 | margin: 0px auto; 25 | } 26 | 27 | .nr-dashboard-switch ui-icon { 28 | padding: 0 8px; 29 | } 30 | 31 | .nr-dashboard-switch ui-icon.center{ 32 | margin: 0px auto; 33 | } 34 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/switch.html: -------------------------------------------------------------------------------- 1 | 9 |

12 |

13 | 18 | 19 | 28 | 29 | 35 | 36 | 42 | 43 |
44 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/template.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-template { 2 | overflow-y: auto; 3 | vertical-align: inherit; 4 | } 5 | 6 | .nr-dashboard-template p { 7 | margin: 0.2em 0; 8 | } 9 | 10 | .nr-dashboard-template h4 { 11 | margin: 0.2em 0; 12 | } 13 | 14 | .nr-dashboard-template h3 { 15 | margin: 0.2em 0; 16 | } 17 | 18 | .nr-dashboard-template h2 { 19 | margin: 0.3em 0; 20 | } 21 | 22 | .nr-dashboard-template h1 { 23 | margin: 0.4em 0; 24 | } 25 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/template.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/text-input-CR.html: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | 19 | 20 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/text-input.css: -------------------------------------------------------------------------------- 1 | /* 2 | overwrite the default md-errors-spacer min-height 3 | reason: https://github.com/angular/material/issues/6214 4 | */ 5 | 6 | .nr-dashboard-textinput md-input-container { 7 | padding: 0px 12px; 8 | margin: 15px 0px; 9 | transition: 0.3s margin; 10 | -webkit-transition: 0.3s margin; 11 | } 12 | 13 | .nr-dashboard-textinput md-input-container .md-input { 14 | padding-top: 1px; 15 | } 16 | 17 | .nr-dashboard-textinput input { 18 | border-bottom-width: 1px; 19 | padding-left: 8px; 20 | } 21 | 22 | .nr-dashboard-textinput input[type="color"] { 23 | border: none; 24 | } 25 | 26 | .nr-dashboard-textinput md-input-container .md-errors-spacer { 27 | min-height: 0; 28 | } 29 | 30 | .nr-dashboard-textinput md-input-container .md-placeholder, 31 | .nr-dashboard-textinput md-input-container label:not(.md-no-float):not(.md-container-ignore) { 32 | padding-left: 12px; 33 | margin-bottom: 3px; 34 | } 35 | 36 | .nr-dashboard-textinput md-input-container.md-input-focused.has-label label:not(.md-no-float):not(.md-container-ignore), 37 | .nr-dashboard-textinput md-input-container.md-input-has-value.has-label label:not(.md-no-float):not(.md-container-ignore) { 38 | margin-bottom: -2px; 39 | } 40 | 41 | .nr-dashboard-textinput md-input-container.md-input-focused.has-label, 42 | .nr-dashboard-textinput md-input-container.md-input-has-value.has-label { 43 | margin: 15px 0px 5px; 44 | } 45 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/text-input.html: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | 19 | 20 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/text.css: -------------------------------------------------------------------------------- 1 | .nr-dashboard-text { 2 | padding: 0 12px; 3 | } 4 | 5 | .nr-dashboard-text p { 6 | margin-top: 0.1em; 7 | margin-bottom: 0.1em; 8 | margin-left: 0; 9 | margin-right: 0.25em; 10 | } 11 | 12 | .nr-dashboard-text .value { 13 | font-weight: bold; 14 | } 15 | -------------------------------------------------------------------------------- /src/components/ui-component/templates/text.html: -------------------------------------------------------------------------------- 1 | 9 |

10 |

11 |
12 | -------------------------------------------------------------------------------- /src/components/ui-component/ui-component.js: -------------------------------------------------------------------------------- 1 | angular.module('ui').directive('uiComponent', ['$http', '$compile', '$templateCache', '$q', 2 | function ($http, $compile, $templateCache, $q) { 3 | return { 4 | restrict: 'E', 5 | bindToController: { 6 | item: '=' 7 | }, 8 | replace: true, 9 | controller: "uiComponentController", 10 | controllerAs: "me", 11 | template: "
", 12 | scope: true, 13 | link: function (scope, element, attributes, ctrl) { 14 | scope.templateUrl = 'components/ui-component/templates/'+ ctrl.item.type +'.html'; 15 | ctrl.init(); 16 | } 17 | }; 18 | } 19 | ]); 20 | 21 | angular.module('ui').directive('includeReplace', function () { 22 | return { 23 | require: 'ngInclude', 24 | restrict: 'A', /* optional */ 25 | link: function (scope, el, attrs) { 26 | el.replaceWith(el.children()); 27 | } 28 | }; 29 | }); 30 | -------------------------------------------------------------------------------- /src/components/ui-gauge/ui-gauge.html: -------------------------------------------------------------------------------- 1 |
7 |
8 | -------------------------------------------------------------------------------- /src/components/ui-icon/ui-icon.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
{{icon.substr(3)}}
5 |
6 |
7 |
8 | 9 | -------------------------------------------------------------------------------- /src/components/ui-icon/ui-icon.js: -------------------------------------------------------------------------------- 1 | /* global angular */ 2 | var iconFontOddEven = false; 3 | angular.module('ui').directive('uiIcon', 4 | function () { 5 | var url = /^https?:\/\//i; 6 | var fa = /^fa-/i; 7 | var wi = /^wi-/i; 8 | var mi = /^mi-/i; 9 | var ic = /^icofont-/i; 10 | var icf = /^iconify-/i; 11 | 12 | return { 13 | restrict: 'E', 14 | templateUrl: 'components/ui-icon/ui-icon.html', 15 | scope: { 16 | icon: '@' 17 | }, 18 | //replace: true, 19 | link: function (scope) { 20 | scope.$watch('icon', function (newValue) { 21 | if (newValue === "") { return; } 22 | else if (fa.test(newValue)) { scope.iconType = 'fa'; } 23 | else if (wi.test(newValue)) { scope.iconType = 'wi'; } 24 | else if (mi.test(newValue)) { scope.iconType = 'mi'; } 25 | else if (ic.test(newValue)) { scope.iconType = 'icofont'; } 26 | else if (icf.test(newValue)) { 27 | if (iconFontOddEven) { scope.iconType = 'iconify'; } 28 | else { scope.iconType = 'iconify1'; } 29 | iconFontOddEven = !iconFontOddEven; 30 | } 31 | else if (url.test(newValue)) { 32 | scope.iconType = 'image'; 33 | scope.url = newValue; 34 | } 35 | else { scope.iconType = 'angular-material'; } 36 | }); 37 | } 38 | }; 39 | }); 40 | -------------------------------------------------------------------------------- /src/dashboard.appcache: -------------------------------------------------------------------------------- 1 | CACHE MANIFEST 2 | 3 | CACHE: 4 | 5 | NETWORK: 6 | * 7 | -------------------------------------------------------------------------------- /src/directives/ui-colour-picker.js: -------------------------------------------------------------------------------- 1 | /* global angular */ 2 | angular.module('ui').directive('colorPickerInputWrapper', 3 | function () { 4 | return { 5 | restrict: 'C', 6 | link: function(scope, element, attrs) { 7 | if (scope.AngularColorPickerController.options.pickerOnly) { 8 | element.hide(); 9 | } 10 | } 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /src/directives/ui-highlight.js: -------------------------------------------------------------------------------- 1 | /* global angular */ 2 | angular.module('ui').directive('uiHighlight', 3 | function () { 4 | return { 5 | restrict: 'A', 6 | link: function(scope, element, attrs) { 7 | attrs.$observe('uiHighlight', function (color) { 8 | if (color) { 9 | element.css('border-bottom', '5px solid ' + color); 10 | } 11 | else { 12 | element.css('border-bottom', undefined); 13 | } 14 | }); 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /src/directives/ui-template.js: -------------------------------------------------------------------------------- 1 | /* global angular */ 2 | angular.module('ui').directive('uiTemplate', ['$compile', '$rootScope', 'UiEvents', 3 | function ($compile, $rootScope, events) { 4 | function createInnerScope(id) { 5 | var innerScope = $rootScope.$new(); 6 | innerScope.send = function(msg) { 7 | events.emit({id:id, msg:msg}); 8 | }; 9 | return innerScope; 10 | } 11 | 12 | return function(scope, element, attrs) { 13 | var id = scope.$eval('me.item.id'); 14 | var innerScope; 15 | 16 | scope.$watch(attrs.uiTemplate, function(value) { 17 | var oldMsg; 18 | if (innerScope) { 19 | oldMsg = innerScope.msg; // save msg.payload to inject good values if template has changed 20 | innerScope.$destroy(); 21 | } 22 | innerScope = createInnerScope(id); 23 | innerScope.theme = scope.$eval('me.item.theme'); 24 | window.scope = innerScope; 25 | element.html(value); 26 | delete window.scope; 27 | if (oldMsg !== undefined) { 28 | innerScope.msg = oldMsg; 29 | } 30 | 31 | var ic = scope.$eval("me.item.initController"); 32 | if (ic) { 33 | var func = eval("("+ic+")"); // jshint ignore:line 34 | func(innerScope, events); 35 | } 36 | innerScope.width = scope.$eval("me.item.width"); 37 | innerScope.height = scope.$eval("me.item.height"); 38 | innerScope.label = scope.$eval("me.item.label"); 39 | 40 | $compile(element.contents())(innerScope); 41 | }); 42 | 43 | scope.$watch('me.item.msg', function (value) { 44 | if (innerScope) { 45 | innerScope.msg = value; 46 | 47 | // update template 48 | if (value !== undefined && value.template !== undefined) { 49 | scope.$parent.me.setFormat(value.template); 50 | } 51 | } 52 | }); 53 | 54 | scope.$on('$destroy', function() { 55 | if (innerScope) { innerScope.$destroy(); } 56 | }); 57 | }; 58 | }]); 59 | -------------------------------------------------------------------------------- /src/directives/ui-touchend.js: -------------------------------------------------------------------------------- 1 | /* global angular */ 2 | angular.module('ui').directive('uiTouchend', 3 | function uiTouchend () { 4 | return { 5 | restrict: 'A', 6 | link: function (scope, element, attrs) { 7 | element.on('touchend', doTouchend); 8 | function doTouchend (event) { 9 | event.preventDefault(); 10 | scope.$event = event; 11 | scope.$apply(attrs["ui-touchend"]); 12 | } 13 | } 14 | }; 15 | } 16 | ) 17 | -------------------------------------------------------------------------------- /src/filters/chartGetRange.js: -------------------------------------------------------------------------------- 1 | /* global angular d3 */ 2 | angular.module('ui').filter('chartGetRange', function() { 3 | return function(value, range) { 4 | range = [parseFloat(range[0]), parseFloat(range[1])]; 5 | var min = Math.abs(range[0])>=0 ? range[0] : d3.min(value, function (a) { return d3.min(a.values, function(b) {return b[1];}); }); 6 | var max = Math.abs(range[1])>=0 ? range[1] : d3.max(value, function (a) { return d3.max(a.values, function(b) {return b[1];}); }); 7 | return [Math.floor(min), Math.ceil(max)]; 8 | }; 9 | }); 10 | -------------------------------------------------------------------------------- /src/filters/spaceToUnderscore.js: -------------------------------------------------------------------------------- 1 | /* global angular */ 2 | angular.module('ui').filter('spaceToUnderscore', function() { 3 | return function (input) { 4 | return input.replace(/ /g,'_'); 5 | }; 6 | }); 7 | 8 | angular.module('ui').filter('underscoreToSpace', function() { 9 | return function (input) { 10 | return input.replace(/_/g,' '); 11 | }; 12 | }); 13 | -------------------------------------------------------------------------------- /src/filters/trusted.js: -------------------------------------------------------------------------------- 1 | /* global angular */ 2 | angular.module('ui').filter('trusted', ['$sce', function($sce) { 3 | return function(html) { 4 | return $sce.trustAsHtml(html) 5 | }; 6 | }]); 7 | -------------------------------------------------------------------------------- /src/gridstack-extra.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * gridstack 0.6.3-dev extra CSS for [2-11] columns (non default) 3 | * https://gridstackjs.com/ 4 | * (c) 2014-2020 Alain Dumesny, Dylan Weiss, Pavel Reznikov 5 | * gridstack.js may be freely distributed under the MIT license. 6 | */ 7 | 8 | $gridstack-columns: 11 !default; 9 | 10 | @mixin grid-stack-items($columns) { 11 | .grid-stack.grid-stack-#{$columns} { 12 | 13 | > .grid-stack-item { 14 | min-width: calc(100% / $columns); 15 | 16 | @for $i from 1 through $columns { 17 | &[data-gs-width='#{$i}'] { width: calc(100% / $columns * $i); } 18 | &[data-gs-x='#{$i}'] { left: calc(100% / $columns * $i); } 19 | &[data-gs-min-width='#{$i}'] { min-width: calc(100% / $columns * $i); } 20 | &[data-gs-max-width='#{$i}'] { max-width: calc(100% / $columns * $i); } 21 | } 22 | } 23 | } 24 | } 25 | 26 | @for $j from 2 through $gridstack-columns { 27 | @include grid-stack-items($j) 28 | } 29 | 30 | .grid-stack>.grid-stack-item>.grid-stack-item-content { 31 | overflow: hidden; 32 | line-height: 18px; 33 | } 34 | -------------------------------------------------------------------------------- /src/i18n.js: -------------------------------------------------------------------------------- 1 | // Placeholder only - This is NOT a sustainable solution to i18n localisation 2 | // Replace/overwrite this file with an angular-locale_... file of your choice from the npm angular-i18n project 3 | // Then edit dashboard.appcache - (for example add a digit to the hash) 4 | // Stop, start Node-RED and refresh the browser page twice to flush the cache. 5 | -------------------------------------------------------------------------------- /src/icon120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/src/icon120x120.png -------------------------------------------------------------------------------- /src/icon192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/src/icon192x192.png -------------------------------------------------------------------------------- /src/icon64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/src/icon64x64.png -------------------------------------------------------------------------------- /src/logout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 25 | 38 |
39 | 40 | 41 |

Welcome to the Node-RED Dashboard

Please sign in to see your flow.
42 |
43 | 44 | -------------------------------------------------------------------------------- /src/main.less: -------------------------------------------------------------------------------- 1 | 2 | @media(max-width: 959px) { 3 | .md-sidenav-left, md-sidenav { 4 | top: 48px !important; 5 | z-index: 80; 6 | } 7 | } 8 | @media (max-width: 959px) and (min-width: 0) and (orientation: portrait) { 9 | md-toolbar { 10 | min-height: 48px; 11 | height: 48px; 12 | max-height: 48px; 13 | } 14 | } 15 | @media(min-width: 960px) { 16 | .md-sidenav-left, md-sidenav { 17 | top: 64px; 18 | z-index: 80; 19 | } 20 | } 21 | @media(max-width: 660px) { 22 | md-sidenav, 23 | md-sidenav.md-locked-open, 24 | md-sidenav.md-closed.md-locked-open-add-active { 25 | min-width: 64px !important; 26 | width: auto; 27 | max-width: 200px !important; 28 | } 29 | } 30 | @media(min-width: 661px) { 31 | md-sidenav, 32 | md-sidenav.md-locked-open, 33 | md-sidenav.md-closed.md-locked-open-add-active { 34 | min-width: 64px !important; 35 | width: auto; 36 | max-width: 320px !important; 37 | } 38 | } 39 | md-sidenav ng-md-icon { 40 | padding-right: 4px; 41 | } 42 | md-sidenav i { 43 | padding-right: 4px; 44 | } 45 | md-sidenav md-list-item .md-list-item-inner>p { 46 | line-height: 20px; 47 | } 48 | md-card > md-list > md-list-item > div > md-icon > ui-icon > ng-md-icon { 49 | vertical-align:unset !important; 50 | } 51 | 52 | md-toast .md-toast-content { 53 | height: auto; 54 | } 55 | md-toast .md-toast-error { 56 | color: rgba(255, 64, 41, 0.84); 57 | font-weight: 500; 58 | font-size: large; 59 | } 60 | md-backdrop.md-sidenav-backdrop { 61 | z-index: 80; 62 | } 63 | md-card { 64 | box-shadow: none; 65 | } 66 | 67 | .md-button { 68 | min-width: 64px; 69 | } 70 | .md-tooltip { 71 | background-color: #888 !important; 72 | color: #fff !important; 73 | border-radius: 3px; 74 | opacity: 1 !important; 75 | } 76 | .md-tooltip.md-origin-bottom { 77 | margin-top: -6px; 78 | margin-left: -8px; 79 | } 80 | 81 | .node-red-ui--notabs { 82 | color: #888; 83 | font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; 84 | display: flex; 85 | height: 100%; 86 | width: 100%; 87 | align-items: center; 88 | justify-content: center; 89 | opacity: 1; 90 | animation-name: fadeInOpacity; 91 | animation-iteration-count: 1; 92 | animation-timing-function: ease-in; 93 | animation-duration: 2.5s; 94 | } 95 | 96 | .node-red-ui--loading { 97 | color: #888; 98 | font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; 99 | display: flex; 100 | height: 100%; 101 | width: 100%; 102 | align-items: center; 103 | justify-content: center; 104 | } 105 | 106 | .node-red-ui--inline-link { 107 | width: 100%; 108 | height: 100%; 109 | position: absolute; 110 | } 111 | .node-red-ui--inline-link iframe { 112 | width: 100%; 113 | height: 100%; 114 | overflow: hidden; 115 | } 116 | 117 | .material-icons { 118 | vertical-align: middle; 119 | } 120 | 121 | .ie9 img[src$=".svg"] { 122 | width: 100%; 123 | } 124 | 125 | @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { 126 | img[src$=".svg"] { 127 | width: 100%; 128 | } 129 | } 130 | 131 | @keyframes fadeInOpacity { 132 | 0% { 133 | opacity: 0; 134 | } 135 | 30% { 136 | opacity: 0; 137 | } 138 | 100% { 139 | opacity: 1; 140 | } 141 | } 142 | 143 | .flip-icon { 144 | animation: flip-icon 0.3s linear both; 145 | } 146 | 147 | @keyframes flip-icon { 148 | 0% { 149 | transform: rotateY(180deg); 150 | } 151 | 100% { 152 | transform: rotateY(0deg); 153 | } 154 | } 155 | 156 | @supports (-ms-overflow-style: none) { 157 | overflow:auto !important; 158 | } 159 | -------------------------------------------------------------------------------- /src/partials/main.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 |

7 |

{{main.name}}

8 |

{{main.selectedTab.header || main.selectedTab.name}}

9 |
10 |
11 |
12 | 13 | 14 | 15 | 16 |

{{main.getMenuName(obj)}}

17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 | 25 |
26 | 30 |
31 |
32 | 33 | -------------------------------------------------------------------------------- /src/partials/toast.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

{{::toast.title}}

4 |

5 |
6 |
7 | -------------------------------------------------------------------------------- /src/services/events.js: -------------------------------------------------------------------------------- 1 | /* global angular io */ 2 | angular.module('ui').service('UiEvents', 3 | function () { 4 | var updateValueEventName = 'update-value'; 5 | var that = this; 6 | 7 | this.connect = function(onuiloaded, replaydone) { 8 | var socket; 9 | if (location.protocol === "https:") { 10 | socket = io({path:location.pathname + 'socket.io', secure:true}); 11 | } 12 | else { 13 | socket = io({path:location.pathname + 'socket.io'}); 14 | } 15 | 16 | this.emit = function(event, msg) { 17 | if (typeof msg === 'undefined') { 18 | msg = event; 19 | event = updateValueEventName; 20 | } 21 | msg.socketid = socket.id; 22 | socket.emit(event, msg); 23 | }; 24 | 25 | this.on = function(event, handler) { 26 | if (typeof handler === 'undefined') { 27 | handler = event; 28 | event = updateValueEventName; 29 | } 30 | 31 | var socketHandler = function(data) { 32 | handler(data); 33 | }; 34 | 35 | socket.on(event, socketHandler); 36 | 37 | return function() { socket.removeListener(event, socketHandler); }; 38 | }; 39 | 40 | socket.on('ui-controls', function (data) { 41 | onuiloaded(data, function() { 42 | socket.emit('ui-replay-state'); 43 | }); 44 | }); 45 | 46 | socket.on('ui-replay-done', function() { 47 | replaydone(); 48 | }); 49 | 50 | socket.on('connect', function() { 51 | that.id = socket.id; 52 | }) 53 | }; 54 | }); 55 | -------------------------------------------------------------------------------- /src/services/sizes.js: -------------------------------------------------------------------------------- 1 | /* global angular */ 2 | var sizes = { 3 | sx: 48, // width of <1> grid square 4 | sy: 48, // height of <1> grid square 5 | gx: 6, // gap between groups - group spacing 6 | gy: 6, // gap between groups 7 | cx: 6, // gap between components - widget spacing 8 | cy: 6, // gap between components 9 | px: 0, // padding of group's cards - group padding 10 | py: 0 // padding of group's cards 11 | }; 12 | 13 | if (window.innerWidth < 350) { 14 | sizes.sx = 42; 15 | sizes.sy = 42; 16 | } 17 | 18 | sizes.setSizes = function(s) { 19 | sizes.sx = s.sx; 20 | sizes.sy = s.sy; 21 | sizes.gx = s.gx; 22 | sizes.gy = s.gy; 23 | sizes.cx = s.cx; 24 | sizes.cy = s.cy; 25 | sizes.px = s.px; 26 | sizes.py = s.py; 27 | } 28 | 29 | sizes.columns = function (group) { 30 | return parseInt(group.header.config.width); 31 | } 32 | 33 | angular.module('ui').value('uiSizes', sizes); 34 | -------------------------------------------------------------------------------- /src/socket.io/socket.io.js: -------------------------------------------------------------------------------- 1 | //this is an empty file so that the gulp build task doesn't fail -------------------------------------------------------------------------------- /src/wheel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/node-red/node-red-dashboard/d03a654071a034b343d6d9397e4eaa9f07b09747/src/wheel.png --------------------------------------------------------------------------------