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;
private onIcon$: Observable<Element>;
private offIcon$: Observable<Element>;
protected onIconOffsetX: number = 0;
protected onIconOffsetY: number = 0;
protected constructor(protected widgetContext: WidgetContext,
protected svgShape: Svg,
@ -362,10 +365,14 @@ export abstract class PowerButtonShape {
take(1),
map((svgElement) => {
const element = new Element(svgElement.firstChild);
const iconGroup = this.svgShape.group();
element.addTo(iconGroup);
const box = element.bbox();
const scale = size / box.height;
element.scale(scale);
return element;
const scaledBox = iconGroup.bbox();
iconGroup.translate(-scaledBox.cx, -scaledBox.cy);
return iconGroup;
}),
catchError(() => of(null)
));
@ -416,8 +423,15 @@ export abstract class PowerButtonShape {
public drawOffShape(centerGroup: G, label: boolean, labelWeight?: string, circleStroke?: boolean) {
if (this.icons.offButtonIcon.showIcon) {
this.createIconElement(this.icons.offButtonIcon.icon, this.icons.offButtonIcon.iconSize).subscribe(icon =>
this.offPowerSymbolIcon = icon.center(cx, cy).addTo(centerGroup));
this.offIcon$ = this.createIconElement(this.icons.offButtonIcon.icon, this.icons.offButtonIcon.iconSize)
.pipe(shareReplay(1));
this.offIcon$.pipe(take(1)).subscribe(icon => {
this.offPowerSymbolIcon = icon;
icon.translate(cx, cy);
centerGroup.add(icon);
});
} else {
if (label) {
this.offLabelShape = this.createOffLabel(labelWeight).addTo(centerGroup);
@ -434,9 +448,12 @@ export abstract class PowerButtonShape {
.pipe(shareReplay(1));
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)) {
this.onPowerSymbolIcon.addTo(onCenterGroup);
onCenterGroup.add(this.onPowerSymbolIcon);
}
if (isDefinedAndNotNull(mask)) {
this.createMask(mask, [this.onPowerSymbolIcon]);
@ -468,7 +485,7 @@ export abstract class PowerButtonShape {
public onCenterTimeLine(timeline: Timeline, label: boolean) {
if (this.icons.onButtonIcon.showIcon) {
if (this.onIcon$) {
this.onIcon$.subscribe(icon => icon.timeline(timeline))
this.onIcon$.subscribe(icon => icon.timeline(timeline));
}
} else {
if (label) {
@ -482,7 +499,7 @@ export abstract class PowerButtonShape {
public offCenterColor(mainColor: PowerButtonColor, label: boolean) {
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 {
if (label) {
this.offLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
@ -495,7 +512,7 @@ export abstract class PowerButtonShape {
public onCenterColor(mainColor: PowerButtonColor, label: boolean) {
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 {
if (label) {
this.onLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
@ -508,7 +525,12 @@ export abstract class PowerButtonShape {
public buttonAnimation(scale: number, label: boolean) {
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 {
if (label) {
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,
componentType: MarkerImageSettingsPanelComponent,
hostView: this.viewContainerRef,
preferredPlacement: 'left',
preferredPlacement: 'leftOnly',
context: {
markerImageSettings: this.modelValue,
},
isModal: true
isModal: true,
overlayStyle: {padding: '10px'}
});
markerImageSettingsPanelPopover.tbComponentRef.instance.popover = markerImageSettingsPanelPopover;
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,
componentType: ShapeFillImageSettingsPanelComponent,
hostView: this.viewContainerRef,
preferredPlacement: 'left',
preferredPlacement: 'leftOnly',
context: {
shapeFillImageSettings: this.modelValue,
},
isModal: true
isModal: true,
overlayStyle: {padding: '10px'}
}).tbComponentRef.instance.shapeFillImageSettingsApplied.subscribe((shapeFillImageSettings) => {
this.modelValue = shapeFillImageSettings;
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> = {
base_url: '/assets/tinymce',
suffix: '.min',
plugins: ['link', 'table', 'image', 'imagetools', 'lists', 'fullscreen'],
plugins: ['link', 'table', 'image', 'lists', 'fullscreen'],
menubar: 'edit insert view format',
toolbar: ['fontfamily fontsize | bold italic underline strikethrough forecolor backcolor',
'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 {
let result = "";
if (this.authService.redirectUrl) {
result += "?prevUri=" + this.authService.redirectUrl;
result += "?prevUri=" + encodeURIComponent(this.authService.redirectUrl);
}
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.
///
import { OverlayModule } from '@angular/cdk/overlay';
import { Overlay, OverlayContainer, OverlayModule } from '@angular/cdk/overlay';
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 { DynamicDialog, DynamicMatDialog } from './dynamic-dialog';
import { DynamicOverlay } from './dynamic-overlay';
@ -24,8 +24,11 @@ import { DynamicOverlayContainer } from './dynamic-overlay-container';
export const DYNAMIC_MAT_DIALOG_PROVIDERS = [
DynamicOverlayContainer,
{ provide: OverlayContainer, useExisting: DynamicOverlayContainer },
DynamicOverlay,
{ provide: Overlay, useExisting: DynamicOverlay },
DynamicDialog,
{ provide: Dialog, useExisting: DynamicDialog },
DynamicMatDialog,
{
provide: DEFAULT_DIALOG_CONFIG,

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

@ -14,18 +14,11 @@
/// limitations under the License.
///
import { Location } from "@angular/common";
import { Inject, Injectable, Injector, Optional, SkipSelf, TemplateRef } from '@angular/core';
import {
MAT_DIALOG_DEFAULT_OPTIONS,
MAT_DIALOG_SCROLL_STRATEGY,
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';
import { inject, Injectable, TemplateRef } from '@angular/core';
import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
import { DynamicOverlay } from './dynamic-overlay';
import { ComponentType } from '@angular/cdk/overlay';
import { Dialog } from '@angular/cdk/dialog';
export interface DynamicMatDialogConfig<D> extends MatDialogConfig<D> {
containerElement?: HTMLElement;
@ -34,25 +27,12 @@ export interface DynamicMatDialogConfig<D> extends MatDialogConfig<D> {
@Injectable()
export class DynamicMatDialog extends MatDialog {
private _customOverlay: DynamicOverlay;
private _customOverlay = inject(DynamicOverlay);
constructor( _overlay: DynamicOverlay,
_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> {
public override open<T, D = any, R = any>(component: ComponentType<T> | TemplateRef<T>, config?: DynamicMatDialogConfig<D>): MatDialogRef<T, R> {
if (config?.containerElement) {
config.containerElement.style.transform = 'translateZ(0)';
this._customOverlay.setContainerElement( config.containerElement );
this._customOverlay.setContainerElement(config.containerElement);
}
const ref = super.open(component, config);
if (config?.containerElement) {
@ -73,13 +53,4 @@ export class DynamicMatDialog extends MatDialog {
@Injectable()
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.
///
import {
Overlay,
ScrollStrategyOptions,
OverlayKeyboardDispatcher, OverlayOutsideClickDispatcher, OverlayPositionBuilder
} from '@angular/cdk/overlay';
import { ComponentFactoryResolver, Inject, Injectable, Injector, NgZone, DOCUMENT } from '@angular/core';
import { Overlay } from '@angular/cdk/overlay';
import { inject, Injectable } from '@angular/core';
import { DynamicOverlayContainer } from './dynamic-overlay-container';
import { Location } from '@angular/common';
import { Directionality } from '@angular/cdk/bidi';
@Injectable()
export class DynamicOverlay extends Overlay {
private _dynamicOverlayContainer: DynamicOverlayContainer;
private _dynamicOverlayContainer = inject(DynamicOverlayContainer);
constructor( scrollStrategies: ScrollStrategyOptions,
_overlayContainer: DynamicOverlayContainer,
_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 );
public setContainerElement(containerElement: HTMLElement): void {
this._dynamicOverlayContainer.setContainerElement(containerElement);
}
}

Loading…
Cancel
Save