Commit e32e1883d1f8066bd4732501da3b7922ee217182

Authored by Igor Kulikov
1 parent a87956eb

Api Usage dashboard improvements

... ... @@ -95,7 +95,20 @@
95 95 "decimals": null,
96 96 "funcBody": null,
97 97 "usePostProcessing": true,
98   - "postFuncBody": "return \"JavaScript functions\";"
  98 + "postFuncBody": "return \"JavaScript\";"
  99 + },
  100 + {
  101 + "name": "jsExecutionApiState",
  102 + "type": "timeseries",
  103 + "label": "unit",
  104 + "color": "#8bc34a",
  105 + "settings": {},
  106 + "_hash": 0.7926918686567068,
  107 + "units": null,
  108 + "decimals": null,
  109 + "funcBody": null,
  110 + "usePostProcessing": true,
  111 + "postFuncBody": "return \"Executions\";"
99 112 }
100 113 ]
101 114 }
... ... @@ -110,8 +123,8 @@
110 123 "color": "#666666",
111 124 "padding": "0",
112 125 "settings": {
113   - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 24px;\n font-size: 20px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n",
114   - "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"javascript_functions_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>"
  126 + "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class=\"unit\">${unit}</div>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"javascript_functions_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>",
  127 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n"
115 128 },
116 129 "title": "JavaScript functions",
117 130 "dropShadow": true,
... ... @@ -240,7 +253,20 @@
240 253 "decimals": null,
241 254 "funcBody": null,
242 255 "usePostProcessing": true,
243   - "postFuncBody": "return \"Telemetry persistence\";"
  256 + "postFuncBody": "return \"Telemetry\";"
  257 + },
  258 + {
  259 + "name": "dbApiState",
  260 + "type": "timeseries",
  261 + "label": "unit",
  262 + "color": "#8bc34a",
  263 + "settings": {},
  264 + "_hash": 0.0027742924142306613,
  265 + "units": null,
  266 + "decimals": null,
  267 + "funcBody": null,
  268 + "usePostProcessing": true,
  269 + "postFuncBody": "return \"Data points storage days\";"
244 270 }
245 271 ]
246 272 }
... ... @@ -255,8 +281,8 @@
255 281 "color": "#666666",
256 282 "padding": "0",
257 283 "settings": {
258   - "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"telemetry_persistence_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>",
259   - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 24px;\n font-size: 20px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n"
  284 + "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class=\"unit\">${unit}</div>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"telemetry_persistence_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>",
  285 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n"
260 286 },
261 287 "title": "Telemetry persistence",
262 288 "dropShadow": true,
... ... @@ -385,7 +411,20 @@
385 411 "decimals": null,
386 412 "funcBody": null,
387 413 "usePostProcessing": true,
388   - "postFuncBody": "return \"Rule Engine execution\";"
  414 + "postFuncBody": "return \"Rule Engine\";"
  415 + },
  416 + {
  417 + "name": "ruleEngineApiState",
  418 + "type": "timeseries",
  419 + "label": "unit",
  420 + "color": "#8bc34a",
  421 + "settings": {},
  422 + "_hash": 0.5100381746798048,
  423 + "units": null,
  424 + "decimals": null,
  425 + "funcBody": null,
  426 + "usePostProcessing": true,
  427 + "postFuncBody": "return \"Executions\";"
389 428 }
390 429 ]
391 430 }
... ... @@ -400,8 +439,8 @@
400 439 "color": "#666666",
401 440 "padding": "0",
402 441 "settings": {
403   - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 24px;\n font-size: 20px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n",
404   - "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"rule_engine_statistics_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View statistics</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n <button id=\"rule_engine_execution_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>"
  442 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n",
  443 + "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class=\"unit\">${unit}</div>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"rule_engine_statistics_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View statistics</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n <button id=\"rule_engine_execution_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>"
405 444 },
406 445 "title": "Rule Engine execution",
407 446 "dropShadow": true,
... ... @@ -581,8 +620,8 @@
581 620 "color": "#666666",
582 621 "padding": "0",
583 622 "settings": {
584   - "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n var pointsCount = \"${pointsCount:0}\";\n var pointsLimit = \"${pointsLimit:0}\";\n pointsCount = pointsCount.length > 0 ? parseInt(pointsCount, 10) : 0;\n pointsLimit = pointsLimit.length > 0 ? parseInt(pointsLimit, 10) : 0;\n var pointsPercentElement = $('#api-usage-percent2', parentTag);\n var pointsValueElement = $('#api-usage-value2', parentTag);\n var pointsBarElement = $('#api-usage-bar2', parentTag);\n if (Number.isFinite(pointsLimit) && pointsLimit > 0) {\n var percent = Math.min(100, ((pointsCount / pointsLimit) * 100));\n pointsBarElement.width(percent + '%');\n percent = percent.toFixed(2);\n pointsPercentElement.text(percent + '%');\n pointsValueElement.text(toShortNumber(pointsCount) + ' / ' + toShortNumber(pointsLimit));\n } else {\n pointsBarElement.width('0%');\n pointsPercentElement.text('');\n pointsValueElement.text(toShortNumber(pointsCount) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>\n <span>${title}</span>\n </div>\n <div class='state'>${apiState}</div>\n </div>\n <div class=\"bars-row\">\n <div class=\"bar-column\" style=\"margin-right: 10px;\">\n <div class='bar-container'>\n <div>Messages</div>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div>\n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n <div class=\"bar-column\" style=\"margin-left: 10px;\">\n <div class='bar-container'>\n <div>Data points</div>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar2\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent2\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value2\"></div>\n </div>\n </div> \n </div>\n </div>\n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"transport_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>",
585   - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 16px;\n font-size: 14px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n"
  623 + "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n var pointsCount = \"${pointsCount:0}\";\n var pointsLimit = \"${pointsLimit:0}\";\n pointsCount = pointsCount.length > 0 ? parseInt(pointsCount, 10) : 0;\n pointsLimit = pointsLimit.length > 0 ? parseInt(pointsLimit, 10) : 0;\n var pointsPercentElement = $('#api-usage-percent2', parentTag);\n var pointsValueElement = $('#api-usage-value2', parentTag);\n var pointsBarElement = $('#api-usage-bar2', parentTag);\n if (Number.isFinite(pointsLimit) && pointsLimit > 0) {\n var percent = Math.min(100, ((pointsCount / pointsLimit) * 100));\n pointsBarElement.width(percent + '%');\n percent = percent.toFixed(2);\n pointsPercentElement.text(percent + '%');\n pointsValueElement.text(toShortNumber(pointsCount) + ' / ' + toShortNumber(pointsLimit));\n } else {\n pointsBarElement.width('0%');\n pointsPercentElement.text('');\n pointsValueElement.text(toShortNumber(pointsCount) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>\n <span>${title}</span>\n </div>\n <div class='state'>${apiState}</div>\n </div>\n <div class=\"bars-row\">\n <div class=\"bar-column\" style=\"margin-right: 10px;\">\n <div class='bar-container'>\n <div class=\"unit\">Messages</div>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div>\n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n <div class=\"bar-column\" style=\"margin-left: 10px;\">\n <div class='bar-container'>\n <div class=\"unit\">Data points</div>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar2\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent2\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value2\"></div>\n </div>\n </div> \n </div>\n </div>\n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"transport_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>",
  624 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 6px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n"
586 625 },
587 626 "title": "Transport",
588 627 "dropShadow": true,
... ... @@ -711,7 +750,20 @@
711 750 "decimals": null,
712 751 "funcBody": null,
713 752 "usePostProcessing": true,
714   - "postFuncBody": "return \"Email messages\";"
  753 + "postFuncBody": "return \"Email\";"
  754 + },
  755 + {
  756 + "name": "emailApiState",
  757 + "type": "timeseries",
  758 + "label": "unit",
  759 + "color": "#8bc34a",
  760 + "settings": {},
  761 + "_hash": 0.9964061963495883,
  762 + "units": null,
  763 + "decimals": null,
  764 + "funcBody": null,
  765 + "usePostProcessing": true,
  766 + "postFuncBody": "return \"Messages\";"
715 767 }
716 768 ]
717 769 }
... ... @@ -726,8 +778,8 @@
726 778 "color": "#666666",
727 779 "padding": "0",
728 780 "settings": {
729   - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 24px;\n font-size: 20px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n",
730   - "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"email_messages_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>"
  781 + "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class=\"unit\">${unit}</div>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"email_messages_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>",
  782 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n"
731 783 },
732 784 "title": "Email messages",
733 785 "dropShadow": true,
... ... @@ -856,7 +908,20 @@
856 908 "decimals": null,
857 909 "funcBody": null,
858 910 "usePostProcessing": true,
859   - "postFuncBody": "return \"SMS messages\";"
  911 + "postFuncBody": "return \"SMS\";"
  912 + },
  913 + {
  914 + "name": "smsApiState",
  915 + "type": "timeseries",
  916 + "label": "unit",
  917 + "color": "#8bc34a",
  918 + "settings": {},
  919 + "_hash": 0.39363366156190605,
  920 + "units": null,
  921 + "decimals": null,
  922 + "funcBody": null,
  923 + "usePostProcessing": true,
  924 + "postFuncBody": "return \"Messages\";"
860 925 }
861 926 ]
862 927 }
... ... @@ -871,8 +936,8 @@
871 936 "color": "#666666",
872 937 "padding": "0",
873 938 "settings": {
874   - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 24px;\n font-size: 20px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n",
875   - "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"sms_messages_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>"
  939 + "cardHtml": "<div class='card ${apiStateClass}'>\n <img src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" onload=\"initializeCard_${cardId:0}(event);\">\n <script type=\"text/javascript\">\n function initializeCard_${cardId:0}(e) {\n \n function toShortNumber(number) {\n var rounder = Math.pow(10, 1);\n var powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n \n var key = '';\n \n for (var i = 0; i < powers.length; i++) {\n var reduced = number / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = powers[i].key;\n break;\n }\n }\n return number + key;\n }\n \n var imgTag = e.target;\n var parentTag = imgTag.parentNode;\n var count = \"${count:0}\";\n var limit = \"${limit:0}\";\n count = count.length > 0 ? parseInt(count, 10) : 0;\n limit = limit.length > 0 ? parseInt(limit, 10) : 0;\n var percentElement = $('#api-usage-percent', parentTag);\n var valueElement = $('#api-usage-value', parentTag);\n var barElement = $('#api-usage-bar', parentTag);\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n barElement.width(percent + '%');\n percent = percent.toFixed(2);\n percentElement.text(percent + '%');\n valueElement.text(toShortNumber(count) + ' / ' + toShortNumber(limit));\n } else {\n barElement.width('0%');\n percentElement.text('');\n valueElement.text(toShortNumber(count) + ' / unlimited');\n }\n }\n </script>\n <div class='content'>\n <div class='column'>\n <div class='title-row'>\n <div class='title'>${title}</div>\n <div class='state'>${apiState}</div>\n </div> \n <div class='bar-container'>\n <div class=\"unit\">${unit}</div>\n <div class='bar'>\n <div class=\"bar-fill\" id=\"api-usage-bar\"></div>\n </div> \n <div class='bar-labels'>\n <div id=\"api-usage-percent\"></div>\n <div style=\"flex: 1;\"></div>\n <div id=\"api-usage-value\"></div>\n </div>\n </div> \n </div>\n </div>\n <div role=\"separator\" class=\"mat-divider mat-divider-horizontal\" aria-orientation=\"horizontal\"></div>\n <div class='action-row'>\n <button id=\"sms_messages_details\" class=\"mat-focus-indicator mat-button mat-button-base mat-primary\">\n <span class=\"mat-button-wrapper\">View details</span>\n <span class=\"mat-ripple mat-button-ripple\"></span>\n <span class=\"mat-button-focus-overlay\"></span>\n </button>\n </div> \n</div>",
  940 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n"
876 941 },
877 942 "title": "SMS messages",
878 943 "dropShadow": true,
... ... @@ -4352,4 +4417,4 @@
4352 4417 }
4353 4418 },
4354 4419 "name": "Api Usage"
4355   -}
  4420 +}
\ No newline at end of file
... ...