Commit ffdef6425adcc6d2427b27cd6016a02e743acc3c

Authored by Igor Kulikov
Committed by GitHub
2 parents 30bca765 ddfe3858

Merge pull request #3799 from vvlladd28/improvement/api-usage/translation

UI: Added translation for dashboard api usage
... ... @@ -198,7 +198,7 @@ export class WidgetSubscriptionContext {
198 198 export type SubscriptionMessageSeverity = 'info' | 'warn' | 'error' | 'success';
199 199
200 200 export interface SubscriptionMessage {
201   - severity: SubscriptionMessageSeverity,
  201 + severity: SubscriptionMessageSeverity;
202 202 message: string;
203 203 }
204 204
... ...
... ... @@ -90,7 +90,7 @@
90 90 matTooltipPosition="above"
91 91 class="mat-subheading-2 title">
92 92 <mat-icon *ngIf="widget.showTitleIcon" [ngStyle]="widget.titleIconStyle">{{widget.titleIcon}}</mat-icon>
93   - {{widget.title}}
  93 + {{widget.customTranslatedTitle}}
94 94 </span>
95 95 <tb-timewindow *ngIf="widget.hasTimewindow"
96 96 #timewindowComponent
... ...
... ... @@ -54,6 +54,7 @@ import { MatMenuTrigger } from '@angular/material/menu';
54 54 import { SafeStyle } from '@angular/platform-browser';
55 55 import { distinct } from 'rxjs/operators';
56 56 import { ResizeObserver } from '@juggle/resize-observer';
  57 +import { UtilsService } from '@core/services/utils.service';
57 58
58 59 @Component({
59 60 selector: 'tb-dashboard',
... ... @@ -168,6 +169,7 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
168 169 private gridsterResize$: ResizeObserver;
169 170
170 171 constructor(protected store: Store<AppState>,
  172 + public utils: UtilsService,
171 173 private timeService: TimeService,
172 174 private dialogService: DialogService,
173 175 private breakpointObserver: BreakpointObserver,
... ...
... ... @@ -24,6 +24,7 @@ import { guid, isDefined, isEqual, isUndefined } from '@app/core/utils';
24 24 import { IterableDiffer, KeyValueDiffer } from '@angular/core';
25 25 import { IAliasController, IStateController } from '@app/core/api/widget-api.models';
26 26 import { enumerable } from '@shared/decorators/enumerable';
  27 +import { UtilsService } from '@core/services/utils.service';
27 28
28 29 export interface WidgetsData {
29 30 widgets: Array<Widget>;
... ... @@ -56,6 +57,7 @@ export interface DashboardCallbacks {
56 57 }
57 58
58 59 export interface IDashboardComponent {
  60 + utils: UtilsService;
59 61 gridsterOpts: GridsterConfig;
60 62 gridster: GridsterComponent;
61 63 dashboardWidgets: DashboardWidgets;
... ... @@ -295,6 +297,7 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
295 297 margin: string;
296 298
297 299 title: string;
  300 + customTranslatedTitle: string;
298 301 titleTooltip: string;
299 302 showTitle: boolean;
300 303 titleStyle: {[klass: string]: any};
... ... @@ -358,8 +361,10 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
358 361
359 362 this.title = isDefined(this.widgetContext.widgetTitle)
360 363 && this.widgetContext.widgetTitle.length ? this.widgetContext.widgetTitle : this.widget.config.title;
  364 + this.customTranslatedTitle = this.dashboard.utils.customTranslation(this.title, this.title);
361 365 this.titleTooltip = isDefined(this.widgetContext.widgetTitleTooltip)
362 366 && this.widgetContext.widgetTitleTooltip.length ? this.widgetContext.widgetTitleTooltip : this.widget.config.titleTooltip;
  367 + this.titleTooltip = this.dashboard.utils.customTranslation(this.titleTooltip, this.titleTooltip);
363 368 this.showTitle = isDefined(this.widget.config.showTitle) ? this.widget.config.showTitle : true;
364 369 this.titleStyle = this.widget.config.titleStyle ? this.widget.config.titleStyle : {};
365 370
... ...
... ... @@ -95,7 +95,7 @@
95 95 "decimals": null,
96 96 "funcBody": null,
97 97 "usePostProcessing": true,
98   - "postFuncBody": "return \"JavaScript\";"
  98 + "postFuncBody": "return \"{i18n:api-usage.javascript}\";"
99 99 },
100 100 {
101 101 "name": "jsExecutionApiState",
... ... @@ -108,7 +108,7 @@
108 108 "decimals": null,
109 109 "funcBody": null,
110 110 "usePostProcessing": true,
111   - "postFuncBody": "return \"Executions\";"
  111 + "postFuncBody": "return \"{i18n:api-usage.executions}\";"
112 112 }
113 113 ]
114 114 }
... ... @@ -123,8 +123,8 @@
123 123 "color": "#666666",
124 124 "padding": "0",
125 125 "settings": {
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"
  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) + ' / ∞');\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\">{i18n:api-usage.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 > img {\n height: 0;\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"
128 128 },
129 129 "title": "JavaScript functions",
130 130 "dropShadow": true,
... ... @@ -253,7 +253,7 @@
253 253 "decimals": null,
254 254 "funcBody": null,
255 255 "usePostProcessing": true,
256   - "postFuncBody": "return \"Telemetry\";"
  256 + "postFuncBody": "return \"{i18n:api-usage.telemetry}\";"
257 257 },
258 258 {
259 259 "name": "dbApiState",
... ... @@ -266,7 +266,7 @@
266 266 "decimals": null,
267 267 "funcBody": null,
268 268 "usePostProcessing": true,
269   - "postFuncBody": "return \"Data points storage days\";"
  269 + "postFuncBody": "return \"{i18n:api-usage.data-points-storage-days}\";"
270 270 }
271 271 ]
272 272 }
... ... @@ -281,8 +281,8 @@
281 281 "color": "#666666",
282 282 "padding": "0",
283 283 "settings": {
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"
  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) + ' / ∞');\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\">{i18n:api-usage.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 > img {\n height: 0;\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"
286 286 },
287 287 "title": "Telemetry persistence",
288 288 "dropShadow": true,
... ... @@ -411,7 +411,7 @@
411 411 "decimals": null,
412 412 "funcBody": null,
413 413 "usePostProcessing": true,
414   - "postFuncBody": "return \"Rule Engine\";"
  414 + "postFuncBody": "return \"{i18n:api-usage.rule-engine}\";"
415 415 },
416 416 {
417 417 "name": "ruleEngineApiState",
... ... @@ -424,7 +424,7 @@
424 424 "decimals": null,
425 425 "funcBody": null,
426 426 "usePostProcessing": true,
427   - "postFuncBody": "return \"Executions\";"
  427 + "postFuncBody": "return \"{i18n:api-usage.executions}\";"
428 428 }
429 429 ]
430 430 }
... ... @@ -439,8 +439,8 @@
439 439 "color": "#666666",
440 440 "padding": "0",
441 441 "settings": {
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>"
  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 > img {\n height: 0;\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) + ' / ∞');\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\">{i18n:api-usage.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\">{i18n:api-usage.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>"
444 444 },
445 445 "title": "Rule Engine execution",
446 446 "dropShadow": true,
... ... @@ -605,7 +605,7 @@
605 605 "decimals": null,
606 606 "funcBody": null,
607 607 "usePostProcessing": true,
608   - "postFuncBody": "return \"Transport\";"
  608 + "postFuncBody": "return \"{i18n:api-usage.transport}\";"
609 609 }
610 610 ]
611 611 }
... ... @@ -620,8 +620,8 @@
620 620 "color": "#666666",
621 621 "padding": "0",
622 622 "settings": {
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"
  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) + ' / ∞');\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) + ' / ∞');\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\">{i18n:api-usage.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\">{i18n:api-usage.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\">{i18n:api-usage.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 > img {\n height: 0;\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"
625 625 },
626 626 "title": "Transport",
627 627 "dropShadow": true,
... ... @@ -750,7 +750,7 @@
750 750 "decimals": null,
751 751 "funcBody": null,
752 752 "usePostProcessing": true,
753   - "postFuncBody": "return \"Email\";"
  753 + "postFuncBody": "return \"{i18n:api-usage.email}\";"
754 754 },
755 755 {
756 756 "name": "emailApiState",
... ... @@ -763,7 +763,7 @@
763 763 "decimals": null,
764 764 "funcBody": null,
765 765 "usePostProcessing": true,
766   - "postFuncBody": "return \"Messages\";"
  766 + "postFuncBody": "return \"{i18n:api-usage.messages}\";"
767 767 }
768 768 ]
769 769 }
... ... @@ -778,8 +778,8 @@
778 778 "color": "#666666",
779 779 "padding": "0",
780 780 "settings": {
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"
  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) + ' / ∞');\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\">{i18n:api-usage.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 > img {\n height: 0;\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"
783 783 },
784 784 "title": "Email messages",
785 785 "dropShadow": true,
... ... @@ -908,7 +908,7 @@
908 908 "decimals": null,
909 909 "funcBody": null,
910 910 "usePostProcessing": true,
911   - "postFuncBody": "return \"SMS\";"
  911 + "postFuncBody": "return \"{i18n:api-usage.sms}\";"
912 912 },
913 913 {
914 914 "name": "smsApiState",
... ... @@ -921,7 +921,7 @@
921 921 "decimals": null,
922 922 "funcBody": null,
923 923 "usePostProcessing": true,
924   - "postFuncBody": "return \"Messages\";"
  924 + "postFuncBody": "return \"{i18n:api-usage.messages}\";"
925 925 }
926 926 ]
927 927 }
... ... @@ -936,8 +936,8 @@
936 936 "color": "#666666",
937 937 "padding": "0",
938 938 "settings": {
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"
  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) + ' / ∞');\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\">{i18n:api-usage.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 > img {\n height: 0;\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"
941 941 },
942 942 "title": "SMS messages",
943 943 "dropShadow": true,
... ... @@ -993,7 +993,7 @@
993 993 {
994 994 "name": "ruleEngineExecutionCountHourly",
995 995 "type": "timeseries",
996   - "label": "Rule Engine executions",
  996 + "label": "{i18n:api-usage.rule-engine-executions}",
997 997 "color": "#ab00ff",
998 998 "settings": {
999 999 "excludeFromStacking": false,
... ... @@ -1078,7 +1078,7 @@
1078 1078 "showLabels": true
1079 1079 }
1080 1080 },
1081   - "title": "Rule Engine hourly activity",
  1081 + "title": "{i18n:api-usage.rule-engine-hourly-activity}",
1082 1082 "dropShadow": true,
1083 1083 "enableFullscreen": true,
1084 1084 "titleStyle": {
... ... @@ -1091,7 +1091,7 @@
1091 1091 "actions": {
1092 1092 "headerButton": [
1093 1093 {
1094   - "name": "View statistics",
  1094 + "name": "{i18n:api-usage.view-statistics}",
1095 1095 "icon": "show_chart",
1096 1096 "type": "openDashboardState",
1097 1097 "targetDashboardStateId": "rule_engine_statistics",
... ... @@ -1101,7 +1101,7 @@
1101 1101 "id": "f9f08190-9ed9-d802-5b7a-c57ff84b5648"
1102 1102 },
1103 1103 {
1104   - "name": "View details",
  1104 + "name": "{i18n:api-usage.view-details}",
1105 1105 "icon": "insert_chart",
1106 1106 "type": "openDashboardState",
1107 1107 "targetDashboardStateId": "rule_engine_execution",
... ... @@ -1150,7 +1150,7 @@
1150 1150 {
1151 1151 "name": "transportMsgCountHourly",
1152 1152 "type": "timeseries",
1153   - "label": "Transport messages",
  1153 + "label": "{i18n:api-usage.transport-messages}",
1154 1154 "color": "#2196f3",
1155 1155 "settings": {
1156 1156 "excludeFromStacking": false,
... ... @@ -1185,7 +1185,7 @@
1185 1185 {
1186 1186 "name": "transportDataPointsCountHourly",
1187 1187 "type": "timeseries",
1188   - "label": "Transport data points",
  1188 + "label": "{i18n:api-usage.transport-data-points}",
1189 1189 "color": "#4caf50",
1190 1190 "settings": {
1191 1191 "excludeFromStacking": false,
... ... @@ -1271,7 +1271,7 @@
1271 1271 },
1272 1272 "tooltipCumulative": false
1273 1273 },
1274   - "title": "Transport hourly activity",
  1274 + "title": "{i18n:api-usage.transport-hourly-activity}",
1275 1275 "dropShadow": true,
1276 1276 "enableFullscreen": true,
1277 1277 "titleStyle": {
... ... @@ -1284,7 +1284,7 @@
1284 1284 "actions": {
1285 1285 "headerButton": [
1286 1286 {
1287   - "name": "View details",
  1287 + "name": "{i18n:api-usage.view-details}",
1288 1288 "icon": "insert_chart",
1289 1289 "type": "openDashboardState",
1290 1290 "targetDashboardStateId": "transport",
... ... @@ -1333,7 +1333,7 @@
1333 1333 {
1334 1334 "name": "jsExecutionCountHourly",
1335 1335 "type": "timeseries",
1336   - "label": "JavaScript executions",
  1336 + "label": "{i18n:api-usage.javascript-executions}",
1337 1337 "color": "#ff9900",
1338 1338 "settings": {
1339 1339 "excludeFromStacking": false,
... ... @@ -1418,7 +1418,7 @@
1418 1418 "showLabels": true
1419 1419 }
1420 1420 },
1421   - "title": "JavaScript functions hourly activity",
  1421 + "title": "{i18n:api-usage.javascript-functions-hourly-activity}",
1422 1422 "dropShadow": true,
1423 1423 "enableFullscreen": true,
1424 1424 "titleStyle": {
... ... @@ -1431,7 +1431,7 @@
1431 1431 "actions": {
1432 1432 "headerButton": [
1433 1433 {
1434   - "name": "View details",
  1434 + "name": "{i18n:api-usage.view-details}",
1435 1435 "icon": "insert_chart",
1436 1436 "type": "openDashboardState",
1437 1437 "targetDashboardStateId": "javascript_functions",
... ... @@ -1480,7 +1480,7 @@
1480 1480 {
1481 1481 "name": "storageDataPointsCountHourly",
1482 1482 "type": "timeseries",
1483   - "label": "Data points storage days",
  1483 + "label": "{i18n:api-usage.data-points-storage-days}",
1484 1484 "color": "#1039ee",
1485 1485 "settings": {
1486 1486 "excludeFromStacking": false,
... ... @@ -1565,7 +1565,7 @@
1565 1565 "showLabels": true
1566 1566 }
1567 1567 },
1568   - "title": "Telemetry persistence hourly activity",
  1568 + "title": "{i18n:api-usage.telemetry-persistence-hourly-activity}",
1569 1569 "dropShadow": true,
1570 1570 "enableFullscreen": true,
1571 1571 "titleStyle": {
... ... @@ -1578,7 +1578,7 @@
1578 1578 "actions": {
1579 1579 "headerButton": [
1580 1580 {
1581   - "name": "View details",
  1581 + "name": "{i18n:api-usage.view-details}",
1582 1582 "icon": "insert_chart",
1583 1583 "type": "openDashboardState",
1584 1584 "targetDashboardStateId": "telemetry_persistence",
... ... @@ -1627,7 +1627,7 @@
1627 1627 {
1628 1628 "name": "emailCountHourly",
1629 1629 "type": "timeseries",
1630   - "label": "Email messages",
  1630 + "label": "{i18n:api-usage.email-messages}",
1631 1631 "color": "#d35a00",
1632 1632 "settings": {
1633 1633 "excludeFromStacking": false,
... ... @@ -1712,7 +1712,7 @@
1712 1712 "showLabels": true
1713 1713 }
1714 1714 },
1715   - "title": "Email messages hourly activity",
  1715 + "title": "{i18n:api-usage.email-messages-hourly-activity}",
1716 1716 "dropShadow": true,
1717 1717 "enableFullscreen": true,
1718 1718 "titleStyle": {
... ... @@ -1725,7 +1725,7 @@
1725 1725 "actions": {
1726 1726 "headerButton": [
1727 1727 {
1728   - "name": "View details",
  1728 + "name": "{i18n:api-usage.view-details}",
1729 1729 "icon": "insert_chart",
1730 1730 "type": "openDashboardState",
1731 1731 "targetDashboardStateId": "email_messages",
... ... @@ -1774,7 +1774,7 @@
1774 1774 {
1775 1775 "name": "smsCountHourly",
1776 1776 "type": "timeseries",
1777   - "label": "SMS messages",
  1777 + "label": "{i18n:api-usage.sms-messages}",
1778 1778 "color": "#f36021",
1779 1779 "settings": {
1780 1780 "excludeFromStacking": false,
... ... @@ -1859,7 +1859,7 @@
1859 1859 "showLabels": true
1860 1860 }
1861 1861 },
1862   - "title": "SMS messages hourly activity",
  1862 + "title": "{i18n:api-usage.sms-messages-hourly-activity}",
1863 1863 "dropShadow": true,
1864 1864 "enableFullscreen": true,
1865 1865 "titleStyle": {
... ... @@ -1872,7 +1872,7 @@
1872 1872 "actions": {
1873 1873 "headerButton": [
1874 1874 {
1875   - "name": "View details",
  1875 + "name": "{i18n:api-usage.view-details}",
1876 1876 "icon": "insert_chart",
1877 1877 "type": "openDashboardState",
1878 1878 "targetDashboardStateId": "sms_messages",
... ... @@ -1921,7 +1921,7 @@
1921 1921 {
1922 1922 "name": "ruleEngineExecutionCountHourly",
1923 1923 "type": "timeseries",
1924   - "label": "Rule Engine executions",
  1924 + "label": "{i18n:api-usage.rule-engine-executions}",
1925 1925 "color": "#ab00ff",
1926 1926 "settings": {
1927 1927 "excludeFromStacking": false,
... ... @@ -2007,7 +2007,7 @@
2007 2007 "showLabels": true
2008 2008 }
2009 2009 },
2010   - "title": "Rule Engine daily activity",
  2010 + "title": "{i18n:api-usage.rule-engine-daily-activity}",
2011 2011 "dropShadow": true,
2012 2012 "enableFullscreen": true,
2013 2013 "titleStyle": {
... ... @@ -2056,7 +2056,7 @@
2056 2056 {
2057 2057 "name": "ruleEngineExecutionCount",
2058 2058 "type": "timeseries",
2059   - "label": "Rule Engine executions",
  2059 + "label": "{i18n:api-usage.rule-engine-executions}",
2060 2060 "color": "#ab00ff",
2061 2061 "settings": {
2062 2062 "excludeFromStacking": false,
... ... @@ -2142,7 +2142,7 @@
2142 2142 "showLabels": true
2143 2143 }
2144 2144 },
2145   - "title": "Rule Engine monthly activity",
  2145 + "title": "{i18n:api-usage.rule-engine-monthly-activity}",
2146 2146 "dropShadow": true,
2147 2147 "enableFullscreen": true,
2148 2148 "titleStyle": {
... ... @@ -2191,7 +2191,7 @@
2191 2191 {
2192 2192 "name": "jsExecutionCountHourly",
2193 2193 "type": "timeseries",
2194   - "label": "JavaScript executions",
  2194 + "label": "{i18n:api-usage.javascript-executions}",
2195 2195 "color": "#ff9900",
2196 2196 "settings": {
2197 2197 "excludeFromStacking": false,
... ... @@ -2277,7 +2277,7 @@
2277 2277 "showLabels": true
2278 2278 }
2279 2279 },
2280   - "title": "JavaScript functions daily activity",
  2280 + "title": "{i18n:api-usage.javascript-functions-daily-activity}",
2281 2281 "dropShadow": true,
2282 2282 "enableFullscreen": true,
2283 2283 "titleStyle": {
... ... @@ -2326,7 +2326,7 @@
2326 2326 {
2327 2327 "name": "jsExecutionCount",
2328 2328 "type": "timeseries",
2329   - "label": "JavaScript executions",
  2329 + "label": "{i18n:api-usage.javascript-executions}",
2330 2330 "color": "#ff9900",
2331 2331 "settings": {
2332 2332 "excludeFromStacking": false,
... ... @@ -2412,7 +2412,7 @@
2412 2412 "showLabels": true
2413 2413 }
2414 2414 },
2415   - "title": "JavaScript functions monthly activity",
  2415 + "title": "{i18n:api-usage.javascript-functions-monthly-activity}",
2416 2416 "dropShadow": true,
2417 2417 "enableFullscreen": true,
2418 2418 "titleStyle": {
... ... @@ -2461,7 +2461,7 @@
2461 2461 {
2462 2462 "name": "transportMsgCountHourly",
2463 2463 "type": "timeseries",
2464   - "label": "Transport messages",
  2464 + "label": "{i18n:api-usage.transport-messages}",
2465 2465 "color": "#2196f3",
2466 2466 "settings": {
2467 2467 "excludeFromStacking": false,
... ... @@ -2496,7 +2496,7 @@
2496 2496 {
2497 2497 "name": "transportDataPointsCountHourly",
2498 2498 "type": "timeseries",
2499   - "label": "Transport data points",
  2499 + "label": "{i18n:api-usage.transport-data-points}",
2500 2500 "color": "#4caf50",
2501 2501 "settings": {
2502 2502 "excludeFromStacking": false,
... ... @@ -2583,7 +2583,7 @@
2583 2583 },
2584 2584 "tooltipCumulative": false
2585 2585 },
2586   - "title": "Transport daily activity",
  2586 + "title": "{i18n:api-usage.transport-daily-activity}",
2587 2587 "dropShadow": true,
2588 2588 "enableFullscreen": true,
2589 2589 "titleStyle": {
... ... @@ -2632,7 +2632,7 @@
2632 2632 {
2633 2633 "name": "transportMsgCount",
2634 2634 "type": "timeseries",
2635   - "label": "Transport messages",
  2635 + "label": "{i18n:api-usage.transport-messages}",
2636 2636 "color": "#2196f3",
2637 2637 "settings": {
2638 2638 "excludeFromStacking": false,
... ... @@ -2667,7 +2667,7 @@
2667 2667 {
2668 2668 "name": "transportDataPointsCount",
2669 2669 "type": "timeseries",
2670   - "label": "Transport data points",
  2670 + "label": "{i18n:api-usage.transport-data-points}",
2671 2671 "color": "#4caf50",
2672 2672 "settings": {
2673 2673 "excludeFromStacking": false,
... ... @@ -2754,7 +2754,7 @@
2754 2754 },
2755 2755 "tooltipCumulative": false
2756 2756 },
2757   - "title": "Transport monthly activity",
  2757 + "title": "{i18n:api-usage.transport-monthly-activity}",
2758 2758 "dropShadow": true,
2759 2759 "enableFullscreen": true,
2760 2760 "titleStyle": {
... ... @@ -2803,7 +2803,7 @@
2803 2803 {
2804 2804 "name": "storageDataPointsCountHourly",
2805 2805 "type": "timeseries",
2806   - "label": "Data points storage days",
  2806 + "label": "{i18n:api-usage.data-points-storage-days}",
2807 2807 "color": "#1039ee",
2808 2808 "settings": {
2809 2809 "excludeFromStacking": false,
... ... @@ -2889,7 +2889,7 @@
2889 2889 "showLabels": true
2890 2890 }
2891 2891 },
2892   - "title": "Telemetry persistence daily activity",
  2892 + "title": "{i18n:api-usage.telemetry-persistence-daily-activity}",
2893 2893 "dropShadow": true,
2894 2894 "enableFullscreen": true,
2895 2895 "titleStyle": {
... ... @@ -2938,7 +2938,7 @@
2938 2938 {
2939 2939 "name": "storageDataPointsCount",
2940 2940 "type": "timeseries",
2941   - "label": "Data points storage days",
  2941 + "label": "{i18n:api-usage.data-points-storage-days}",
2942 2942 "color": "#1039ee",
2943 2943 "settings": {
2944 2944 "excludeFromStacking": false,
... ... @@ -3024,7 +3024,7 @@
3024 3024 "showLabels": true
3025 3025 }
3026 3026 },
3027   - "title": "Telemetry persistence monthly activity",
  3027 + "title": "{i18n:api-usage.telemetry-persistence-monthly-activity}",
3028 3028 "dropShadow": true,
3029 3029 "enableFullscreen": true,
3030 3030 "titleStyle": {
... ... @@ -3073,7 +3073,7 @@
3073 3073 {
3074 3074 "name": "emailCountHourly",
3075 3075 "type": "timeseries",
3076   - "label": "Email messages",
  3076 + "label": "{i18n:api-usage.email-messages}",
3077 3077 "color": "#d35a00",
3078 3078 "settings": {
3079 3079 "excludeFromStacking": false,
... ... @@ -3159,7 +3159,7 @@
3159 3159 "showLabels": true
3160 3160 }
3161 3161 },
3162   - "title": "Email messages daily activity",
  3162 + "title": "{i18n:api-usage.email-messages-daily-activity}",
3163 3163 "dropShadow": true,
3164 3164 "enableFullscreen": true,
3165 3165 "titleStyle": {
... ... @@ -3208,7 +3208,7 @@
3208 3208 {
3209 3209 "name": "emailCount",
3210 3210 "type": "timeseries",
3211   - "label": "Email messages",
  3211 + "label": "{i18n:api-usage.email-messages}",
3212 3212 "color": "#d35a00",
3213 3213 "settings": {
3214 3214 "excludeFromStacking": false,
... ... @@ -3294,7 +3294,7 @@
3294 3294 "showLabels": true
3295 3295 }
3296 3296 },
3297   - "title": "Email messages monthly activity",
  3297 + "title": "{i18n:api-usage.sms-messages-monthly-activity}",
3298 3298 "dropShadow": true,
3299 3299 "enableFullscreen": true,
3300 3300 "titleStyle": {
... ... @@ -3343,7 +3343,7 @@
3343 3343 {
3344 3344 "name": "smsCountHourly",
3345 3345 "type": "timeseries",
3346   - "label": "SMS messages",
  3346 + "label": "{i18n:api-usage.sms-messages}",
3347 3347 "color": "#f36021",
3348 3348 "settings": {
3349 3349 "excludeFromStacking": false,
... ... @@ -3429,7 +3429,7 @@
3429 3429 "showLabels": true
3430 3430 }
3431 3431 },
3432   - "title": "SMS messages daily activity",
  3432 + "title": "{i18n:api-usage.sms-messages-daily-activity}",
3433 3433 "dropShadow": true,
3434 3434 "enableFullscreen": true,
3435 3435 "titleStyle": {
... ... @@ -3478,7 +3478,7 @@
3478 3478 {
3479 3479 "name": "smsCount",
3480 3480 "type": "timeseries",
3481   - "label": "SMS messages",
  3481 + "label": "{i18n:api-usage.sms-messages}",
3482 3482 "color": "#f36021",
3483 3483 "settings": {
3484 3484 "excludeFromStacking": false,
... ... @@ -3564,7 +3564,7 @@
3564 3564 "showLabels": true
3565 3565 }
3566 3566 },
3567   - "title": "SMS messages monthly activity",
  3567 + "title": "{i18n:api-usage.sms-messages-monthly-activity}",
3568 3568 "dropShadow": true,
3569 3569 "enableFullscreen": true,
3570 3570 "titleStyle": {
... ... @@ -3610,7 +3610,7 @@
3610 3610 {
3611 3611 "name": "successfulMsgs",
3612 3612 "type": "timeseries",
3613   - "label": "${entityName} Successful",
  3613 + "label": "{i18n:api-usage.successful}",
3614 3614 "color": "#4caf50",
3615 3615 "settings": {
3616 3616 "excludeFromStacking": false,
... ... @@ -3640,7 +3640,7 @@
3640 3640 {
3641 3641 "name": "failedMsgs",
3642 3642 "type": "timeseries",
3643   - "label": "${entityName} Permanent Failures",
  3643 + "label": "{i18n:api-usage.permanent-failures}",
3644 3644 "color": "#ef5350",
3645 3645 "settings": {
3646 3646 "excludeFromStacking": false,
... ... @@ -3670,7 +3670,7 @@
3670 3670 {
3671 3671 "name": "tmpFailed",
3672 3672 "type": "timeseries",
3673   - "label": "${entityName} Processing Failures",
  3673 + "label": "{i18n:api-usage.processing-failures}",
3674 3674 "color": "#ffc107",
3675 3675 "settings": {
3676 3676 "excludeFromStacking": false,
... ... @@ -3794,7 +3794,7 @@
3794 3794 {
3795 3795 "name": "timeoutMsgs",
3796 3796 "type": "timeseries",
3797   - "label": "${entityName} Permanent Timeouts",
  3797 + "label": "{i18n:api-usage.permanent-timeouts}",
3798 3798 "color": "#4caf50",
3799 3799 "settings": {
3800 3800 "excludeFromStacking": false,
... ... @@ -3824,7 +3824,7 @@
3824 3824 {
3825 3825 "name": "tmpTimeout",
3826 3826 "type": "timeseries",
3827   - "label": "${entityName} Processing Timeouts",
  3827 + "label": "{i18n:api-usage.processing-timeouts}",
3828 3828 "color": "#9c27b0",
3829 3829 "settings": {
3830 3830 "excludeFromStacking": false,
... ... @@ -4031,7 +4031,7 @@
4031 4031 },
4032 4032 "states": {
4033 4033 "default": {
4034   - "name": "Api Usage",
  4034 + "name": "{i18n:api-usage.api-usage}",
4035 4035 "root": true,
4036 4036 "layouts": {
4037 4037 "main": {
... ... @@ -4130,7 +4130,7 @@
4130 4130 }
4131 4131 },
4132 4132 "transport": {
4133   - "name": "Transport",
  4133 + "name": "{i18n:api-usage.transport}",
4134 4134 "root": false,
4135 4135 "layouts": {
4136 4136 "main": {
... ... @@ -4163,7 +4163,7 @@
4163 4163 }
4164 4164 },
4165 4165 "rule_engine_execution": {
4166   - "name": "Rule Engine execution",
  4166 + "name": "{i18n:api-usage.rule-engine-executions}",
4167 4167 "root": false,
4168 4168 "layouts": {
4169 4169 "main": {
... ... @@ -4196,7 +4196,7 @@
4196 4196 }
4197 4197 },
4198 4198 "javascript_functions": {
4199   - "name": "JavaScript functions",
  4199 + "name": "{i18n:api-usage.javascript-functions}",
4200 4200 "root": false,
4201 4201 "layouts": {
4202 4202 "main": {
... ... @@ -4229,7 +4229,7 @@
4229 4229 }
4230 4230 },
4231 4231 "telemetry_persistence": {
4232   - "name": "Telemetry persistence",
  4232 + "name": "{i18n:api-usage.telemetry-persistence}",
4233 4233 "root": false,
4234 4234 "layouts": {
4235 4235 "main": {
... ... @@ -4262,7 +4262,7 @@
4262 4262 }
4263 4263 },
4264 4264 "email_messages": {
4265   - "name": "Email messages",
  4265 + "name": "{i18n:api-usage.email-messages}",
4266 4266 "root": false,
4267 4267 "layouts": {
4268 4268 "main": {
... ... @@ -4295,7 +4295,7 @@
4295 4295 }
4296 4296 },
4297 4297 "sms_messages": {
4298   - "name": "SMS messages",
  4298 + "name": "{i18n:api-usage.sms-messages}",
4299 4299 "root": false,
4300 4300 "layouts": {
4301 4301 "main": {
... ... @@ -4328,7 +4328,7 @@
4328 4328 }
4329 4329 },
4330 4330 "rule_engine_statistics": {
4331   - "name": "Rule Engine Statistics",
  4331 + "name": "{i18n:api-usage.rule-engine-statistics}",
4332 4332 "root": false,
4333 4333 "layouts": {
4334 4334 "main": {
... ... @@ -4417,4 +4417,4 @@
4417 4417 }
4418 4418 },
4419 4419 "name": "Api Usage"
4420   -}
\ No newline at end of file
  4420 +}
... ...
... ... @@ -433,7 +433,57 @@
433 433 "no-telemetry-text": "No telemetry found"
434 434 },
435 435 "api-usage": {
436   - "api-usage": "Api Usage"
  436 + "api-usage": "Api Usage",
  437 + "data-points": "Data points",
  438 + "data-points-storage-days": "Data points storage days",
  439 + "email": "Email",
  440 + "email-messages": "Email messages",
  441 + "email-messages-daily-activity": "Email messages daily activity",
  442 + "email-messages-hourly-activity": "Email messages hourly activity",
  443 + "email-messages-monthly-activity": "Email messages monthly activity",
  444 + "exceptions": "Exceptions",
  445 + "executions": "Executions",
  446 + "javascript": "JavaScript",
  447 + "javascript-executions": "JavaScript executions",
  448 + "javascript-functions": "JavaScript functions",
  449 + "javascript-functions-daily-activity": "JavaScript functions daily activity",
  450 + "javascript-functions-hourly-activity": "JavaScript functions hourly activity",
  451 + "javascript-functions-monthly-activity": "JavaScript functions monthly activity",
  452 + "latest-error": "Latest Error",
  453 + "messages": "Messages",
  454 + "permanent-failures": "${entityName} Permanent Failures",
  455 + "permanent-timeouts": "${entityName} Permanent Timeouts",
  456 + "processing-failures": "${entityName} Processing Failures",
  457 + "processing-failures-and-timeouts": "Processing Failures and Timeouts",
  458 + "processing-timeouts": "${entityName} Processing Timeouts",
  459 + "queue-stats": "Queue Stats",
  460 + "rule-chain": "Rule Chain",
  461 + "rule-engine": "Rule Engine",
  462 + "rule-engine-daily-activity": "Rule Engine daily activity",
  463 + "rule-engine-executions": "Rule Engine executions",
  464 + "rule-engine-hourly-activity": "Rule Engine hourly activity",
  465 + "rule-engine-monthly-activity": "Rule Engine monthly activity",
  466 + "rule-engine-statistics": "Rule Engine Statistics",
  467 + "rule-node": "Rule Node",
  468 + "sms": "SMS",
  469 + "sms-messages": "SMS messages",
  470 + "sms-messages-daily-activity": "SMS messages daily activity",
  471 + "sms-messages-hourly-activity": "SMS messages hourly activity",
  472 + "sms-messages-monthly-activity": "SMS messages monthly activity",
  473 + "successful": "${entityName} Successful",
  474 + "telemetry": "Telemetry",
  475 + "telemetry-persistence": "Telemetry persistence",
  476 + "telemetry-persistence-daily-activity": "Telemetry persistence daily activity",
  477 + "telemetry-persistence-hourly-activity": "Telemetry persistence hourly activity",
  478 + "telemetry-persistence-monthly-activity": "Telemetry persistence monthly activity",
  479 + "transport": "Transport",
  480 + "transport-daily-activity": "Transport daily activity",
  481 + "transport-data-points": "Transport data points",
  482 + "transport-hourly-activity": "Transport hourly activity",
  483 + "transport-messages": "Transport messages",
  484 + "transport-monthly-activity": "Transport monthly activity",
  485 + "view-details": "View details",
  486 + "view-statistics": "View statistics"
437 487 },
438 488 "audit-log": {
439 489 "audit": "Audit",
... ...