diff --git a/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts
index 040e27b2ff..8bd881f38f 100644
--- a/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts
@@ -46,6 +46,7 @@ import { TranslateService } from '@ngx-translate/core';
import { DomSanitizer } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { TbInject } from '@shared/decorators/tb-inject';
+import { MillisecondsToTimeStringPipe } from '@shared/pipe/milliseconds-to-time-string.pipe';
@Directive()
// tslint:disable-next-line:directive-class-suffix
@@ -83,6 +84,7 @@ export class DynamicWidgetComponent extends PageComponent implements IDynamicWid
this.ctx.resourceService = $injector.get(ResourceService);
this.ctx.telemetryWsService = $injector.get(TelemetryWebsocketService);
this.ctx.date = $injector.get(DatePipe);
+ this.ctx.milliSecondsToTimeString = $injector.get(MillisecondsToTimeStringPipe);
this.ctx.translate = $injector.get(TranslateService);
this.ctx.http = $injector.get(HttpClient);
this.ctx.sanitizer = $injector.get(DomSanitizer);
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/markdown-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/markdown-widget.component.ts
index d76e43d765..07c4555937 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/markdown-widget.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/markdown-widget.component.ts
@@ -42,7 +42,7 @@ interface MarkdownWidgetSettings {
markdownCss: string;
}
-type MarkdownTextFunction = (data: FormattedData[]) => string;
+type MarkdownTextFunction = (data: FormattedData[], ctx: WidgetContext) => string;
@Component({
selector: 'tb-markdown-widget ',
@@ -72,7 +72,8 @@ export class MarkdownWidgetComponent extends PageComponent implements OnInit {
ngOnInit(): void {
this.ctx.$scope.markdownWidget = this;
this.settings = this.ctx.settings;
- this.markdownTextFunction = this.settings.useMarkdownTextFunction ? parseFunction(this.settings.markdownTextFunction, ['data']) : null;
+ this.markdownTextFunction = this.settings.useMarkdownTextFunction ?
+ parseFunction(this.settings.markdownTextFunction, ['data', 'ctx']) : null;
this.markdownClass = 'markdown-widget';
const cssString = this.settings.markdownCss;
if (isNotEmptyStr(cssString)) {
@@ -117,7 +118,7 @@ export class MarkdownWidgetComponent extends PageComponent implements OnInit {
}
const data = formattedDataFormDatasourceData(initialData);
let markdownText = this.settings.useMarkdownTextFunction ?
- safeExecute(this.markdownTextFunction, [data]) : this.settings.markdownTextPattern;
+ safeExecute(this.markdownTextFunction, [data, this.ctx]) : this.settings.markdownTextPattern;
const allData: FormattedData = flatDataWithoutOverride(data);
markdownText = createLabelFromPattern(markdownText, allData);
if (this.markdownText !== markdownText) {
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html
index 040e470be1..06a419542b 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html
@@ -22,7 +22,7 @@
diff --git a/ui-ngx/src/app/modules/home/models/services.map.ts b/ui-ngx/src/app/modules/home/models/services.map.ts
index 7514e972b5..f8c4390611 100644
--- a/ui-ngx/src/app/modules/home/models/services.map.ts
+++ b/ui-ngx/src/app/modules/home/models/services.map.ts
@@ -40,6 +40,7 @@ import { AuthService } from '@core/auth/auth.service';
import { ResourceService } from '@core/http/resource.service';
import { TwoFactorAuthenticationService } from '@core/http/two-factor-authentication.service';
import { TelemetryWebsocketService } from '@core/ws/telemetry-websocket.service';
+import { MillisecondsToTimeStringPipe } from '@shared/pipe/milliseconds-to-time-string.pipe';
export const ServicesMap = new Map>(
[
@@ -57,6 +58,7 @@ export const ServicesMap = new Map>(
['dialogs', DialogService],
['customDialog', CustomDialogService],
['date', DatePipe],
+ ['milliSecondsToTimeString', MillisecondsToTimeStringPipe],
['utils', UtilsService],
['translate', TranslateService],
['http', HttpClient],
diff --git a/ui-ngx/src/app/modules/home/models/widget-component.models.ts b/ui-ngx/src/app/modules/home/models/widget-component.models.ts
index 813b3b6927..41c7453fc6 100644
--- a/ui-ngx/src/app/modules/home/models/widget-component.models.ts
+++ b/ui-ngx/src/app/modules/home/models/widget-component.models.ts
@@ -88,7 +88,7 @@ import * as RxJSOperators from 'rxjs/operators';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { EntityId } from '@shared/models/id/entity-id';
import { AlarmQuery, AlarmSearchStatus, AlarmStatus} from '@app/shared/models/alarm.models';
-import { TelemetrySubscriber } from '@app/shared/public-api';
+import { MillisecondsToTimeStringPipe, TelemetrySubscriber } from '@app/shared/public-api';
export interface IWidgetAction {
name: string;
@@ -182,6 +182,7 @@ export class WidgetContext {
telemetryWsService: TelemetryWebsocketService;
telemetrySubscribers?: TelemetrySubscriber[];
date: DatePipe;
+ milliSecondsToTimeString: MillisecondsToTimeStringPipe;
translate: TranslateService;
http: HttpClient;
sanitizer: DomSanitizer;
diff --git a/ui-ngx/src/app/shared/pipe/milliseconds-to-time-string.pipe.ts b/ui-ngx/src/app/shared/pipe/milliseconds-to-time-string.pipe.ts
index 6722f2f72e..d66513e057 100644
--- a/ui-ngx/src/app/shared/pipe/milliseconds-to-time-string.pipe.ts
+++ b/ui-ngx/src/app/shared/pipe/milliseconds-to-time-string.pipe.ts
@@ -25,33 +25,51 @@ export class MillisecondsToTimeStringPipe implements PipeTransform {
constructor(private translate: TranslateService) {
}
- transform(millseconds: number, args?: any): string {
+ transform(millseconds: number, shortFormat = false): string {
let seconds = Math.floor(millseconds / 1000);
const days = Math.floor(seconds / 86400);
let hours = Math.floor((seconds % 86400) / 3600);
let minutes = Math.floor(((seconds % 86400) % 3600) / 60);
seconds = seconds % 60;
let timeString = '';
- if (days > 0) {
- timeString += this.translate.instant('timewindow.days', {days});
- }
- if (hours > 0) {
- if (timeString.length === 0 && hours === 1) {
- hours = 0;
+ if (shortFormat) {
+ if (days > 0) {
+ timeString += this.translate.instant('timewindow.short.days', {days});
}
- timeString += this.translate.instant('timewindow.hours', {hours});
- }
- if (minutes > 0) {
- if (timeString.length === 0 && minutes === 1) {
- minutes = 0;
+ if (hours > 0) {
+ timeString += this.translate.instant('timewindow.short.hours', {hours});
}
- timeString += this.translate.instant('timewindow.minutes', {minutes});
- }
- if (seconds > 0) {
- if (timeString.length === 0 && seconds === 1) {
- seconds = 0;
+ if (minutes > 0) {
+ timeString += this.translate.instant('timewindow.short.minutes', {minutes});
+ }
+ if (seconds > 0) {
+ timeString += this.translate.instant('timewindow.short.seconds', {seconds});
+ }
+ if (!timeString.length) {
+ timeString += this.translate.instant('timewindow.short.seconds', {seconds: 0});
+ }
+ } else {
+ if (days > 0) {
+ timeString += this.translate.instant('timewindow.days', {days});
+ }
+ if (hours > 0) {
+ if (timeString.length === 0 && hours === 1) {
+ hours = 0;
+ }
+ timeString += this.translate.instant('timewindow.hours', {hours});
+ }
+ if (minutes > 0) {
+ if (timeString.length === 0 && minutes === 1) {
+ minutes = 0;
+ }
+ timeString += this.translate.instant('timewindow.minutes', {minutes});
+ }
+ if (seconds > 0) {
+ if (timeString.length === 0 && seconds === 1) {
+ seconds = 0;
+ }
+ timeString += this.translate.instant('timewindow.seconds', {seconds});
}
- timeString += this.translate.instant('timewindow.seconds', {seconds});
}
return timeString;
}
diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/markdown/markdown_text_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/markdown/markdown_text_fn.md
index 9bbcb7fd7c..c11f412b6f 100644
--- a/ui-ngx/src/assets/help/en_US/widget/lib/markdown/markdown_text_fn.md
+++ b/ui-ngx/src/assets/help/en_US/widget/lib/markdown/markdown_text_fn.md
@@ -3,7 +3,7 @@
-*function (data): string*
+*function (data, ctx): string*
A JavaScript function used to calculate markdown or HTML content.
@@ -13,6 +13,9 @@ A JavaScript function used to calculate markdown or HTML content.
data: FormattedData[] - An array of FormattedData objects resolved from configured datasources.
Each object represents basic entity properties (ex. entityId, entityName)
and provides access to other entity attributes/timeseries declared in widget datasource configuration.
+ ctx: WidgetContext - A reference to WidgetContext that has all necessary API
+ and data used by widget instance.
+
**Returns:**
diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json
index dd28154103..c7ce4f9211 100644
--- a/ui-ngx/src/assets/locale/locale.constant-en_US.json
+++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json
@@ -3379,6 +3379,12 @@
"hours": "{ hours, plural, 0 { hour } 1 {1 hour } other {# hours } }",
"minutes": "{ minutes, plural, 0 { minute } 1 {1 minute } other {# minutes } }",
"seconds": "{ seconds, plural, 0 { second } 1 {1 second } other {# seconds } }",
+ "short": {
+ "days": "{ days, plural, 1 {1 day } other {# days } }",
+ "hours": "{ hours, plural, 1 {1 hour } other {# hours } }",
+ "minutes": "{{minutes}} min ",
+ "seconds": "{{seconds}} sec "
+ },
"realtime": "Realtime",
"history": "History",
"last-prefix": "last",