thingsboard-aplcache

UI: New widget type 'HTML Card'

2/6/2017 7:55:43 AM

Details

diff --git a/dao/src/main/resources/system-data.cql b/dao/src/main/resources/system-data.cql
index 3b8e320..76ffd24 100644
--- a/dao/src/main/resources/system-data.cql
+++ b/dao/src/main/resources/system-data.cql
@@ -83,6 +83,11 @@ VALUES ( now ( ), minTimeuuid ( 0 ), 'cards', 'timeseries_table',
 'Timeseries table' );
 
 INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
+VALUES ( now ( ), minTimeuuid ( 0 ), 'cards', 'html_card',
+'{"type":"static","sizeX":7.5,"sizeY":3,"resources":[],"templateHtml":"","templateCss":"","controllerScript":"fns.init = function(containerElement, settings, datasources,\n    data) {\n\n    var container = $(containerElement);\n    \n    var cssParser = new cssjs();\n    cssParser.testMode = false;\n    var namespace = ''html-card-'' + hashCode(settings.cardCss);\n    cssParser.cssPreviewNamespace = namespace;\n    cssParser.createStyleElement(namespace, settings.cardCss);\n    container.addClass(namespace);\n    container.html(settings.cardHtml);\n    \n    function hashCode(str) {\n        var hash = 0;\n        var i, char;\n        if (str.length === 0) return hash;\n        for (i = 0; i < str.length; i++) {\n            char = str.charCodeAt(i);\n            hash = ((hash << 5) - hash) + char;\n            hash = hash & hash;\n        }\n        return hash;\n    }\n\n}\n\n\nfns.redraw = function(containerElement, width, height, data, timeWindow, sizeChanged) {\n\n};","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"required\": [\"cardHtml\"],\n        \"properties\": {\n            \"cardCss\": {\n                \"title\": \"CSS\",\n                \"type\": \"string\",\n                \"default\": \".card {\\n font-weight: bold; \\n}\"\n            },\n            \"cardHtml\": {\n                \"title\": \"HTML\",\n                \"type\": \"string\",\n                \"default\": \"<div class=''card''>HTML code here</div>\"\n            }\n        }\n    },\n    \"form\": [\n        {\n            \"key\": \"cardCss\",\n            \"type\": \"css\"\n        },           \n        {\n            \"key\": \"cardHtml\",\n            \"type\": \"html\"\n        }    \n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"cardHtml\":\"<div class=''card''>HTML code here</div>\",\"cardCss\":\".card {\\n    font-weight: bold;\\n    font-size: 32px;\\n    color: #999;\\n    width: 100%;\\n    height: 100%;\\n    display: flex;\\n    align-items: center;\\n    justify-content: center;\\n}\"},\"title\":\"HTML Card\",\"dropShadow\":true}"}',
+'HTML Card' );
+
+INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
 VALUES ( now ( ), minTimeuuid ( 0 ), 'analogue_gauges', 'speed_gauge_canvas_gauges',
 '{"type":"latest","sizeX":7,"sizeY":5,"resources":[],"templateHtml":"<canvas id=\"radialGauge\"></canvas>\n","templateCss":"","controllerScript":"var gauge;\n\nfns.init = function(containerElement, settings, datasources,\n    data) {\n    gauge = new TbAnalogueRadialGauge(containerElement, settings, data, ''radialGauge'');    \n\n}\n\n\nfns.redraw = function(containerElement, width, height, data, timeWindow, sizeChanged) {\n    gauge.redraw(width, height, data, sizeChanged);\n};\n\nfns.destroy = function() {\n}\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"properties\": {\n            \"minValue\": {\n                \"title\": \"Minimum value\",\n                \"type\": \"number\",\n                \"default\": 0\n            },\n            \"maxValue\": {\n                \"title\": \"Maximum value\",\n                \"type\": \"number\",\n                \"default\": 100\n            },\n            \"unitTitle\": {\n                \"title\": \"Unit title\",\n                \"type\": \"string\",\n                \"default\": null\n            },\n            \"showUnitTitle\": {\n                \"title\": \"Show unit title\",\n                \"type\": \"boolean\",\n                \"default\": true\n            },\n            \"units\": {\n                \"title\": \"Units\",\n                \"type\": \"string\",\n                \"default\": \"\"\n            },\n            \"majorTicksCount\": {\n                \"title\": \"Major ticks count\",\n                \"type\": \"number\",\n                \"default\": null\n            },\n            \"minorTicks\": {\n                \"title\": \"Minor ticks count\",\n                \"type\": \"number\",\n                \"default\": 2\n            },\n            \"valueBox\": {\n                \"title\": \"Show value box\",\n                \"type\": \"boolean\",\n                \"default\": true\n            },\n            \"valueInt\": {\n                \"title\": \"Digits count for integer part of value\",\n                \"type\": \"number\",\n                \"default\": 3\n            },\n            \"valueDec\": {\n                \"title\": \"Digits count for decimal part of value\",\n                \"type\": \"number\",\n                \"default\": 2\n            },\n            \"defaultColor\": {\n                \"title\": \"Default color\",\n                \"type\": \"string\",\n                \"default\": null\n            },\n            \"colorPlate\": {\n                \"title\": \"Plate color\",\n                \"type\": \"string\",\n                \"default\": \"#fff\"\n            },\n            \"colorMajorTicks\": {\n                \"title\": \"Major ticks color\",\n                \"type\": \"string\",\n                \"default\": \"#444\"\n            },\n            \"colorMinorTicks\": {\n                \"title\": \"Minor ticks color\",\n                \"type\": \"string\",\n                \"default\": \"#666\"\n            },\n            \"colorNeedle\": {\n                \"title\": \"Needle color\",\n                \"type\": \"string\",\n                \"default\": null\n            },\n            \"colorNeedleEnd\": {\n                \"title\": \"Needle color - end gradient\",\n                \"type\": \"string\",\n                \"default\": null\n            },\n            \"colorNeedleShadowUp\": {\n                \"title\": \"Upper half of the needle shadow color\",\n                \"type\": \"string\",\n                \"default\": \"rgba(2,255,255,0.2)\"\n            },\n            \"colorNeedleShadowDown\": {\n                \"title\": \"Drop shadow needle color.\",\n                \"type\": \"string\",\n                \"default\": \"rgba(188,143,143,0.45)\"\n            },\n            \"colorValueBoxRect\": {\n                \"title\": \"Value box rectangle stroke color\",\n                \"type\": \"string\",\n                \"default\": \"#888\"\n            },\n            \"colorValueBoxRectEnd\": {\n                \"title\": \"Value box rectangle stroke color - end gradient\",\n                \"type\": \"string\",\n                \"default\": \"#666\"\n            },\n            \"colorValueBoxBackground\": {\n                \"title\": \"Value box background color\",\n                \"type\": \"string\",\n                \"default\": \"#babab2\"\n            },\n            \"colorValueBoxShadow\": {\n                \"title\": \"Value box shadow color\",\n                \"type\": \"string\",\n                \"default\": \"rgba(0,0,0,1)\"\n            },\n            \"highlights\": {\n                \"title\": \"Highlights\",\n                \"type\": \"array\",\n                \"items\": {\n                  \"title\": \"Highlight\",\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"from\": {\n                      \"title\": \"From\",\n                      \"type\": \"number\"\n                    },\n                    \"to\": {\n                      \"title\": \"To\",\n                      \"type\": \"number\"\n                    },\n                    \"color\": {\n                      \"title\": \"Color\",\n                      \"type\": \"string\"\n                    }\n                  }\n                }\n            },\n            \"highlightsWidth\": {\n                \"title\": \"Highlights width\",\n                \"type\": \"number\",\n                \"default\": 15\n            },\n            \"showBorder\": {\n                \"title\": \"Show border\",\n                \"type\": \"boolean\",\n                \"default\": true\n            },\n            \"numbersFont\": {\n                \"title\": \"Tick numbers font\",\n                \"type\": \"object\",\n                 \"properties\": {\n                    \"family\": {\n                        \"title\": \"Font family\",\n                        \"type\": \"string\",\n                        \"default\": \"RobotoDraft\"\n                    },\n                    \"size\": {\n                      \"title\": \"Size\",\n                      \"type\": \"number\",\n                      \"default\": 18\n                    },\n                    \"style\": {\n                      \"title\": \"Style\",\n                      \"type\": \"string\",\n                      \"default\": \"normal\"\n                    },\n                    \"weight\": {\n                      \"title\": \"Weight\",\n                      \"type\": \"string\",\n                      \"default\": \"500\"\n                    },\n                    \"color\": {\n                        \"title\": \"color\",\n                        \"type\": \"string\",\n                        \"default\": null\n                    }\n                }\n            },\n            \"titleFont\": {\n                \"title\": \"Title text font\",\n                \"type\": \"object\",\n                 \"properties\": {\n                    \"family\": {\n                        \"title\": \"Font family\",\n                        \"type\": \"string\",\n                        \"default\": \"RobotoDraft\"\n                    },\n                    \"size\": {\n                      \"title\": \"Size\",\n                      \"type\": \"number\",\n                      \"default\": 24\n                    },\n                    \"style\": {\n                      \"title\": \"Style\",\n                      \"type\": \"string\",\n                      \"default\": \"normal\"\n                    },\n                    \"weight\": {\n                      \"title\": \"Weight\",\n                      \"type\": \"string\",\n                      \"default\": \"500\"\n                    },\n                    \"color\": {\n                        \"title\": \"color\",\n                        \"type\": \"string\",\n                        \"default\": \"#888\"\n                    }\n                }\n            },\n            \"unitsFont\": {\n                \"title\": \"Units text font\",\n                \"type\": \"object\",\n                 \"properties\": {\n                    \"family\": {\n                        \"title\": \"Font family\",\n                        \"type\": \"string\",\n                        \"default\": \"RobotoDraft\"\n                    },\n                    \"size\": {\n                      \"title\": \"Size\",\n                      \"type\": \"number\",\n                      \"default\": 22\n                    },\n                    \"style\": {\n                      \"title\": \"Style\",\n                      \"type\": \"string\",\n                      \"default\": \"normal\"\n                    },\n                    \"weight\": {\n                      \"title\": \"Weight\",\n                      \"type\": \"string\",\n                      \"default\": \"500\"\n                    },\n                    \"color\": {\n                        \"title\": \"color\",\n                        \"type\": \"string\",\n                        \"default\": \"#888\"\n                    }\n                }\n            },\n            \"valueFont\": {\n                \"title\": \"Value text font\",\n                \"type\": \"object\",\n                 \"properties\": {\n                    \"family\": {\n                        \"title\": \"Font family\",\n                        \"type\": \"string\",\n                        \"default\": \"RobotoDraft\"\n                    },\n                    \"size\": {\n                      \"title\": \"Size\",\n                      \"type\": \"number\",\n                      \"default\": 40\n                    },\n                    \"style\": {\n                      \"title\": \"Style\",\n                      \"type\": \"string\",\n                      \"default\": \"normal\"\n                    },\n                    \"weight\": {\n                      \"title\": \"Weight\",\n                      \"type\": \"string\",\n                      \"default\": \"500\"\n                    },\n                    \"color\": {\n                        \"title\": \"color\",\n                        \"type\": \"string\",\n                        \"default\": \"#444\"\n                    },\n                    \"shadowColor\": {\n                        \"title\": \"Shadow color\",\n                        \"type\": \"string\",\n                        \"default\": \"rgba(0,0,0,0.3)\"\n                    }\n                }\n            },\n            \"animation\": {\n                \"title\": \"Enable animation\",\n                \"type\": \"boolean\",\n                \"default\": true\n            },\n            \"animationDuration\": {\n                \"title\": \"Animation duration\",\n                \"type\": \"number\",\n                \"default\": 500\n            },\n            \"animationRule\": {\n                \"title\": \"Animation rule\",\n                \"type\": \"string\",\n                \"default\": \"cycle\"\n            },\n            \"startAngle\": {\n                \"title\": \"Start ticks angle\",\n                \"type\": \"number\",\n                \"default\": 45\n            },\n            \"ticksAngle\": {\n                \"title\": \"Ticks angle\",\n                \"type\": \"number\",\n                \"default\": 270\n            },\n            \"needleCircleSize\": {\n                \"title\": \"Needle circle size\",\n                \"type\": \"number\",\n                \"default\": 10\n            }\n        },\n        \"required\": []\n    },\n    \"form\": [\n        \"startAngle\",\n        \"ticksAngle\",\n        \"needleCircleSize\",\n        \"minValue\",\n        \"maxValue\",\n        \"unitTitle\",\n        \"showUnitTitle\",\n        \"units\",\n        \"majorTicksCount\",\n        \"minorTicks\",\n        \"valueBox\",\n        \"valueInt\",\n        \"valueDec\",\n        {\n            \"key\": \"defaultColor\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorPlate\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorMajorTicks\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorMinorTicks\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorNeedle\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorNeedleEnd\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorNeedleShadowUp\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorNeedleShadowDown\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorValueBoxRect\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorValueBoxRectEnd\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorValueBoxBackground\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"colorValueBoxShadow\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"highlights\",\n            \"items\": [\n                \"highlights[].from\",\n                \"highlights[].to\",\n                {\n                    \"key\": \"highlights[].color\",\n                    \"type\": \"color\"\n                }\n            ]\n        },\n        \"highlightsWidth\",\n        \"showBorder\",\n        {\n            \"key\": \"numbersFont\",\n            \"items\": [\n                \"numbersFont.family\",\n                \"numbersFont.size\",\n                {\n                   \"key\": \"numbersFont.style\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"italic\",\n                           \"label\": \"Italic\"\n                       },\n                       {\n                           \"value\": \"oblique\",\n                           \"label\": \"Oblique\"\n                       }\n                    ]\n                },\n                {\n                   \"key\": \"numbersFont.weight\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"bold\",\n                           \"label\": \"Bold\"\n                       },\n                       {\n                           \"value\": \"bolder\",\n                           \"label\": \"Bolder\"\n                       },\n                       {\n                           \"value\": \"lighter\",\n                           \"label\": \"Lighter\"\n                       },\n                       {\n                           \"value\": \"100\",\n                           \"label\": \"100\"\n                       },\n                       {\n                           \"value\": \"200\",\n                           \"label\": \"200\"\n                       },\n                       {\n                           \"value\": \"300\",\n                           \"label\": \"300\"\n                       },\n                       {\n                           \"value\": \"400\",\n                           \"label\": \"400\"\n                       },\n                       {\n                           \"value\": \"500\",\n                           \"label\": \"500\"\n                       },\n                       {\n                           \"value\": \"600\",\n                           \"label\": \"600\"\n                       },\n                       {\n                           \"value\": \"700\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"800\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"900\",\n                           \"label\": \"900\"\n                       }\n                    ]\n                },\n                {\n                    \"key\": \"numbersFont.color\",\n                    \"type\": \"color\"\n                }\n            ]\n        },\n        {\n            \"key\": \"titleFont\",\n            \"items\": [\n                \"titleFont.family\",\n                \"titleFont.size\",\n                {\n                   \"key\": \"titleFont.style\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"italic\",\n                           \"label\": \"Italic\"\n                       },\n                       {\n                           \"value\": \"oblique\",\n                           \"label\": \"Oblique\"\n                       }\n                    ]\n                },\n                {\n                   \"key\": \"titleFont.weight\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"bold\",\n                           \"label\": \"Bold\"\n                       },\n                       {\n                           \"value\": \"bolder\",\n                           \"label\": \"Bolder\"\n                       },\n                       {\n                           \"value\": \"lighter\",\n                           \"label\": \"Lighter\"\n                       },\n                       {\n                           \"value\": \"100\",\n                           \"label\": \"100\"\n                       },\n                       {\n                           \"value\": \"200\",\n                           \"label\": \"200\"\n                       },\n                       {\n                           \"value\": \"300\",\n                           \"label\": \"300\"\n                       },\n                       {\n                           \"value\": \"400\",\n                           \"label\": \"400\"\n                       },\n                       {\n                           \"value\": \"500\",\n                           \"label\": \"500\"\n                       },\n                       {\n                           \"value\": \"600\",\n                           \"label\": \"600\"\n                       },\n                       {\n                           \"value\": \"700\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"800\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"900\",\n                           \"label\": \"900\"\n                       }\n                    ]\n                },\n                {\n                    \"key\": \"titleFont.color\",\n                    \"type\": \"color\"\n                }\n            ]\n        },\n        {\n            \"key\": \"unitsFont\",\n            \"items\": [\n                \"unitsFont.family\",\n                \"unitsFont.size\",\n                {\n                   \"key\": \"unitsFont.style\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"italic\",\n                           \"label\": \"Italic\"\n                       },\n                       {\n                           \"value\": \"oblique\",\n                           \"label\": \"Oblique\"\n                       }\n                    ]\n                },\n                {\n                   \"key\": \"unitsFont.weight\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"bold\",\n                           \"label\": \"Bold\"\n                       },\n                       {\n                           \"value\": \"bolder\",\n                           \"label\": \"Bolder\"\n                       },\n                       {\n                           \"value\": \"lighter\",\n                           \"label\": \"Lighter\"\n                       },\n                       {\n                           \"value\": \"100\",\n                           \"label\": \"100\"\n                       },\n                       {\n                           \"value\": \"200\",\n                           \"label\": \"200\"\n                       },\n                       {\n                           \"value\": \"300\",\n                           \"label\": \"300\"\n                       },\n                       {\n                           \"value\": \"400\",\n                           \"label\": \"400\"\n                       },\n                       {\n                           \"value\": \"500\",\n                           \"label\": \"500\"\n                       },\n                       {\n                           \"value\": \"600\",\n                           \"label\": \"600\"\n                       },\n                       {\n                           \"value\": \"700\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"800\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"900\",\n                           \"label\": \"900\"\n                       }\n                    ]\n                },\n                {\n                    \"key\": \"unitsFont.color\",\n                    \"type\": \"color\"\n                }\n            ]\n        },\n        {\n            \"key\": \"valueFont\",\n            \"items\": [\n                \"valueFont.family\",\n                \"valueFont.size\",\n                {\n                   \"key\": \"valueFont.style\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"italic\",\n                           \"label\": \"Italic\"\n                       },\n                       {\n                           \"value\": \"oblique\",\n                           \"label\": \"Oblique\"\n                       }\n                    ]\n                },\n                {\n                   \"key\": \"valueFont.weight\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"bold\",\n                           \"label\": \"Bold\"\n                       },\n                       {\n                           \"value\": \"bolder\",\n                           \"label\": \"Bolder\"\n                       },\n                       {\n                           \"value\": \"lighter\",\n                           \"label\": \"Lighter\"\n                       },\n                       {\n                           \"value\": \"100\",\n                           \"label\": \"100\"\n                       },\n                       {\n                           \"value\": \"200\",\n                           \"label\": \"200\"\n                       },\n                       {\n                           \"value\": \"300\",\n                           \"label\": \"300\"\n                       },\n                       {\n                           \"value\": \"400\",\n                           \"label\": \"400\"\n                       },\n                       {\n                           \"value\": \"500\",\n                           \"label\": \"500\"\n                       },\n                       {\n                           \"value\": \"600\",\n                           \"label\": \"600\"\n                       },\n                       {\n                           \"value\": \"700\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"800\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"900\",\n                           \"label\": \"900\"\n                       }\n                    ]\n                },\n                {\n                    \"key\": \"valueFont.color\",\n                    \"type\": \"color\"\n                },\n                {\n                    \"key\": \"valueFont.shadowColor\",\n                    \"type\": \"color\"\n                }\n            ]\n        },        \n        \"animation\",\n        \"animationDuration\",\n        {\n            \"key\": \"animationRule\",\n            \"type\": \"rc-select\",\n            \"multiple\": false,\n            \"items\": [\n                {\n                    \"value\": \"linear\",\n                    \"label\": \"Linear\"\n                },\n                {\n                    \"value\": \"quad\",\n                    \"label\": \"Quad\"\n                },\n                {\n                    \"value\": \"quint\",\n                    \"label\": \"Quint\"\n                },\n                {\n                    \"value\": \"cycle\",\n                    \"label\": \"Cycle\"\n                },\n                {\n                    \"value\": \"bounce\",\n                    \"label\": \"Bounce\"\n                },\n                {\n                    \"value\": \"elastic\",\n                    \"label\": \"Elastic\"\n                },\n                {\n                    \"value\": \"dequad\",\n                    \"label\": \"Dequad\"\n                },\n                {\n                    \"value\": \"dequint\",\n                    \"label\": \"Dequint\"\n                },\n                {\n                    \"value\": \"decycle\",\n                    \"label\": \"Decycle\"\n                },\n                {\n                    \"value\": \"debounce\",\n                    \"label\": \"Debounce\"\n                },\n                {\n                    \"value\": \"delastic\",\n                    \"label\": \"Delastic\"\n                }\n            ]\n        }\n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 50 - 25;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 220) {\\n\\tvalue = 220;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":180,\"startAngle\":45,\"ticksAngle\":270,\"showBorder\":false,\"defaultColor\":\"#e65100\",\"needleCircleSize\":7,\"highlights\":[{\"from\":80,\"to\":120,\"color\":\"#fdd835\"},{\"color\":\"#e57373\",\"from\":120,\"to\":180}],\"showUnitTitle\":false,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":2,\"valueInt\":3,\"minValue\":0,\"valueDec\":0,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":1500,\"animationRule\":\"linear\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"colorNeedleShadowDown\":\"rgba(188, 143, 143, 0.78)\",\"units\":\"MPH\",\"majorTicksCount\":9,\"numbersFont\":{\"family\":\"RobotoDraft\",\"size\":22,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"titleFont\":{\"family\":\"RobotoDraft\",\"size\":24,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#888\"},\"unitsFont\":{\"family\":\"RobotoDraft\",\"size\":28,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"size\":32,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\",\"family\":\"Segment7Standard\"},\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\"},\"title\":\"Speed gauge - Canvas Gauges\"}"}',
 'Speed gauge - Canvas Gauges' );
diff --git a/ui/src/app/api/widget.service.js b/ui/src/app/api/widget.service.js
index 23375cb..cde32f0 100644
--- a/ui/src/app/api/widget.service.js
+++ b/ui/src/app/api/widget.service.js
@@ -46,6 +46,7 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, typ
     $window.TbAnalogueRadialGauge = TbAnalogueRadialGauge;
     $window.TbDigitalGauge = TbDigitalGauge;
     $window.TbMapWidget = TbMapWidget;
+    $window.cssjs = cssjs;
 
     var cssParser = new cssjs();
     cssParser.testMode = false;
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index 71bc886..5314038 100644
--- a/ui/src/app/common/types.constant.js
+++ b/ui/src/app/common/types.constant.js
@@ -141,6 +141,14 @@ export default angular.module('thingsboard.types', [])
                         bundleAlias: "gpio_widgets",
                         alias: "basic_gpio_control"
                     }
+                },
+                static: {
+                    value: "static",
+                    name: "widget.static",
+                    template: {
+                        bundleAlias: "cards",
+                        alias: "html_card"
+                    }
                 }
             },
             systemBundleAlias: {
diff --git a/ui/src/app/components/dashboard.directive.js b/ui/src/app/components/dashboard.directive.js
index 4fc8599..0e89a01 100644
--- a/ui/src/app/components/dashboard.directive.js
+++ b/ui/src/app/components/dashboard.directive.js
@@ -139,6 +139,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $log, toast
     vm.widgetBackgroundColor = widgetBackgroundColor;
     vm.widgetPadding = widgetPadding;
     vm.showWidgetTitle = showWidgetTitle;
+    vm.dropWidgetShadow = dropWidgetShadow;
     vm.hasTimewindow = hasTimewindow;
     vm.editWidget = editWidget;
     vm.exportWidget = exportWidget;
@@ -521,6 +522,14 @@ function DashboardController($scope, $rootScope, $element, $timeout, $log, toast
         }
     }
 
+    function dropWidgetShadow(widget) {
+        if (angular.isDefined(widget.config.dropShadow)) {
+            return widget.config.dropShadow;
+        } else {
+            return true;
+        }
+    }
+
     function hasTimewindow(widget) {
         return widget.type === types.widgetType.timeseries.value;
     }
diff --git a/ui/src/app/components/dashboard.tpl.html b/ui/src/app/components/dashboard.tpl.html
index 111f0d3..cac3d7f 100644
--- a/ui/src/app/components/dashboard.tpl.html
+++ b/ui/src/app/components/dashboard.tpl.html
@@ -28,8 +28,10 @@
 					<li gridster-item="widget" ng-repeat="widget in vm.widgets">
 						<md-menu md-position-mode="target target" tb-mousepoint-menu>
 							<div tb-expand-fullscreen
-								        expand-button-id="expand-button" on-fullscreen-changed="vm.onWidgetFullscreenChanged(expanded, widget)" layout="column" class="tb-widget md-whiteframe-4dp"
-										ng-class="{'tb-highlighted': vm.isHighlighted(widget), 'tb-not-highlighted': vm.isNotHighlighted(widget)}"
+								        expand-button-id="expand-button" on-fullscreen-changed="vm.onWidgetFullscreenChanged(expanded, widget)" layout="column" class="tb-widget"
+										ng-class="{'tb-highlighted': vm.isHighlighted(widget),
+										           'tb-not-highlighted': vm.isNotHighlighted(widget),
+										           'md-whiteframe-4dp': vm.dropWidgetShadow(widget)}"
 										tb-mousedown="vm.widgetMouseDown($event, widget)"
 										tb-mousemove="vm.widgetMouseMove($event, widget)"
 										tb-mouseup="vm.widgetMouseUp($event, widget)"
diff --git a/ui/src/app/components/react/json-form-css.jsx b/ui/src/app/components/react/json-form-css.jsx
new file mode 100644
index 0000000..9c5dcc6
--- /dev/null
+++ b/ui/src/app/components/react/json-form-css.jsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react';
+import ThingsboardAceEditor from './json-form-ace-editor.jsx';
+import 'brace/mode/css';
+import beautify from 'js-beautify';
+
+const css_beautify = beautify.css;
+
+class ThingsboardCss extends React.Component {
+
+    constructor(props) {
+        super(props);
+        this.onTidyCss = this.onTidyCss.bind(this);
+    }
+
+    onTidyCss(css) {
+        return css_beautify(css, {indent_size: 4});
+    }
+
+    render() {
+        return (
+            <ThingsboardAceEditor {...this.props} mode='css' onTidy={this.onTidyCss} {...this.state}></ThingsboardAceEditor>
+        );
+    }
+}
+
+export default ThingsboardCss;
diff --git a/ui/src/app/components/react/json-form-html.jsx b/ui/src/app/components/react/json-form-html.jsx
new file mode 100644
index 0000000..f45952f
--- /dev/null
+++ b/ui/src/app/components/react/json-form-html.jsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react';
+import ThingsboardAceEditor from './json-form-ace-editor.jsx';
+import 'brace/mode/html';
+import beautify from 'js-beautify';
+
+const html_beautify = beautify.html;
+
+class ThingsboardHtml extends React.Component {
+
+    constructor(props) {
+        super(props);
+        this.onTidyHtml = this.onTidyHtml.bind(this);
+    }
+
+    onTidyHtml(html) {
+        return html_beautify(html, {indent_size: 4});
+    }
+
+    render() {
+        return (
+            <ThingsboardAceEditor {...this.props} mode='html' onTidy={this.onTidyHtml} {...this.state}></ThingsboardAceEditor>
+        );
+    }
+}
+
+export default ThingsboardHtml;
diff --git a/ui/src/app/components/react/json-form-schema-form.jsx b/ui/src/app/components/react/json-form-schema-form.jsx
index 734ae12..d708d53 100644
--- a/ui/src/app/components/react/json-form-schema-form.jsx
+++ b/ui/src/app/components/react/json-form-schema-form.jsx
@@ -19,6 +19,8 @@ import { utils } from 'react-schema-form';
 import ThingsboardArray from './json-form-array.jsx';
 import ThingsboardJavaScript from './json-form-javascript.jsx';
 import ThingsboardJson from './json-form-json.jsx';
+import ThingsboardHtml from './json-form-html.jsx';
+import ThingsboardCss from './json-form-css.jsx';
 import ThingsboardColor from './json-form-color.jsx'
 import ThingsboardRcSelect from './json-form-rc-select.jsx';
 import ThingsboardNumber from './json-form-number.jsx';
@@ -52,6 +54,8 @@ class ThingsboardSchemaForm extends React.Component {
             'array': ThingsboardArray,
             'javascript': ThingsboardJavaScript,
             'json': ThingsboardJson,
+            'html': ThingsboardHtml,
+            'css': ThingsboardCss,
             'color': ThingsboardColor,
             'rc-select': ThingsboardRcSelect,
             'fieldset': ThingsboardFieldSet
diff --git a/ui/src/app/components/widget-config.directive.js b/ui/src/app/components/widget-config.directive.js
index da12a49..775000a 100644
--- a/ui/src/app/components/widget-config.directive.js
+++ b/ui/src/app/components/widget-config.directive.js
@@ -74,11 +74,12 @@ function WidgetConfig($compile, $templateCache, $rootScope, types, utils) {
                 scope.selectedTab = 0;
                 scope.title = ngModelCtrl.$viewValue.title;
                 scope.showTitle = ngModelCtrl.$viewValue.showTitle;
+                scope.dropShadow = angular.isDefined(ngModelCtrl.$viewValue.dropShadow) ? ngModelCtrl.$viewValue.dropShadow : true;
                 scope.backgroundColor = ngModelCtrl.$viewValue.backgroundColor;
                 scope.color = ngModelCtrl.$viewValue.color;
                 scope.padding = ngModelCtrl.$viewValue.padding;
                 scope.timewindow = ngModelCtrl.$viewValue.timewindow;
-                if (scope.widgetType !== types.widgetType.rpc.value) {
+                if (scope.widgetType !== types.widgetType.rpc.value && scope.widgetType !== types.widgetType.static.value) {
                     if (scope.datasources) {
                         scope.datasources.splice(0, scope.datasources.length);
                     } else {
@@ -89,7 +90,7 @@ function WidgetConfig($compile, $templateCache, $rootScope, types, utils) {
                             scope.datasources.push({value: ngModelCtrl.$viewValue.datasources[i]});
                         }
                     }
-                } else {
+                } else if (scope.widgetType === types.widgetType.rpc.value) {
                     if (ngModelCtrl.$viewValue.targetDeviceAliasIds && ngModelCtrl.$viewValue.targetDeviceAliasIds.length > 0) {
                         var aliasId = ngModelCtrl.$viewValue.targetDeviceAliasIds[0];
                         if (scope.deviceAliases[aliasId]) {
@@ -140,18 +141,19 @@ function WidgetConfig($compile, $templateCache, $rootScope, types, utils) {
                 if (scope.widgetType === types.widgetType.rpc.value) {
                     valid = value && value.targetDeviceAliasIds && value.targetDeviceAliasIds.length > 0;
                     ngModelCtrl.$setValidity('targetDeviceAliasIds', valid);
-                } else {
+                } else if (scope.widgetType !== types.widgetType.static.value) {
                     valid = value && value.datasources && value.datasources.length > 0;
                     ngModelCtrl.$setValidity('datasources', valid);
                 }
             }
         };
 
-        scope.$watch('title + showTitle + backgroundColor + color + padding + intervalSec', function () {
+        scope.$watch('title + showTitle + dropShadow + backgroundColor + color + padding + intervalSec', function () {
             if (ngModelCtrl.$viewValue) {
                 var value = ngModelCtrl.$viewValue;
                 value.title = scope.title;
                 value.showTitle = scope.showTitle;
+                value.dropShadow = scope.dropShadow;
                 value.backgroundColor = scope.backgroundColor;
                 value.color = scope.color;
                 value.padding = scope.padding;
@@ -177,7 +179,8 @@ function WidgetConfig($compile, $templateCache, $rootScope, types, utils) {
         }, true);
 
         scope.$watch('datasources', function () {
-            if (ngModelCtrl.$viewValue && scope.widgetType !== types.widgetType.rpc.value) {
+            if (ngModelCtrl.$viewValue && scope.widgetType !== types.widgetType.rpc.value
+                && scope.widgetType !== types.widgetType.static.value) {
                 var value = ngModelCtrl.$viewValue;
                 if (value.datasources) {
                     value.datasources.splice(0, value.datasources.length);
@@ -235,7 +238,8 @@ function WidgetConfig($compile, $templateCache, $rootScope, types, utils) {
         };
 
         scope.updateDatasourcesAccordionState = function () {
-            if (scope.widgetType !== types.widgetType.rpc.value) {
+            if (scope.widgetType !== types.widgetType.rpc.value &&
+                scope.widgetType !== types.widgetType.static.value) {
                 if (scope.datasourcesAccordion) {
                     scope.updateDatasourcesAccordionStatePending = false;
                     var expand = scope.datasources && scope.datasources.length < 4;
diff --git a/ui/src/app/components/widget-config.tpl.html b/ui/src/app/components/widget-config.tpl.html
index d988677..87b3afd 100644
--- a/ui/src/app/components/widget-config.tpl.html
+++ b/ui/src/app/components/widget-config.tpl.html
@@ -31,6 +31,11 @@
                                      ng-model="showTitle">{{ 'widget-config.display-title' | translate }}
                         </md-checkbox>
                     </div>
+                    <div layout="row" layout-padding>
+                        <md-checkbox flex aria-label="{{ 'widget-config.drop-shadow' | translate }}"
+                                     ng-model="dropShadow">{{ 'widget-config.drop-shadow' | translate }}
+                        </md-checkbox>
+                    </div>
                     <div flex
                          md-color-picker
                          ng-model="backgroundColor"
@@ -64,7 +69,7 @@
                     <tb-timewindow as-button="true" flex ng-model="timewindow"></tb-timewindow>
                 </div>
                 <v-accordion id="datasources-accordion" control="datasourcesAccordion" class="vAccordion--default"
-                             ng-show="widgetType !== types.widgetType.rpc.value">
+                             ng-show="widgetType !== types.widgetType.rpc.value && widgetType !== types.widgetType.static.value">
                     <v-pane id="datasources-pane" expanded="forceExpandDatasources">
                         <v-pane-header>
                             {{ 'widget-config.datasources' | translate }}
diff --git a/ui/src/app/dashboard/add-widget.controller.js b/ui/src/app/dashboard/add-widget.controller.js
index 02b4e31..2599085 100644
--- a/ui/src/app/dashboard/add-widget.controller.js
+++ b/ui/src/app/dashboard/add-widget.controller.js
@@ -66,6 +66,10 @@ export default function AddWidgetController($scope, widgetService, deviceService
                     link = 'widgetsConfigRpc';
                     break;
                 }
+                case types.widgetType.static.value: {
+                    link = 'widgetsConfigStatic';
+                    break;
+                }
             }
         }
         return link;
diff --git a/ui/src/app/dashboard/dashboard.controller.js b/ui/src/app/dashboard/dashboard.controller.js
index 018bda4..3b5d819 100644
--- a/ui/src/app/dashboard/dashboard.controller.js
+++ b/ui/src/app/dashboard/dashboard.controller.js
@@ -41,6 +41,7 @@ export default function DashboardController(types, widgetService, userService,
     vm.latestWidgetTypes = [];
     vm.timeseriesWidgetTypes = [];
     vm.rpcWidgetTypes = [];
+    vm.staticWidgetTypes = [];
     vm.widgetEditMode = $state.$current.data.widgetEditMode;
     vm.widgets = [];
 
@@ -82,6 +83,7 @@ export default function DashboardController(types, widgetService, userService,
         vm.latestWidgetTypes = [];
         vm.timeseriesWidgetTypes = [];
         vm.rpcWidgetTypes = [];
+        vm.staticWidgetTypes = [];
         if (vm.widgetsBundle) {
             var bundleAlias = vm.widgetsBundle.alias;
             var isSystem = vm.widgetsBundle.tenantId.id === types.id.nullUid;
@@ -127,6 +129,8 @@ export default function DashboardController(types, widgetService, userService,
                             vm.latestWidgetTypes.push(widget);
                         } else if (widgetTypeInfo.type === types.widgetType.rpc.value) {
                             vm.rpcWidgetTypes.push(widget);
+                        } else if (widgetTypeInfo.type === types.widgetType.static.value) {
+                            vm.staticWidgetTypes.push(widget);
                         }
                         top += sizeY;
                         loadNextOrComplete(i);
@@ -442,6 +446,10 @@ export default function DashboardController(types, widgetService, userService,
                     link = 'widgetsConfigRpc';
                     break;
                 }
+                case types.widgetType.static.value: {
+                    link = 'widgetsConfigStatic';
+                    break;
+                }
             }
         }
         return link;
@@ -490,6 +498,7 @@ export default function DashboardController(types, widgetService, userService,
         vm.timeseriesWidgetTypes = [];
         vm.latestWidgetTypes = [];
         vm.rpcWidgetTypes = [];
+        vm.staticWidgetTypes = [];
     }
 
     function addWidgetFromType(event, widget) {
diff --git a/ui/src/app/dashboard/dashboard.tpl.html b/ui/src/app/dashboard/dashboard.tpl.html
index 109c10a..99f9c60 100644
--- a/ui/src/app/dashboard/dashboard.tpl.html
+++ b/ui/src/app/dashboard/dashboard.tpl.html
@@ -136,7 +136,7 @@
         </header-pane>
         <div>
             <md-tabs ng-if="vm.timeseriesWidgetTypes.length > 0 || vm.latestWidgetTypes.length > 0 ||
-                            vm.rpcWidgetTypes.length > 0"
+                            vm.rpcWidgetTypes.length > 0 || vm.staticWidgetTypes.length > 0"
                      flex
                      class="tb-absolute-fill" md-border-bottom>
                 <md-tab ng-if="vm.timeseriesWidgetTypes.length > 0" style="height: 100%;" label="{{ 'widget.timeseries' | translate }}">
@@ -169,9 +169,19 @@
                             on-widget-clicked="vm.addWidgetFromType(event, widget)">
                     </tb-dashboard>
                 </md-tab>
+                <md-tab ng-if="vm.staticWidgetTypes.length > 0" style="height: 100%;" label="{{ 'widget.static' | translate }}">
+                    <tb-dashboard
+                            widgets="vm.staticWidgetTypes"
+                            is-edit="false"
+                            is-mobile="true"
+                            is-edit-action-enabled="false"
+                            is-remove-action-enabled="false"
+                            on-widget-clicked="vm.addWidgetFromType(event, widget)">
+                    </tb-dashboard>
+                </md-tab>
             </md-tabs>
             <span translate ng-if="vm.timeseriesWidgetTypes.length === 0 && vm.latestWidgetTypes.length === 0 &&
-                                   vm.rpcWidgetTypes.length === 0 && vm.widgetsBundle"
+                                   vm.rpcWidgetTypes.length === 0 && vm.staticWidgetTypes.length === 0 && vm.widgetsBundle"
                   layout-align="center center"
                   style="text-transform: uppercase; display: flex;"
                   class="md-headline tb-absolute-fill">widgets-bundle.empty</span>
diff --git a/ui/src/app/device/attribute/attribute-table.directive.js b/ui/src/app/device/attribute/attribute-table.directive.js
index 63794dc..bec99ea 100644
--- a/ui/src/app/device/attribute/attribute-table.directive.js
+++ b/ui/src/app/device/attribute/attribute-table.directive.js
@@ -305,31 +305,33 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS
                                 for (var i = 0; i < widgetTypes.length; i++) {
                                     var widgetType = widgetTypes[i];
                                     var widgetInfo = widgetService.toWidgetInfo(widgetType);
-                                    var sizeX = widgetInfo.sizeX*2;
-                                    var sizeY = widgetInfo.sizeY*2;
-                                    var col = Math.floor(Math.max(0, (20 - sizeX)/2));
-                                    var widget = {
-                                        isSystemType: isSystem,
-                                        bundleAlias: bundleAlias,
-                                        typeAlias: widgetInfo.alias,
-                                        type: widgetInfo.type,
-                                        title: widgetInfo.widgetName,
-                                        sizeX: sizeX,
-                                        sizeY: sizeY,
-                                        row: 0,
-                                        col: col,
-                                        config: angular.fromJson(widgetInfo.defaultConfig)
-                                    };
-
-                                    widget.config.title = widgetInfo.widgetName;
-                                    widget.config.datasources = [datasource];
-                                    var length;
-                                    if (scope.attributeScope === types.latestTelemetry && widgetInfo.type !== types.widgetType.rpc.value) {
-                                        length = scope.widgetsListCache.push([widget]);
-                                        scope.widgetsList.push(length === 1 ? [widget] : []);
-                                    } else if (widgetInfo.type === types.widgetType.latest.value) {
-                                        length = scope.widgetsListCache.push([widget]);
-                                        scope.widgetsList.push(length === 1 ? [widget] : []);
+                                    if (widgetInfo.type !== types.widgetType.static.value) {
+                                        var sizeX = widgetInfo.sizeX * 2;
+                                        var sizeY = widgetInfo.sizeY * 2;
+                                        var col = Math.floor(Math.max(0, (20 - sizeX) / 2));
+                                        var widget = {
+                                            isSystemType: isSystem,
+                                            bundleAlias: bundleAlias,
+                                            typeAlias: widgetInfo.alias,
+                                            type: widgetInfo.type,
+                                            title: widgetInfo.widgetName,
+                                            sizeX: sizeX,
+                                            sizeY: sizeY,
+                                            row: 0,
+                                            col: col,
+                                            config: angular.fromJson(widgetInfo.defaultConfig)
+                                        };
+
+                                        widget.config.title = widgetInfo.widgetName;
+                                        widget.config.datasources = [datasource];
+                                        var length;
+                                        if (scope.attributeScope === types.latestTelemetry && widgetInfo.type !== types.widgetType.rpc.value) {
+                                            length = scope.widgetsListCache.push([widget]);
+                                            scope.widgetsList.push(length === 1 ? [widget] : []);
+                                        } else if (widgetInfo.type === types.widgetType.latest.value) {
+                                            length = scope.widgetsListCache.push([widget]);
+                                            scope.widgetsList.push(length === 1 ? [widget] : []);
+                                        }
                                     }
                                 }
                                 scope.widgetsLoaded = true;
diff --git a/ui/src/app/help/help-links.constant.js b/ui/src/app/help/help-links.constant.js
index 0ce0395..62d6c2d 100644
--- a/ui/src/app/help/help-links.constant.js
+++ b/ui/src/app/help/help-links.constant.js
@@ -45,7 +45,7 @@ var pluginActionsClazzHelpLinkMap = {
     'org.thingsboard.server.extensions.rest.action.RestApiCallPluginAction': 'pluginActionRestApiCall'
 };
 
-var helpBaseUrl = "http://thingsboard.io";
+var helpBaseUrl = "https://thingsboard.io";
 
 export default angular.module('thingsboard.help', [])
     .constant('helpLinks',
@@ -86,6 +86,7 @@ export default angular.module('thingsboard.help', [])
                 widgetsConfigTimeseries:  helpBaseUrl + "/docs/user-guide/ui/dashboards#timeseries",
                 widgetsConfigLatest: helpBaseUrl +  "/docs/user-guide/ui/dashboards#latest",
                 widgetsConfigRpc: helpBaseUrl +  "/docs/user-guide/ui/dashboards#rpc",
+                widgetsConfigStatic: helpBaseUrl +  "/docs/user-guide/ui/dashboards#static",
             },
             getPluginLink: function(plugin) {
                 var link = 'plugins';
diff --git a/ui/src/app/widget/select-widget-type.tpl.html b/ui/src/app/widget/select-widget-type.tpl.html
index e7ada8b..1b39835 100644
--- a/ui/src/app/widget/select-widget-type.tpl.html
+++ b/ui/src/app/widget/select-widget-type.tpl.html
@@ -53,6 +53,13 @@
                             </md-icon>
                             <span translate>{{vm.types.widgetType.rpc.name}}</span>
                         </md-button>
+                        <md-button class="tb-card-button md-raised md-primary" layout="column"
+                                   ng-click="vm.typeSelected(vm.types.widgetType.static.value)">
+                            <md-icon class="material-icons tb-md-96"
+                                     aria-label="{{ vm.types.widgetType.static.name | translate }}">font_download
+                            </md-icon>
+                            <span translate>{{vm.types.widgetType.static.name}}</span>
+                        </md-button>
                     </div>
                 </fieldset>
             </div>
diff --git a/ui/src/locale/en_US.json b/ui/src/locale/en_US.json
index cf1a97b..d9a761c 100644
--- a/ui/src/locale/en_US.json
+++ b/ui/src/locale/en_US.json
@@ -603,6 +603,7 @@
     "timeseries": "Time series",
     "latest-values": "Latest values",
     "rpc": "Control widget",
+    "static": "Static widget",
     "select-widget-type": "Select widget type",
     "missing-widget-title-error": "Widget title must be specified!",
     "widget-saved": "Widget saved",
@@ -663,6 +664,7 @@
     "title": "Title",
     "general-settings": "General settings",
     "display-title": "Display title",
+    "drop-shadow": "Drop shadow",
     "background-color": "Background color",
     "text-color": "Text color",
     "padding": "Padding",