diff --git a/application/src/main/data/json/system/widget_types/timeseries_table.json b/application/src/main/data/json/system/widget_types/timeseries_table.json
index 625f7a1e7d..0283899134 100644
--- a/application/src/main/data/json/system/widget_types/timeseries_table.json
+++ b/application/src/main/data/json/system/widget_types/timeseries_table.json
@@ -17,7 +17,7 @@
"latestDataKeySettingsDirective": "tb-timeseries-table-latest-key-settings",
"hasBasicMode": true,
"basicModeDirective": "tb-timeseries-table-basic-config",
- "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"filterId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}],\"latestDataKeys\":[]}],\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"enableSearch\":true,\"enableSelectColumnDisplay\":true,\"enableStickyHeader\":true,\"enableStickyAction\":true,\"showCellActionsMenu\":true,\"reserveSpaceForHiddenAction\":\"true\",\"showTimestamp\":true,\"dateFormat\":{\"format\":\"yyyy-MM-dd HH:mm:ss\"},\"displayPagination\":true,\"useEntityLabel\":false,\"defaultPageSize\":10,\"pageStepCount\":3,\"pageStepIncrement\":10,\"hideEmptyLines\":false,\"disableStickyHeader\":false,\"useRowStyleFunction\":false,\"rowStyleFunction\":\"\",\"tabSortKey\":\"timestamp\"},\"title\":\"Time series table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{},\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"configMode\":\"basic\",\"titleFont\":null,\"titleColor\":null,\"titleIcon\":null}"
+ "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"filterId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}],\"latestDataKeys\":[]}],\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"enableSearch\":true,\"enableSelectColumnDisplay\":true,\"enableStickyHeader\":true,\"enableStickyAction\":true,\"showCellActionsMenu\":true,\"reserveSpaceForHiddenAction\":\"true\",\"showTimestamp\":true,\"dateFormat\":{\"format\":\"yyyy-MM-dd HH:mm:ss\"},\"displayPagination\":true,\"useEntityLabel\":false,\"defaultPageSize\":10,\"pageStepCount\":3,\"pageStepIncrement\":10,\"hideEmptyLines\":false,\"disableStickyHeader\":false,\"useRowStyleFunction\":false,\"rowStyleFunction\":\"\",\"sortOrder\":{\"property\":\"createdTime\",\"direction\":\"ASC\"}},\"title\":\"Time series table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{},\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"configMode\":\"basic\",\"titleFont\":null,\"titleColor\":null,\"titleIcon\":null}"
},
"resources": [
{
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html
index f236dd1acd..ae07674162 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html
@@ -113,17 +113,24 @@
widgets.table.table-tabs
- {{ 'widgets.table.use-entity-label-tab-name' | translate }}
+ {{ 'widgets.table.use-entity-label-header-title' | translate }}
-
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts
index ccbb582679..95a9eb8014 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts
@@ -20,7 +20,8 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { buildPageStepSizeValues } from '@home/components/widget/lib/table-widget.models';
-import { TabSortKey } from '@app/modules/home/components/widget/lib/timeseries-table-widget.component'
+import { Direction } from '@shared/models/page/sort-order';
+import { entityFields } from '@shared/models/entity.models';
@Component({
selector: 'tb-timeseries-table-widget-settings',
@@ -29,7 +30,8 @@ import { TabSortKey } from '@app/modules/home/components/widget/lib/timeseries-t
})
export class TimeseriesTableWidgetSettingsComponent extends WidgetSettingsComponent {
- TabSortKey = TabSortKey;
+ entityFields = entityFields;
+ Direction = Direction;
timeseriesTableWidgetSettingsForm: UntypedFormGroup;
pageStepSizeValues = [];
@@ -44,6 +46,7 @@ export class TimeseriesTableWidgetSettingsComponent extends WidgetSettingsCompon
}
protected defaultSettings(): WidgetSettings {
+ console.log("default")
return {
enableSearch: true,
enableSelectColumnDisplay: true,
@@ -62,14 +65,21 @@ export class TimeseriesTableWidgetSettingsComponent extends WidgetSettingsCompon
disableStickyHeader: false,
useRowStyleFunction: false,
rowStyleFunction: '',
- tabSortKey: TabSortKey.TIMESTAMP
+ sortOrder: {
+ property: this.entityFields.name.keyName,
+ direction: Direction.ASC
+ }
};
}
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
settings.pageStepIncrement = settings.pageStepIncrement ?? settings.defaultPageSize;
- settings.tabSortKey = settings.tabSortKey ?? TabSortKey.TIMESTAMP;
+ settings.sortOrder = {
+ property: settings.sortOrder?.property || this.entityFields.name.keyName,
+ direction: settings.sortOrder?.direction || Direction.ASC
+ };
this.pageStepSizeValues = buildPageStepSizeValues(settings.pageStepCount, settings.pageStepIncrement);
+ console.log("input",settings)
return settings;
}
@@ -99,7 +109,16 @@ export class TimeseriesTableWidgetSettingsComponent extends WidgetSettingsCompon
disableStickyHeader: [settings.disableStickyHeader, []],
useRowStyleFunction: [settings.useRowStyleFunction, []],
rowStyleFunction: [settings.rowStyleFunction, [Validators.required]],
- tabSortKey: [settings.tabSortKey, []],
+ sortOrder: this.fb.group({
+ property: [
+ settings.sortOrder.property,
+ Validators.required
+ ],
+ direction: [
+ settings.sortOrder.direction,
+ Validators.required
+ ]
+ })
});
}
@@ -107,6 +126,15 @@ export class TimeseriesTableWidgetSettingsComponent extends WidgetSettingsCompon
return ['useRowStyleFunction', 'displayPagination', 'pageStepCount', 'pageStepIncrement'];
}
+ protected prepareOutputSettings(settings: WidgetSettings): WidgetSettings {
+ settings.sortOrder = {
+ property: settings.sortOrder?.property || this.entityFields.name.keyName,
+ direction: settings.sortOrder?.direction || Direction.ASC
+ };
+ console.log("output",settings)
+ return settings;
+ }
+
protected updateValidators(emitEvent: boolean, trigger: string) {
if (trigger === 'pageStepCount' || trigger === 'pageStepIncrement') {
this.timeseriesTableWidgetSettingsForm.get('defaultPageSize').reset();
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts
index dbd4905299..d6c73d7f82 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts
@@ -106,19 +106,14 @@ import { ComponentPortal } from '@angular/cdk/portal';
import { FormBuilder } from '@angular/forms';
import { DEFAULT_OVERLAY_POSITIONS } from '@shared/models/overlay.models';
import { DateFormatSettings, ValueFormatProcessor } from '@shared/models/widget-settings.models';
-
-export enum TabSortKey {
- NAME_ASC = 'NAME_ASC',
- NAME_DESC = 'NAME_DESC',
- TIMESTAMP = 'timestamp'
-}
+import { entityFields } from '@shared/models/entity.models';
export interface TimeseriesTableWidgetSettings extends TableWidgetSettings {
showTimestamp: boolean;
showMilliseconds: boolean;
hideEmptyLines: boolean;
dateFormat: DateFormatSettings;
- tabSortKey: TabSortKey;
+ sortOrder: SortOrder;
}
interface TimeseriesWidgetLatestDataKeySettings extends TableWidgetDataKeySettings {
@@ -405,7 +400,7 @@ export class TimeseriesTableWidgetComponent extends PageComponent implements OnI
return entityLabelCache.get(source.entityId);
}
- const value = this.useEntityLabel
+ const value = this.useEntityLabel
? (source.entityLabel || source.entityName)
: source.entityName;
@@ -414,19 +409,78 @@ export class TimeseriesTableWidgetComponent extends PageComponent implements OnI
return translated;
}
- private sortDatasources(source: Datasource[], entityLabelCache:Map): Datasource[] {
+ private sortDatasources(source: Datasource[], entityLabelCache: Map): Datasource[] {
+ const property = this.settings?.sortOrder?.property;
+ const direction = this.settings?.sortOrder?.direction;
+ const isAsc = direction === Direction.ASC;
+ let sortedSource = [...source];
+
source.forEach(ds => this.getTabLabel(ds, entityLabelCache));
- if (this.settings.tabSortKey === TabSortKey.TIMESTAMP) {
- return source;
+ if (property === entityFields.name.keyName) {
+ const collator = new Intl.Collator(undefined, {
+ sensitivity: "variant",
+ numeric: true,
+ ignorePunctuation: false
+ });
+
+ sortedSource.sort((a, b) => {
+ const valueA = entityLabelCache.get(a.entityId) || '';
+ const valueB = entityLabelCache.get(b.entityId) || '';
+
+ return isAsc
+ ? collator.compare(valueA, valueB)
+ : collator.compare(valueB, valueA);
+ });
+ } else if (property === entityFields.createdTime.keyName) {
+ if (!isAsc) {
+ sortedSource.reverse();
+ }
}
- return source.sort((a, b) => {
- const valueA = entityLabelCache.get(a.entityId);
- const valueB = entityLabelCache.get(b.entityId);
- return this.settings.tabSortKey === TabSortKey.NAME_ASC
- ? valueA.localeCompare(valueB)
- : valueB.localeCompare(valueA);
+ this.reorderDataArrays(source, sortedSource);
+ return sortedSource;
+ }
+
+ private reorderDataArrays(originalOrder: Datasource[], newOrder: Datasource[]): void {
+ const indexMap = new Map();
+ originalOrder.forEach((ds, oldIndex) => {
+ const newIndex = newOrder.findIndex(newDs => newDs.entityId === ds.entityId);
+ indexMap.set(oldIndex, newIndex);
});
+
+ const newData: Array = [];
+ originalOrder.forEach((ds, oldIndex) => {
+ const dataKeys = ds.dataKeys;
+ const startIdx = oldIndex * dataKeys.length;
+ const endIdx = startIdx + dataKeys.length;
+ const datasourceData = this.data.slice(startIdx, endIdx);
+
+ const newIndex = indexMap.get(oldIndex);
+ const newStartIdx = newIndex * dataKeys.length;
+
+ datasourceData.forEach((data, i) => {
+ newData[newStartIdx + i] = data;
+ });
+ });
+ this.data = newData;
+
+ if (this.latestData && this.latestData.length > 0) {
+ const newLatestData: Array = [];
+ originalOrder.forEach((ds, oldIndex) => {
+ const latestDataKeys = ds.latestDataKeys || [];
+ const startIdx = oldIndex * latestDataKeys.length;
+ const endIdx = startIdx + latestDataKeys.length;
+ const datasourceLatestData = this.latestData.slice(startIdx, endIdx);
+
+ const newIndex = indexMap.get(oldIndex);
+ const newStartIdx = newIndex * latestDataKeys.length;
+
+ datasourceLatestData.forEach((data, i) => {
+ newLatestData[newStartIdx + i] = data;
+ });
+ });
+ this.latestData = newLatestData;
+ }
}
private updateDatasources() {
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 538b3a8352..9850ec73d7 100644
--- a/ui-ngx/src/assets/locale/locale.constant-en_US.json
+++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json
@@ -9482,7 +9482,7 @@
"page-step-increment": "Step increment",
"page-step-count-format-message": "Should be an integer value, in the range from 1 to 100.",
"page-step-increment-format-message": "Should be an integer value, greater or equal to 1.",
- "use-entity-label-tab-name": "Use entity label in tab name",
+ "use-entity-label-header-title": "Use entity label in header title",
"hide-empty-lines": "Hide empty lines",
"row-style": "Row style",
"use-row-style-function": "Use row style function",
@@ -9538,8 +9538,8 @@
"show-cell-actions-menu-mobile": "Show cell actions dropdown menu in mobile mode",
"disable-sorting": "Disable sorting",
"sort-by": "Sort tabs by",
- "sort-asc": "Name Ascending",
- "sort-desc": "Name Descending",
+ "sort-asc": "Ascending",
+ "sort-desc": "Descending",
"sort-timestamp-option": "Created time"
},
"latest-chart": {
diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss
index af166b406d..b8e269c14e 100644
--- a/ui-ngx/src/form.scss
+++ b/ui-ngx/src/form.scss
@@ -257,6 +257,12 @@
flex: 1;
}
}
+ &.flex-lt-lg {
+ @media #{$mat-lt-lg} {
+ width: auto;
+ flex: 1;
+ }
+ }
}
.fixed-title-width {
min-width: 200px;