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 {