Browse Source

Merge pull request #15014 from thingsboard/rc

rc to master
pull/15033/head
Vladyslav Prykhodko 8 months ago
committed by GitHub
parent
commit
65560bd4a0
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 31
      ui-ngx/patches/ngx-hm-carousel+19.0.0.patch
  2. 40
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts
  3. 5
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings.component.ts
  4. 5
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings.component.ts
  5. 2
      ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts
  6. 2
      ui-ngx/src/app/modules/login/pages/login/login.component.ts
  7. 7
      ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-dialog.module.ts
  8. 45
      ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-dialog.ts
  9. 43
      ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-overlay.ts

31
ui-ngx/patches/ngx-hm-carousel+19.0.0.patch

@ -0,0 +1,31 @@
diff --git a/node_modules/ngx-hm-carousel/fesm2022/ngx-hm-carousel.mjs b/node_modules/ngx-hm-carousel/fesm2022/ngx-hm-carousel.mjs
index 117f782..70e49a7 100644
--- a/node_modules/ngx-hm-carousel/fesm2022/ngx-hm-carousel.mjs
+++ b/node_modules/ngx-hm-carousel/fesm2022/ngx-hm-carousel.mjs
@@ -1,5 +1,5 @@
import * as i0 from '@angular/core';
-import { Directive, inject, ViewContainerRef, TemplateRef, input, PLATFORM_ID, DestroyRef, Renderer2, NgZone, ChangeDetectorRef, viewChild, ElementRef, contentChildren, contentChild, computed, signal, effect, forwardRef, Component, ChangeDetectionStrategy } from '@angular/core';
+import { Directive, inject, ViewContainerRef, TemplateRef, input, PLATFORM_ID, DestroyRef, Renderer2, NgZone, ChangeDetectorRef, viewChild, ElementRef, contentChildren, contentChild, computed, signal, effect, forwardRef, Component, ChangeDetectionStrategy, afterNextRender } from '@angular/core';
import { DOCUMENT, isPlatformBrowser, NgTemplateOutlet, AsyncPipe } from '@angular/common';
import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
@@ -340,7 +340,7 @@ class NgxHmCarouselComponent {
});
});
});
- const effectRef = effect(() => {
+ afterNextRender(() => {
this.rootElm = this.container().nativeElement;
this.containerElm = this.rootElm.children[0];
this.init();
@@ -365,10 +365,6 @@ class NgxHmCarouselComponent {
])
.pipe(takeUntilDestroyed(this._destroyRef))
.subscribe();
- // only exec once
- effectRef.destroy();
- }, {
- allowSignalWrites: true,
});
}
ngOnDestroy() {

40
ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts

@ -337,6 +337,9 @@ export abstract class PowerButtonShape {
protected onPowerSymbolLine: Path; protected onPowerSymbolLine: Path;
private onIcon$: Observable<Element>; private onIcon$: Observable<Element>;
private offIcon$: Observable<Element>;
protected onIconOffsetX: number = 0;
protected onIconOffsetY: number = 0;
protected constructor(protected widgetContext: WidgetContext, protected constructor(protected widgetContext: WidgetContext,
protected svgShape: Svg, protected svgShape: Svg,
@ -362,10 +365,14 @@ export abstract class PowerButtonShape {
take(1), take(1),
map((svgElement) => { map((svgElement) => {
const element = new Element(svgElement.firstChild); const element = new Element(svgElement.firstChild);
const iconGroup = this.svgShape.group();
element.addTo(iconGroup);
const box = element.bbox(); const box = element.bbox();
const scale = size / box.height; const scale = size / box.height;
element.scale(scale); element.scale(scale);
return element; const scaledBox = iconGroup.bbox();
iconGroup.translate(-scaledBox.cx, -scaledBox.cy);
return iconGroup;
}), }),
catchError(() => of(null) catchError(() => of(null)
)); ));
@ -416,8 +423,15 @@ export abstract class PowerButtonShape {
public drawOffShape(centerGroup: G, label: boolean, labelWeight?: string, circleStroke?: boolean) { public drawOffShape(centerGroup: G, label: boolean, labelWeight?: string, circleStroke?: boolean) {
if (this.icons.offButtonIcon.showIcon) { if (this.icons.offButtonIcon.showIcon) {
this.createIconElement(this.icons.offButtonIcon.icon, this.icons.offButtonIcon.iconSize).subscribe(icon => this.offIcon$ = this.createIconElement(this.icons.offButtonIcon.icon, this.icons.offButtonIcon.iconSize)
this.offPowerSymbolIcon = icon.center(cx, cy).addTo(centerGroup)); .pipe(shareReplay(1));
this.offIcon$.pipe(take(1)).subscribe(icon => {
this.offPowerSymbolIcon = icon;
icon.translate(cx, cy);
centerGroup.add(icon);
});
} else { } else {
if (label) { if (label) {
this.offLabelShape = this.createOffLabel(labelWeight).addTo(centerGroup); this.offLabelShape = this.createOffLabel(labelWeight).addTo(centerGroup);
@ -434,9 +448,12 @@ export abstract class PowerButtonShape {
.pipe(shareReplay(1)); .pipe(shareReplay(1));
this.onIcon$.subscribe(icon => { this.onIcon$.subscribe(icon => {
this.onPowerSymbolIcon = icon.center(cx, cy); const iconBox = icon.bbox();
this.onIconOffsetX = iconBox.cx;
this.onIconOffsetY = iconBox.cy;
this.onPowerSymbolIcon = icon.translate(cx, cy);
if (isDefinedAndNotNull(onCenterGroup)) { if (isDefinedAndNotNull(onCenterGroup)) {
this.onPowerSymbolIcon.addTo(onCenterGroup); onCenterGroup.add(this.onPowerSymbolIcon);
} }
if (isDefinedAndNotNull(mask)) { if (isDefinedAndNotNull(mask)) {
this.createMask(mask, [this.onPowerSymbolIcon]); this.createMask(mask, [this.onPowerSymbolIcon]);
@ -468,7 +485,7 @@ export abstract class PowerButtonShape {
public onCenterTimeLine(timeline: Timeline, label: boolean) { public onCenterTimeLine(timeline: Timeline, label: boolean) {
if (this.icons.onButtonIcon.showIcon) { if (this.icons.onButtonIcon.showIcon) {
if (this.onIcon$) { if (this.onIcon$) {
this.onIcon$.subscribe(icon => icon.timeline(timeline)) this.onIcon$.subscribe(icon => icon.timeline(timeline));
} }
} else { } else {
if (label) { if (label) {
@ -482,7 +499,7 @@ export abstract class PowerButtonShape {
public offCenterColor(mainColor: PowerButtonColor, label: boolean) { public offCenterColor(mainColor: PowerButtonColor, label: boolean) {
if (this.icons.offButtonIcon.showIcon) { if (this.icons.offButtonIcon.showIcon) {
this.offPowerSymbolIcon.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity}); this.offIcon$.subscribe(icon => icon.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity}))
} else { } else {
if (label) { if (label) {
this.offLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity}); this.offLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
@ -495,7 +512,7 @@ export abstract class PowerButtonShape {
public onCenterColor(mainColor: PowerButtonColor, label: boolean) { public onCenterColor(mainColor: PowerButtonColor, label: boolean) {
if (this.icons.onButtonIcon.showIcon) { if (this.icons.onButtonIcon.showIcon) {
this.onPowerSymbolIcon.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity}); this.onIcon$.subscribe((icon)=> icon.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity}))
} else { } else {
if (label) { if (label) {
this.onLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity}); this.onLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
@ -508,7 +525,12 @@ export abstract class PowerButtonShape {
public buttonAnimation(scale: number, label: boolean) { public buttonAnimation(scale: number, label: boolean) {
if (this.icons.onButtonIcon.showIcon) { if (this.icons.onButtonIcon.showIcon) {
powerButtonAnimation(this.onPowerSymbolIcon).transform({scale}); const translateX = cx - this.onIconOffsetX;
const translateY = cy - this.onIconOffsetY;
powerButtonAnimation(this.onPowerSymbolIcon).transform({
scale: scale,
translate: [translateX, translateY]
});
} else { } else {
if (label) { if (label) {
powerButtonAnimation(this.onLabelShape).transform({scale, origin: {x: cx, y: cy}}); powerButtonAnimation(this.onLabelShape).transform({scale, origin: {x: cx, y: cy}});

5
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings.component.ts

@ -82,11 +82,12 @@ export class MarkerImageSettingsComponent implements ControlValueAccessor {
renderer: this.renderer, renderer: this.renderer,
componentType: MarkerImageSettingsPanelComponent, componentType: MarkerImageSettingsPanelComponent,
hostView: this.viewContainerRef, hostView: this.viewContainerRef,
preferredPlacement: 'left', preferredPlacement: 'leftOnly',
context: { context: {
markerImageSettings: this.modelValue, markerImageSettings: this.modelValue,
}, },
isModal: true isModal: true,
overlayStyle: {padding: '10px'}
}); });
markerImageSettingsPanelPopover.tbComponentRef.instance.popover = markerImageSettingsPanelPopover; markerImageSettingsPanelPopover.tbComponentRef.instance.popover = markerImageSettingsPanelPopover;
markerImageSettingsPanelPopover.tbComponentRef.instance.markerImageSettingsApplied.subscribe((markerImageSettings) => { markerImageSettingsPanelPopover.tbComponentRef.instance.markerImageSettingsApplied.subscribe((markerImageSettings) => {

5
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/shape-fill-image-settings.component.ts

@ -82,11 +82,12 @@ export class ShapeFillImageSettingsComponent implements ControlValueAccessor {
renderer: this.renderer, renderer: this.renderer,
componentType: ShapeFillImageSettingsPanelComponent, componentType: ShapeFillImageSettingsPanelComponent,
hostView: this.viewContainerRef, hostView: this.viewContainerRef,
preferredPlacement: 'left', preferredPlacement: 'leftOnly',
context: { context: {
shapeFillImageSettings: this.modelValue, shapeFillImageSettings: this.modelValue,
}, },
isModal: true isModal: true,
overlayStyle: {padding: '10px'}
}).tbComponentRef.instance.shapeFillImageSettingsApplied.subscribe((shapeFillImageSettings) => { }).tbComponentRef.instance.shapeFillImageSettingsApplied.subscribe((shapeFillImageSettings) => {
this.modelValue = shapeFillImageSettings; this.modelValue = shapeFillImageSettings;
this.propagateChange(this.modelValue); this.propagateChange(this.modelValue);

2
ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts

@ -48,7 +48,7 @@ export class EditorPanelComponent implements OnInit {
tinyMceOptions: Partial<EditorOptions> = { tinyMceOptions: Partial<EditorOptions> = {
base_url: '/assets/tinymce', base_url: '/assets/tinymce',
suffix: '.min', suffix: '.min',
plugins: ['link', 'table', 'image', 'imagetools', 'lists', 'fullscreen'], plugins: ['link', 'table', 'image', 'lists', 'fullscreen'],
menubar: 'edit insert view format', menubar: 'edit insert view format',
toolbar: ['fontfamily fontsize | bold italic underline strikethrough forecolor backcolor', toolbar: ['fontfamily fontsize | bold italic underline strikethrough forecolor backcolor',
'alignleft aligncenter alignright alignjustify | bullist | link table image | fullscreen'], 'alignleft aligncenter alignright alignjustify | bullist | link table image | fullscreen'],

2
ui-ngx/src/app/modules/login/pages/login/login.component.ts

@ -76,7 +76,7 @@ export class LoginComponent extends PageComponent implements OnInit {
getOAuth2Uri(oauth2Client: OAuth2ClientLoginInfo): string { getOAuth2Uri(oauth2Client: OAuth2ClientLoginInfo): string {
let result = ""; let result = "";
if (this.authService.redirectUrl) { if (this.authService.redirectUrl) {
result += "?prevUri=" + this.authService.redirectUrl; result += "?prevUri=" + encodeURIComponent(this.authService.redirectUrl);
} }
return oauth2Client.url + result; return oauth2Client.url + result;
} }

7
ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-dialog.module.ts

@ -14,9 +14,9 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { OverlayModule } from '@angular/cdk/overlay'; import { Overlay, OverlayContainer, OverlayModule } from '@angular/cdk/overlay';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { DEFAULT_DIALOG_CONFIG, DialogConfig, DialogModule } from '@angular/cdk/dialog'; import { DEFAULT_DIALOG_CONFIG, Dialog, DialogConfig, DialogModule } from '@angular/cdk/dialog';
import { MatDialogModule } from '@angular/material/dialog'; import { MatDialogModule } from '@angular/material/dialog';
import { DynamicDialog, DynamicMatDialog } from './dynamic-dialog'; import { DynamicDialog, DynamicMatDialog } from './dynamic-dialog';
import { DynamicOverlay } from './dynamic-overlay'; import { DynamicOverlay } from './dynamic-overlay';
@ -24,8 +24,11 @@ import { DynamicOverlayContainer } from './dynamic-overlay-container';
export const DYNAMIC_MAT_DIALOG_PROVIDERS = [ export const DYNAMIC_MAT_DIALOG_PROVIDERS = [
DynamicOverlayContainer, DynamicOverlayContainer,
{ provide: OverlayContainer, useExisting: DynamicOverlayContainer },
DynamicOverlay, DynamicOverlay,
{ provide: Overlay, useExisting: DynamicOverlay },
DynamicDialog, DynamicDialog,
{ provide: Dialog, useExisting: DynamicDialog },
DynamicMatDialog, DynamicMatDialog,
{ {
provide: DEFAULT_DIALOG_CONFIG, provide: DEFAULT_DIALOG_CONFIG,

45
ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-dialog.ts

@ -14,18 +14,11 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Location } from "@angular/common"; import { inject, Injectable, TemplateRef } from '@angular/core';
import { Inject, Injectable, Injector, Optional, SkipSelf, TemplateRef } from '@angular/core'; import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
import { import { DynamicOverlay } from './dynamic-overlay';
MAT_DIALOG_DEFAULT_OPTIONS, import { ComponentType } from '@angular/cdk/overlay';
MAT_DIALOG_SCROLL_STRATEGY, import { Dialog } from '@angular/cdk/dialog';
MatDialog,
MatDialogConfig, MatDialogRef
} from '@angular/material/dialog';
import { DynamicOverlay } from "./dynamic-overlay";
import { DynamicOverlayContainer } from '@shared/components/dialog/dynamic/dynamic-overlay-container';
import { ComponentType, ScrollStrategy } from '@angular/cdk/overlay';
import { DEFAULT_DIALOG_CONFIG, Dialog, DialogConfig } from '@angular/cdk/dialog';
export interface DynamicMatDialogConfig<D> extends MatDialogConfig<D> { export interface DynamicMatDialogConfig<D> extends MatDialogConfig<D> {
containerElement?: HTMLElement; containerElement?: HTMLElement;
@ -34,25 +27,12 @@ export interface DynamicMatDialogConfig<D> extends MatDialogConfig<D> {
@Injectable() @Injectable()
export class DynamicMatDialog extends MatDialog { export class DynamicMatDialog extends MatDialog {
private _customOverlay: DynamicOverlay; private _customOverlay = inject(DynamicOverlay);
constructor( _overlay: DynamicOverlay, public override open<T, D = any, R = any>(component: ComponentType<T> | TemplateRef<T>, config?: DynamicMatDialogConfig<D>): MatDialogRef<T, R> {
_injector: Injector,
@Optional() location: Location,
@Inject( MAT_DIALOG_DEFAULT_OPTIONS ) _defaultOptions: MatDialogConfig,
@Inject( MAT_DIALOG_SCROLL_STRATEGY ) _scrollStrategy: ScrollStrategy,
@Optional() @SkipSelf() _parentDialog:DynamicMatDialog,
_overlayContainer: DynamicOverlayContainer) {
super( _overlay, _injector, location, _defaultOptions, _scrollStrategy, _parentDialog, _overlayContainer );
this._dialog = _injector.get(DynamicDialog);
this._customOverlay = _overlay;
}
public open<T, D = any, R = any>(component: ComponentType<T> | TemplateRef<T>, config?: DynamicMatDialogConfig<D>): MatDialogRef<T, R> {
if (config?.containerElement) { if (config?.containerElement) {
config.containerElement.style.transform = 'translateZ(0)'; config.containerElement.style.transform = 'translateZ(0)';
this._customOverlay.setContainerElement( config.containerElement ); this._customOverlay.setContainerElement(config.containerElement);
} }
const ref = super.open(component, config); const ref = super.open(component, config);
if (config?.containerElement) { if (config?.containerElement) {
@ -73,13 +53,4 @@ export class DynamicMatDialog extends MatDialog {
@Injectable() @Injectable()
export class DynamicDialog extends Dialog { export class DynamicDialog extends Dialog {
constructor( _overlay: DynamicOverlay,
_injector: Injector,
@Inject( DEFAULT_DIALOG_CONFIG ) _defaultOptions: DialogConfig,
@Inject( MAT_DIALOG_SCROLL_STRATEGY ) _scrollStrategy: ScrollStrategy,
@Optional() @SkipSelf() _parentDialog: DynamicDialog,
_overlayContainer: DynamicOverlayContainer) {
super( _overlay, _injector, _defaultOptions, _parentDialog, _overlayContainer, _scrollStrategy );
}
} }

43
ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-overlay.ts

@ -14,49 +14,16 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { Overlay } from '@angular/cdk/overlay';
Overlay, import { inject, Injectable } from '@angular/core';
ScrollStrategyOptions,
OverlayKeyboardDispatcher, OverlayOutsideClickDispatcher, OverlayPositionBuilder
} from '@angular/cdk/overlay';
import { ComponentFactoryResolver, Inject, Injectable, Injector, NgZone, DOCUMENT } from '@angular/core';
import { DynamicOverlayContainer } from './dynamic-overlay-container'; import { DynamicOverlayContainer } from './dynamic-overlay-container';
import { Location } from '@angular/common';
import { Directionality } from '@angular/cdk/bidi';
@Injectable() @Injectable()
export class DynamicOverlay extends Overlay { export class DynamicOverlay extends Overlay {
private _dynamicOverlayContainer: DynamicOverlayContainer; private _dynamicOverlayContainer = inject(DynamicOverlayContainer);
constructor( scrollStrategies: ScrollStrategyOptions, public setContainerElement(containerElement: HTMLElement): void {
_overlayContainer: DynamicOverlayContainer, this._dynamicOverlayContainer.setContainerElement(containerElement);
_componentFactoryResolver: ComponentFactoryResolver,
_positionBuilder: OverlayPositionBuilder,
_keyboardDispatcher: OverlayKeyboardDispatcher,
_injector: Injector,
_ngZone: NgZone,
@Inject(DOCUMENT) document: Document,
_directionality: Directionality,
_location: Location,
_outsideClickDispatcher: OverlayOutsideClickDispatcher) {
super( scrollStrategies,
_overlayContainer,
_componentFactoryResolver,
_positionBuilder,
_keyboardDispatcher,
_injector,
_ngZone,
document,
_directionality,
_location,
_outsideClickDispatcher);
this._dynamicOverlayContainer = _overlayContainer;
}
public setContainerElement(containerElement:HTMLElement ): void {
this._dynamicOverlayContainer.setContainerElement( containerElement );
} }
} }

Loading…
Cancel
Save