diff --git a/application/src/main/data/json/edge/instructions/install/centos/instructions.md b/application/src/main/data/json/edge/instructions/install/centos/instructions.md
index bcc1967dfd..86c5acad56 100644
--- a/application/src/main/data/json/edge/instructions/install/centos/instructions.md
+++ b/application/src/main/data/json/edge/instructions/install/centos/instructions.md
@@ -56,13 +56,13 @@ sudo yum update
sudo yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# Install packages
sudo yum -y install epel-release yum-utils
-sudo yum-config-manager --enable pgdg15
-sudo yum install postgresql15-server postgresql15
+sudo yum-config-manager --enable pgdg16
+sudo yum install postgresql16-server postgresql16 postgresql16-contrib
# Initialize your PostgreSQL DB
-sudo /usr/pgsql-15/bin/postgresql-15-setup initdb
-sudo systemctl start postgresql-15
+sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
+sudo systemctl start postgresql-16
# Optional: Configure PostgreSQL to start on boot
-sudo systemctl enable --now postgresql-15
+sudo systemctl enable --now postgresql-16
{:copy-code}
```
@@ -74,12 +74,12 @@ sudo systemctl enable --now postgresql-15
sudo yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# Install packages
sudo dnf -qy module disable postgresql
-sudo dnf -y install postgresql15 postgresql15-server
+sudo dnf -y install postgresql16 postgresql16-server postgresql16-contrib
# Initialize your PostgreSQL DB
-sudo /usr/pgsql-15/bin/postgresql-15-setup initdb
-sudo systemctl start postgresql-15
+sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
+sudo systemctl start postgresql-16
# Optional: Configure PostgreSQL to start on boot
-sudo systemctl enable --now postgresql-15
+sudo systemctl enable --now postgresql-16
{:copy-code}
```
@@ -101,7 +101,7 @@ After configuring the password, edit the pg_hba.conf to use MD5 authentication w
Edit pg_hba.conf file:
```bash
-sudo nano /var/lib/pgsql/15/data/pg_hba.conf
+sudo nano /var/lib/pgsql/16/data/pg_hba.conf
{:copy-code}
```
@@ -121,7 +121,7 @@ host all all 127.0.0.1/32 md5
Finally, you should restart the PostgreSQL service to initialize the new configuration:
```bash
-sudo systemctl restart postgresql-15.service
+sudo systemctl restart postgresql-16.service
{:copy-code}
```
diff --git a/application/src/main/data/json/edge/instructions/install/docker/instructions.md b/application/src/main/data/json/edge/instructions/install/docker/instructions.md
index 9910124b3e..23f484f2ec 100644
--- a/application/src/main/data/json/edge/instructions/install/docker/instructions.md
+++ b/application/src/main/data/json/edge/instructions/install/docker/instructions.md
@@ -38,7 +38,7 @@ services:
${EXTRA_HOSTS}
postgres:
restart: always
- image: "postgres:15"
+ image: "postgres:16"
ports:
- "5432"
environment:
diff --git a/application/src/main/data/json/edge/instructions/install/ubuntu/instructions.md b/application/src/main/data/json/edge/instructions/install/ubuntu/instructions.md
index fe9601443f..992b5e2ee2 100644
--- a/application/src/main/data/json/edge/instructions/install/ubuntu/instructions.md
+++ b/application/src/main/data/json/edge/instructions/install/ubuntu/instructions.md
@@ -49,7 +49,7 @@ echo "deb http://apt.postgresql.org/pub/repos/apt/ ${RELEASE}"-pgdg main | sudo
# install and launch the postgresql service:
sudo apt update
-sudo apt -y install postgresql-15
+sudo apt -y install postgresql-16
sudo service postgresql start
{:copy-code}
```
diff --git a/application/src/main/data/json/edge/instructions/upgrade/docker/upgrade_db.md b/application/src/main/data/json/edge/instructions/upgrade/docker/upgrade_db.md
index d922fa9155..a594ebe4e7 100644
--- a/application/src/main/data/json/edge/instructions/upgrade/docker/upgrade_db.md
+++ b/application/src/main/data/json/edge/instructions/upgrade/docker/upgrade_db.md
@@ -21,7 +21,7 @@ services:
entrypoint: upgrade-tb-edge.sh
postgres:
restart: always
- image: "postgres:15"
+ image: "postgres:16"
ports:
- "5432"
environment:
diff --git a/docker/docker-compose.hybrid.yml b/docker/docker-compose.hybrid.yml
index 43f1e81cd1..5bffa9fb1d 100644
--- a/docker/docker-compose.hybrid.yml
+++ b/docker/docker-compose.hybrid.yml
@@ -19,7 +19,7 @@ version: '3.0'
services:
postgres:
restart: always
- image: "postgres:15"
+ image: "postgres:16"
ports:
- "5432"
environment:
diff --git a/docker/docker-compose.postgres.yml b/docker/docker-compose.postgres.yml
index 780d2ccefd..50844fa2eb 100644
--- a/docker/docker-compose.postgres.yml
+++ b/docker/docker-compose.postgres.yml
@@ -19,7 +19,7 @@ version: '3.0'
services:
postgres:
restart: always
- image: "postgres:15"
+ image: "postgres:16"
ports:
- "5432"
environment:
diff --git a/msa/tb/docker-cassandra/Dockerfile b/msa/tb/docker-cassandra/Dockerfile
index 18071b249b..27613fe161 100644
--- a/msa/tb/docker-cassandra/Dockerfile
+++ b/msa/tb/docker-cassandra/Dockerfile
@@ -16,7 +16,7 @@
FROM thingsboard/openjdk17:bookworm-slim
-ENV PG_MAJOR=15
+ENV PG_MAJOR=16
ENV DATA_FOLDER=/data
diff --git a/ui-ngx/src/app/core/services/dashboard-utils.service.ts b/ui-ngx/src/app/core/services/dashboard-utils.service.ts
index f0341410bc..235924f98f 100644
--- a/ui-ngx/src/app/core/services/dashboard-utils.service.ts
+++ b/ui-ngx/src/app/core/services/dashboard-utils.service.ts
@@ -636,7 +636,7 @@ export class DashboardUtilsService {
targetLayout: DashboardLayoutId,
widget: Widget,
originalColumns?: number,
- originalSize?: {sizeX: number; sizeY: number},
+ originalSize?: WidgetSize,
row?: number,
column?: number,
breakpoint = 'default'): void {
@@ -661,8 +661,8 @@ export class DashboardUtilsService {
mobileHeight: widget.config.mobileHeight,
mobileHide: widget.config.mobileHide,
desktopHide: widget.config.desktopHide,
- preserveAspectRatio: widget.config.preserveAspectRatio,
- resizable: widget.config.resizable
+ preserveAspectRatio: originalSize ? originalSize.preserveAspectRatio : widget.config.preserveAspectRatio,
+ resizable: originalSize ? originalSize.resizable : widget.config.resizable
};
if (isUndefined(originalColumns)) {
originalColumns = 24;
@@ -1065,7 +1065,9 @@ export class DashboardUtilsService {
const widgetLayout = layout.widgets[widget.id];
return {
sizeX: widgetLayout.sizeX,
- sizeY: widgetLayout.sizeY
+ sizeY: widgetLayout.sizeY,
+ preserveAspectRatio: widgetLayout.preserveAspectRatio,
+ resizable: widgetLayout.resizable
};
}
diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts
index c04a2af3df..52742c54c4 100644
--- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts
+++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts
@@ -39,6 +39,7 @@ import { map } from 'rxjs/operators';
import { displayGrids } from 'angular-gridster2/lib/gridsterConfig.interface';
import { BreakpointId, LayoutType, ViewFormatType } from '@shared/models/dashboard.models';
import { isNotEmptyStr } from '@core/utils';
+import { TbContextMenuEvent } from '@shared/models/jquery-event.models';
@Component({
selector: 'tb-dashboard-layout',
@@ -319,12 +320,12 @@ export class DashboardLayoutComponent extends PageComponent implements ILayoutCo
this.layoutCtx.dashboardCtrl.copyWidgetReference($event, this.layoutCtx, widget);
}
- pasteWidget($event: Event) {
+ pasteWidget($event: TbContextMenuEvent | KeyboardEvent) {
const pos = this.dashboard.getEventGridPosition($event);
this.layoutCtx.dashboardCtrl.pasteWidget($event, this.layoutCtx, pos);
}
- pasteWidgetReference($event: Event) {
+ pasteWidgetReference($event: TbContextMenuEvent | KeyboardEvent) {
const pos = this.dashboard.getEventGridPosition($event);
this.layoutCtx.dashboardCtrl.pasteWidgetReference($event, this.layoutCtx, pos);
}
diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/layout.models.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/layout.models.ts
index 3ea9f553a8..7b54261945 100644
--- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/layout.models.ts
+++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/layout.models.ts
@@ -14,13 +14,15 @@
/// limitations under the License.
///
+import { TbContextMenuEvent } from '@shared/models/jquery-event.models';
+
export interface ILayoutController {
reload();
resetHighlight();
highlightWidget(widgetId: string, delay?: number);
selectWidget(widgetId: string, delay?: number);
- pasteWidget($event: MouseEvent);
- pasteWidgetReference($event: MouseEvent);
+ pasteWidget($event: TbContextMenuEvent | KeyboardEvent);
+ pasteWidgetReference($event: TbContextMenuEvent | KeyboardEvent);
}
export enum LayoutWidthType {
diff --git a/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts b/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts
index fd031fa90f..7169e4a20b 100644
--- a/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts
+++ b/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts
@@ -529,7 +529,7 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
return dashboardWidget ? dashboardWidget.widget : null;
}
- getEventGridPosition(event: Event): WidgetPosition {
+ getEventGridPosition(event: TbContextMenuEvent | KeyboardEvent): WidgetPosition {
const pos: WidgetPosition = {
row: 0,
column: 0
@@ -537,7 +537,7 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
const parentElement = $(this.gridster.el);
let pageX = 0;
let pageY = 0;
- if (event instanceof MouseEvent) {
+ if ('pageX' in event && 'pageY' in event) {
pageX = event.pageX;
pageY = event.pageY;
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts
index 41611d3f6e..6d3e9fde82 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts
@@ -1168,13 +1168,13 @@ class CssScadaSymbolAnimation implements ScadaSymbolAnimation {
private element: Element,
duration = 1000) {
this._duration = duration;
- this.fixPatternAnimationForChromeBelow128();
+ this.fixPatternAnimationForChrome();
}
- private fixPatternAnimationForChromeBelow128(): void {
+ private fixPatternAnimationForChrome(): void {
try {
const userAgent = window.navigator.userAgent;
- if (+(/Chrome\/(\d+)/i.exec(userAgent)[1]) <= 127) {
+ if (+(/Chrome\/(\d+)/i.exec(userAgent)[1]) > 0) {
if (this.svgShape.defs().findOne('pattern') && !this.svgShape.defs().findOne('pattern.empty-animation')) {
this.svgShape.defs().add(SVG(''));
this.svgShape.style()
diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts
index 9ff7f24568..8459a361e4 100644
--- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts
@@ -959,11 +959,15 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
this.widgetContext.hiddenData = subscription.hiddenData;
this.widgetContext.timeWindow = subscription.timeWindow;
this.widgetContext.defaultSubscription = subscription;
- createSubscriptionSubject.next();
- createSubscriptionSubject.complete();
+ this.ngZone.run(() => {
+ createSubscriptionSubject.next();
+ createSubscriptionSubject.complete();
+ });
},
(err) => {
- createSubscriptionSubject.error(err);
+ this.ngZone.run(() => {
+ createSubscriptionSubject.error(err);
+ });
}
);
} else if (this.widget.type === widgetType.rpc) {
@@ -1016,11 +1020,15 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
this.createSubscription(options).subscribe(
(subscription) => {
this.widgetContext.defaultSubscription = subscription;
- createSubscriptionSubject.next();
- createSubscriptionSubject.complete();
+ this.ngZone.run(() => {
+ createSubscriptionSubject.next();
+ createSubscriptionSubject.complete();
+ });
},
(err) => {
- createSubscriptionSubject.error(err);
+ this.ngZone.run(() => {
+ createSubscriptionSubject.error(err);
+ });
}
);
this.detectChanges();
diff --git a/ui-ngx/src/app/modules/home/models/dashboard-component.models.ts b/ui-ngx/src/app/modules/home/models/dashboard-component.models.ts
index 65c6c23004..b4132bf882 100644
--- a/ui-ngx/src/app/modules/home/models/dashboard-component.models.ts
+++ b/ui-ngx/src/app/modules/home/models/dashboard-component.models.ts
@@ -42,6 +42,7 @@ import { enumerable } from '@shared/decorators/enumerable';
import { UtilsService } from '@core/services/utils.service';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { ComponentStyle, iconStyle, textStyle } from '@shared/models/widget-settings.models';
+import { TbContextMenuEvent } from '@shared/models/jquery-event.models';
export interface WidgetsData {
widgets: Array;
@@ -56,11 +57,11 @@ export interface ContextMenuItem {
}
export interface DashboardContextMenuItem extends ContextMenuItem {
- action: (contextMenuEvent: MouseEvent) => void;
+ action: (contextMenuEvent: TbContextMenuEvent) => void;
}
export interface WidgetContextMenuItem extends ContextMenuItem {
- action: (contextMenuEvent: MouseEvent, widget: Widget) => void;
+ action: (contextMenuEvent: TbContextMenuEvent, widget: Widget) => void;
}
export interface DashboardCallbacks {
@@ -94,7 +95,7 @@ export interface IDashboardComponent {
highlightWidget(widgetId: string, delay?: number);
selectWidget(widgetId: string, delay?: number);
getSelectedWidget(): Widget;
- getEventGridPosition(event: Event): WidgetPosition;
+ getEventGridPosition(event: TbContextMenuEvent | KeyboardEvent): WidgetPosition;
notifyGridsterOptionsChanged();
pauseChangeNotifications();
resumeChangeNotifications();
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 673bc21edb..9e739cafb4 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
@@ -415,7 +415,13 @@ export class WidgetContext {
this.dashboardWidget.updateWidgetParams();
}
try {
- this.changeDetectorValue.detectChanges();
+ if (this.ngZone) {
+ this.ngZone.run(() => {
+ this.changeDetectorValue?.detectChanges();
+ });
+ } else {
+ this.changeDetectorValue?.detectChanges();
+ }
} catch (e) {
// console.log(e);
}
@@ -425,7 +431,13 @@ export class WidgetContext {
detectContainerChanges() {
if (!this.destroyed) {
try {
- this.containerChangeDetectorValue.detectChanges();
+ if (this.ngZone) {
+ this.ngZone.run(() => {
+ this.containerChangeDetectorValue?.detectChanges();
+ });
+ } else {
+ this.containerChangeDetectorValue?.detectChanges();
+ }
} catch (e) {
// console.log(e);
}
diff --git a/ui-ngx/src/app/shared/models/jquery-event.models.ts b/ui-ngx/src/app/shared/models/jquery-event.models.ts
index b893da758c..a054210672 100644
--- a/ui-ngx/src/app/shared/models/jquery-event.models.ts
+++ b/ui-ngx/src/app/shared/models/jquery-event.models.ts
@@ -19,6 +19,8 @@ import Timeout = NodeJS.Timeout;
export interface TbContextMenuEvent extends Event {
clientX: number;
clientY: number;
+ pageX: number;
+ pageY: number;
ctrlKey: boolean;
metaKey: boolean;
}
@@ -41,6 +43,8 @@ export const initCustomJQueryEvents = () => {
const event = $.Event('tbcontextmenu', {
clientX: touch.clientX,
clientY: touch.clientY,
+ pageX: touch.pageX,
+ pageY: touch.pageY,
ctrlKey: false,
metaKey: false,
originalEvent: e
@@ -59,6 +63,8 @@ export const initCustomJQueryEvents = () => {
const event = $.Event('tbcontextmenu', {
clientX: e.originalEvent.clientX,
clientY: e.originalEvent.clientY,
+ pageX: e.originalEvent.pageX,
+ pageY: e.originalEvent.pageY,
ctrlKey: e.originalEvent.ctrlKey,
metaKey: e.originalEvent.metaKey,
originalEvent: e
diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts
index 65c09a52e1..e8b00ebab4 100644
--- a/ui-ngx/src/app/shared/models/widget.models.ts
+++ b/ui-ngx/src/app/shared/models/widget.models.ts
@@ -836,6 +836,8 @@ export interface WidgetPosition {
export interface WidgetSize {
sizeX: number;
sizeY: number;
+ preserveAspectRatio: boolean;
+ resizable: boolean;
}
export interface IWidgetSettingsComponent {