UI: mobile app qr code improvements, cleanup
This commit is contained in:
		
							parent
							
								
									9d71bb77ea
								
							
						
					
					
						commit
						45ed484c2a
					
				@ -17,7 +17,7 @@
 | 
				
			|||||||
    "cards.label_widget",
 | 
					    "cards.label_widget",
 | 
				
			||||||
    "cards.dashboard_state_widget",
 | 
					    "cards.dashboard_state_widget",
 | 
				
			||||||
    "cards.qr_code",
 | 
					    "cards.qr_code",
 | 
				
			||||||
    "cards.mobile_app_qr_code",
 | 
					    "mobile_app_qr_code",
 | 
				
			||||||
    "cards.attributes_card",
 | 
					    "cards.attributes_card",
 | 
				
			||||||
    "cards.html_card",
 | 
					    "cards.html_card",
 | 
				
			||||||
    "cards.html_value_card",
 | 
					    "cards.html_value_card",
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,6 @@
 | 
				
			|||||||
    "home_page_widgets.quick_links",
 | 
					    "home_page_widgets.quick_links",
 | 
				
			||||||
    "home_page_widgets.documentation_links",
 | 
					    "home_page_widgets.documentation_links",
 | 
				
			||||||
    "home_page_widgets.dashboards",
 | 
					    "home_page_widgets.dashboards",
 | 
				
			||||||
    "home_page_widgets.usage_info",
 | 
					    "home_page_widgets.usage_info"
 | 
				
			||||||
    "home_page_widgets.home_page_mobile_app_qr_code"
 | 
					 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -83,7 +83,7 @@ export const selectMobileQrEnabled = createSelector(
 | 
				
			|||||||
  (state: AuthState) => state.mobileQrEnabled
 | 
					  (state: AuthState) => state.mobileQrEnabled
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const selectPersistDeviceStateToTelemetryAndMobileQrEnabled = createSelector(
 | 
					export const selectHomeDashboardParams = createSelector(
 | 
				
			||||||
  selectPersistDeviceStateToTelemetry,
 | 
					  selectPersistDeviceStateToTelemetry,
 | 
				
			||||||
  selectMobileQrEnabled,
 | 
					  selectMobileQrEnabled,
 | 
				
			||||||
  (persistDeviceStateToTelemetry, mobileQrEnabled) => ({persistDeviceStateToTelemetry, mobileQrEnabled})
 | 
					  (persistDeviceStateToTelemetry, mobileQrEnabled) => ({persistDeviceStateToTelemetry, mobileQrEnabled})
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ import { HttpClient } from '@angular/common/http';
 | 
				
			|||||||
import { Injectable } from '@angular/core';
 | 
					import { Injectable } from '@angular/core';
 | 
				
			||||||
import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils';
 | 
					import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils';
 | 
				
			||||||
import { Observable } from 'rxjs';
 | 
					import { Observable } from 'rxjs';
 | 
				
			||||||
import { MobileAppQRCodeSettings } from '@shared/models/mobile-app.models';
 | 
					import { MobileAppSettings } from '@shared/models/mobile-app.models';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable({
 | 
					@Injectable({
 | 
				
			||||||
  providedIn: 'root'
 | 
					  providedIn: 'root'
 | 
				
			||||||
@ -30,15 +30,15 @@ export class MobileAppService {
 | 
				
			|||||||
  ) {
 | 
					  ) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public getMobileAppSettings(config?: RequestConfig): Observable<MobileAppQRCodeSettings> {
 | 
					  public getMobileAppSettings(config?: RequestConfig): Observable<MobileAppSettings> {
 | 
				
			||||||
    return this.http.get<MobileAppQRCodeSettings>(`/api/mobile/app/settings`, defaultHttpOptionsFromConfig(config));
 | 
					    return this.http.get<MobileAppSettings>(`/api/mobile/app/settings`, defaultHttpOptionsFromConfig(config));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public saveMobileAppSettings(mobileAppSettings: MobileAppQRCodeSettings, config?: RequestConfig): Observable<MobileAppQRCodeSettings> {
 | 
					  public saveMobileAppSettings(mobileAppSettings: MobileAppSettings, config?: RequestConfig): Observable<MobileAppSettings> {
 | 
				
			||||||
    return this.http.post<MobileAppQRCodeSettings>(`/api/mobile/app/settings`, mobileAppSettings, defaultHttpOptionsFromConfig(config));
 | 
					    return this.http.post<MobileAppSettings>(`/api/mobile/app/settings`, mobileAppSettings, defaultHttpOptionsFromConfig(config));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public getMobileAppDeepLink( config?: RequestConfig): Observable<string> {
 | 
					  public getMobileAppDeepLink(config?: RequestConfig): Observable<string> {
 | 
				
			||||||
    return this.http.get<string>(`/api/mobile/deepLink`, defaultHttpOptionsFromConfig(config));
 | 
					    return this.http.get<string>(`/api/mobile/deepLink`, defaultHttpOptionsFromConfig(config));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -22,23 +22,20 @@ import {
 | 
				
			|||||||
  QRCodeConfig
 | 
					  QRCodeConfig
 | 
				
			||||||
} from '@shared/models/mobile-app.models';
 | 
					} from '@shared/models/mobile-app.models';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type MobileAppQrCodeWidgetSettings = {
 | 
					export interface MobileAppQrCodeWidgetSettings {
 | 
				
			||||||
  useDefaultApp: boolean;
 | 
					  useSystemSettings: boolean;
 | 
				
			||||||
  androidConfig: AndroidConfig;
 | 
					  androidConfig: Pick<AndroidConfig, 'enabled'>;
 | 
				
			||||||
  iosConfig: IosConfig;
 | 
					  iosConfig: Pick<IosConfig, 'enabled'>;
 | 
				
			||||||
  qrCodeConfig: Omit<QRCodeConfig, 'showOnHomePage'>;
 | 
					  qrCodeConfig: Omit<QRCodeConfig, 'showOnHomePage'>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const mobileAppQrCodeWidgetDefaultSettings: MobileAppQrCodeWidgetSettings = {
 | 
					export const mobileAppQrCodeWidgetDefaultSettings: MobileAppQrCodeWidgetSettings = {
 | 
				
			||||||
  useDefaultApp: true,
 | 
					  useSystemSettings: true,
 | 
				
			||||||
  androidConfig: {
 | 
					  androidConfig: {
 | 
				
			||||||
    enabled: true,
 | 
					    enabled: true
 | 
				
			||||||
    appPackage: '',
 | 
					 | 
				
			||||||
    sha256CertFingerprints: ''
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  iosConfig: {
 | 
					  iosConfig: {
 | 
				
			||||||
    enabled: true,
 | 
					    enabled: true
 | 
				
			||||||
    appId: ''
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  qrCodeConfig: {
 | 
					  qrCodeConfig: {
 | 
				
			||||||
    badgeEnabled: true,
 | 
					    badgeEnabled: true,
 | 
				
			||||||
 | 
				
			|||||||
@ -15,16 +15,12 @@
 | 
				
			|||||||
    limitations under the License.
 | 
					    limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-->
 | 
					-->
 | 
				
			||||||
<div *ngIf="!previewMode && !ctx" class="tb-title" translate>admin.mobile-app.connect-mobile-app</div>
 | 
					 | 
				
			||||||
<div class="tb-flex column center align-center">
 | 
					<div class="tb-flex column center align-center">
 | 
				
			||||||
  <div class="tb-flex row align-center shrink"
 | 
					  <div class="tb-flex row align-center shrink"
 | 
				
			||||||
       [class.row]="mobileAppSettings?.qrCodeConfig.badgePosition === badgePosition.RIGHT"
 | 
					       [class.row]="mobileAppSettings?.qrCodeConfig.badgePosition === badgePosition.RIGHT"
 | 
				
			||||||
       [class.row-reverse]="mobileAppSettings?.qrCodeConfig.badgePosition === badgePosition.LEFT">
 | 
					       [class.row-reverse]="mobileAppSettings?.qrCodeConfig.badgePosition === badgePosition.LEFT">
 | 
				
			||||||
<!--    <canvas #canvas class="tb-qrcode"></canvas>-->
 | 
					 | 
				
			||||||
    <canvas #canvas class="tb-qrcode"></canvas>
 | 
					    <canvas #canvas class="tb-qrcode"></canvas>
 | 
				
			||||||
    <div *ngIf="mobileAppSettings?.qrCodeConfig.badgeEnabled"
 | 
					    <div class="tb-flex column" *ngIf="mobileAppSettings?.qrCodeConfig.badgeEnabled && showBadgeContainer">
 | 
				
			||||||
         class="tb-flex column tb-badge-container"
 | 
					 | 
				
			||||||
         [class.tb-badge-container]="!previewMode && !ctx">
 | 
					 | 
				
			||||||
      <ng-container *ngIf="mobileAppSettings.qrCodeConfig.badgeStyle === badgeStyle.ORIGINAL;else white">
 | 
					      <ng-container *ngIf="mobileAppSettings.qrCodeConfig.badgeStyle === badgeStyle.ORIGINAL;else white">
 | 
				
			||||||
        <img *ngIf="mobileAppSettings.iosConfig.enabled" [src]="badgeStyleURLMap.get(badgeStyle.ORIGINAL).iOS">
 | 
					        <img *ngIf="mobileAppSettings.iosConfig.enabled" [src]="badgeStyleURLMap.get(badgeStyle.ORIGINAL).iOS">
 | 
				
			||||||
        <img *ngIf="mobileAppSettings.androidConfig.enabled" [src]="badgeStyleURLMap.get(badgeStyle.ORIGINAL).android">
 | 
					        <img *ngIf="mobileAppSettings.androidConfig.enabled" [src]="badgeStyleURLMap.get(badgeStyle.ORIGINAL).android">
 | 
				
			||||||
 | 
				
			|||||||
@ -23,24 +23,6 @@
 | 
				
			|||||||
  background-color: transparent;
 | 
					  background-color: transparent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tb-title {
 | 
					 | 
				
			||||||
  padding-bottom: 12px;
 | 
					 | 
				
			||||||
  align-self: start;
 | 
					 | 
				
			||||||
  font-weight: 600;
 | 
					 | 
				
			||||||
  font-size: 20px;
 | 
					 | 
				
			||||||
  line-height: 24px;
 | 
					 | 
				
			||||||
  letter-spacing: 0.1px;
 | 
					 | 
				
			||||||
  color: rgba(0, 0, 0, 0.76);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @media #{$mat-md-lg} {
 | 
					 | 
				
			||||||
    padding-bottom: 0;
 | 
					 | 
				
			||||||
    font-weight: 500;
 | 
					 | 
				
			||||||
    font-size: 14px;
 | 
					 | 
				
			||||||
    line-height: 20px;
 | 
					 | 
				
			||||||
    letter-spacing: 0.25px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.tb-qrcode-label {
 | 
					.tb-qrcode-label {
 | 
				
			||||||
  font-size: 14px;
 | 
					  font-size: 14px;
 | 
				
			||||||
  color: rgba(0, 0, 0, 0.54);
 | 
					  color: rgba(0, 0, 0, 0.54);
 | 
				
			||||||
@ -56,8 +38,3 @@
 | 
				
			|||||||
  border-radius: 6px;
 | 
					  border-radius: 6px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tb-badge-container {
 | 
					 | 
				
			||||||
  @media #{$mat-md} {
 | 
					 | 
				
			||||||
    display: none;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -14,97 +14,108 @@
 | 
				
			|||||||
/// limitations under the License.
 | 
					/// limitations under the License.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
 | 
					import { ChangeDetectorRef, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
 | 
				
			||||||
import { PageComponent } from '@shared/components/page.component';
 | 
					import { PageComponent } from '@shared/components/page.component';
 | 
				
			||||||
import { AppState } from '@core/core.state';
 | 
					import { AppState } from '@core/core.state';
 | 
				
			||||||
import { Store } from '@ngrx/store';
 | 
					import { Store } from '@ngrx/store';
 | 
				
			||||||
import { BadgePosition, BadgeStyle, badgeStyleURLMap, MobileAppQRCodeSettings } from '@shared/models/mobile-app.models';
 | 
					import { BadgePosition, BadgeStyle, badgeStyleURLMap, MobileAppSettings } from '@shared/models/mobile-app.models';
 | 
				
			||||||
import { MobileAppService } from '@core/http/mobile-app.service';
 | 
					import { MobileAppService } from '@core/http/mobile-app.service';
 | 
				
			||||||
import { WidgetContext } from '@home/models/widget-component.models';
 | 
					import { WidgetContext } from '@home/models/widget-component.models';
 | 
				
			||||||
import { UtilsService } from '@core/services/utils.service';
 | 
					import { UtilsService } from '@core/services/utils.service';
 | 
				
			||||||
import { interval, mergeMap, Observable, Subject, takeUntil } from 'rxjs';
 | 
					import { Subject } from 'rxjs';
 | 
				
			||||||
import { MINUTE } from '@shared/models/time/time.models';
 | 
					import { MINUTE } from '@shared/models/time/time.models';
 | 
				
			||||||
import { coerceBoolean } from '@shared/decorators/coercion';
 | 
					 | 
				
			||||||
import { MobileAppQrCodeWidgetSettings } from '@home/components/widget/lib/cards/mobile-app-qr-code-widget.models';
 | 
					import { MobileAppQrCodeWidgetSettings } from '@home/components/widget/lib/cards/mobile-app-qr-code-widget.models';
 | 
				
			||||||
 | 
					import { isDefinedAndNotNull } from '@core/utils';
 | 
				
			||||||
 | 
					import { ResizeObserver } from '@juggle/resize-observer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'tb-mobile-app-qrcode-widget',
 | 
					  selector: 'tb-mobile-app-qrcode-widget',
 | 
				
			||||||
  templateUrl: './mobile-app-qrcode-widget.component.html',
 | 
					  templateUrl: './mobile-app-qrcode-widget.component.html',
 | 
				
			||||||
  styleUrls: ['./mobile-app-qrcode-widget.component.scss']
 | 
					  styleUrls: ['./mobile-app-qrcode-widget.component.scss']
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
					export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Input()
 | 
					  @Input()
 | 
				
			||||||
  ctx: WidgetContext;
 | 
					  ctx: WidgetContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Input()
 | 
					  @Input()
 | 
				
			||||||
  @coerceBoolean()
 | 
					  set mobileAppSettings(settings: MobileAppSettings | MobileAppQrCodeWidgetSettings) {
 | 
				
			||||||
  previewMode: boolean;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Input()
 | 
					 | 
				
			||||||
  set mobileAppSettings(settings: MobileAppQRCodeSettings | MobileAppQrCodeWidgetSettings) {
 | 
					 | 
				
			||||||
    if (settings) {
 | 
					    if (settings) {
 | 
				
			||||||
      this.mobileAppSettingsValue = settings;
 | 
					      this.mobileAppSettingsValue = settings;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get mobileAppSettings() {
 | 
					  get mobileAppSettings(): MobileAppSettings | MobileAppQrCodeWidgetSettings {
 | 
				
			||||||
    return this.mobileAppSettingsValue;
 | 
					    return this.mobileAppSettingsValue;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @ViewChild('canvas', {static: false}) canvasRef: ElementRef<HTMLCanvasElement>;
 | 
					  @ViewChild('canvas', {static: true}) canvasRef: ElementRef<HTMLCanvasElement>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private readonly destroy$ = new Subject<void>();
 | 
					  private readonly destroy$ = new Subject<void>();
 | 
				
			||||||
 | 
					  private widgetResize$: ResizeObserver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  badgeStyle = BadgeStyle;
 | 
					  badgeStyle = BadgeStyle;
 | 
				
			||||||
  badgePosition = BadgePosition;
 | 
					  badgePosition = BadgePosition;
 | 
				
			||||||
  badgeStyleURLMap = badgeStyleURLMap;
 | 
					  badgeStyleURLMap = badgeStyleURLMap;
 | 
				
			||||||
 | 
					  showBadgeContainer = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private mobileAppSettingsValue: MobileAppQRCodeSettings | MobileAppQrCodeWidgetSettings;
 | 
					  private mobileAppSettingsValue: MobileAppSettings | MobileAppQrCodeWidgetSettings;
 | 
				
			||||||
  private deepLinkTTL: number;
 | 
					  private deepLinkTTL: number;
 | 
				
			||||||
 | 
					  private deepLinkTTLTimeoutID: NodeJS.Timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(protected store: Store<AppState>,
 | 
					  constructor(protected store: Store<AppState>,
 | 
				
			||||||
              protected cd: ChangeDetectorRef,
 | 
					              protected cd: ChangeDetectorRef,
 | 
				
			||||||
              private mobileAppService: MobileAppService,
 | 
					              private mobileAppService: MobileAppService,
 | 
				
			||||||
              private utilsService: UtilsService) {
 | 
					              private utilsService: UtilsService,
 | 
				
			||||||
 | 
					              private elementRef: ElementRef) {
 | 
				
			||||||
    super(store);
 | 
					    super(store);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ngOnInit(): void {
 | 
					  ngOnInit(): void {
 | 
				
			||||||
    if (!this.previewMode) {
 | 
					    if (!this.mobileAppSettings) {
 | 
				
			||||||
      if (this.ctx) {
 | 
					      if (isDefinedAndNotNull(this.ctx.settings.useSystemSettings) && !this.ctx.settings.useSystemSettings) {
 | 
				
			||||||
        this.mobileAppSettings = this.ctx.settings;
 | 
					        this.mobileAppSettings = this.ctx.settings;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        this.mobileAppService.getMobileAppSettings().subscribe((settings => {
 | 
					        this.mobileAppService.getMobileAppSettings().subscribe((settings => {
 | 
				
			||||||
          this.mobileAppSettings = settings;
 | 
					          this.mobileAppSettings = settings;
 | 
				
			||||||
          this.cd.detectChanges();
 | 
					          this.cd.markForCheck();
 | 
				
			||||||
        }));
 | 
					        }));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					    this.initMobileAppQRCode();
 | 
				
			||||||
 | 
					    this.widgetResize$ = new ResizeObserver(() => {
 | 
				
			||||||
  ngAfterViewInit(): void {
 | 
					      const showHideBadgeContainer = this.elementRef.nativeElement.offsetWidth > 250;
 | 
				
			||||||
    this.getMobileAppDeepLink().subscribe(link => {
 | 
					      if (showHideBadgeContainer !== this.showBadgeContainer) {
 | 
				
			||||||
      this.deepLinkTTL = Number(this.utilsService.getQueryParam('ttl', link)) * MINUTE;
 | 
					        this.showBadgeContainer = showHideBadgeContainer;
 | 
				
			||||||
      this.updateQRCode(link);
 | 
					        this.cd.markForCheck();
 | 
				
			||||||
      interval(this.deepLinkTTL).pipe(
 | 
					      }
 | 
				
			||||||
        takeUntil(this.destroy$),
 | 
					 | 
				
			||||||
        mergeMap(() => this.getMobileAppDeepLink())
 | 
					 | 
				
			||||||
      ).subscribe(link => this.updateQRCode(link));
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    this.widgetResize$.observe(this.elementRef.nativeElement);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ngOnDestroy() {
 | 
					  ngOnDestroy() {
 | 
				
			||||||
 | 
					    if (this.widgetResize$) {
 | 
				
			||||||
 | 
					      this.widgetResize$.disconnect();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    super.ngOnDestroy();
 | 
					    super.ngOnDestroy();
 | 
				
			||||||
    this.destroy$.next();
 | 
					    this.destroy$.next();
 | 
				
			||||||
    this.destroy$.complete();
 | 
					    this.destroy$.complete();
 | 
				
			||||||
 | 
					    clearTimeout(this.deepLinkTTLTimeoutID);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getMobileAppDeepLink(): Observable<string> {
 | 
					  private initMobileAppQRCode() {
 | 
				
			||||||
    return this.mobileAppService.getMobileAppDeepLink();
 | 
					    if (this.deepLinkTTLTimeoutID) {
 | 
				
			||||||
 | 
					      clearTimeout(this.deepLinkTTLTimeoutID);
 | 
				
			||||||
 | 
					      this.deepLinkTTLTimeoutID = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.mobileAppService.getMobileAppDeepLink().subscribe(link => {
 | 
				
			||||||
 | 
					      this.deepLinkTTL = Number(this.utilsService.getQueryParam('ttl', link)) * MINUTE;
 | 
				
			||||||
 | 
					      this.updateQRCode(link);
 | 
				
			||||||
 | 
					      this.deepLinkTTLTimeoutID = setTimeout(() => this.initMobileAppQRCode(), this.deepLinkTTL);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  updateQRCode(link: string) {
 | 
					  private updateQRCode(link: string) {
 | 
				
			||||||
    import('qrcode').then((QRCode) => {
 | 
					    import('qrcode').then((QRCode) => {
 | 
				
			||||||
      QRCode.toCanvas(this.canvasRef.nativeElement, link, { width: 100 });
 | 
					      QRCode.toCanvas(this.canvasRef.nativeElement, link, { width: 100 });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -15,88 +15,36 @@
 | 
				
			|||||||
    limitations under the License.
 | 
					    limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-->
 | 
					-->
 | 
				
			||||||
<section class="tb-widget-settings tb-form-panel no-border no-padding" [formGroup]="mobileAppQRCodeWidgetSettingsForm" fxLayout="column">
 | 
					<section class="tb-widget-settings tb-form-panel no-border no-padding" [formGroup]="mobileAppQRCodeWidgetSettingsForm">
 | 
				
			||||||
  <div class="tb-form-panel">
 | 
					  <div class="tb-form-panel no-padding">
 | 
				
			||||||
    <div fxLayout="row" fxLayoutAlign="space-between center">
 | 
					    <div class="tb-form-row no-border no-padding-bottom">
 | 
				
			||||||
      <div class="tb-form-panel-title" translate>admin.mobile-app.applications</div>
 | 
					      <mat-slide-toggle class="mat-slide" formControlName="useSystemSettings" (click)="$event.stopPropagation()">
 | 
				
			||||||
      <tb-toggle-select formControlName="useDefaultApp">
 | 
					        {{ 'admin.mobile-app.use-system-settings' | translate }}
 | 
				
			||||||
        <tb-toggle-option [value]="true">{{ 'admin.mobile-app.default' | translate }}</tb-toggle-option>
 | 
					      </mat-slide-toggle>
 | 
				
			||||||
        <tb-toggle-option [value]="false">{{ 'admin.mobile-app.custom' | translate }}</tb-toggle-option>
 | 
					 | 
				
			||||||
      </tb-toggle-select>
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="tb-form-panel stroked no-padding no-gap" formGroupName="androidConfig">
 | 
					  </div>
 | 
				
			||||||
 | 
					  <div class="tb-form-panel" *ngIf="!mobileAppQRCodeWidgetSettingsForm.get('useSystemSettings').value">
 | 
				
			||||||
 | 
					    <div class="tb-form-panel-title" translate>admin.mobile-app.applications</div>
 | 
				
			||||||
 | 
					    <div class="tb-form-panel stroked no-padding no-gap">
 | 
				
			||||||
      <div class="tb-form-row no-border no-padding-bottom">
 | 
					      <div class="tb-form-row no-border no-padding-bottom">
 | 
				
			||||||
        <mat-slide-toggle class="mat-slide" formControlName="enabled" (click)="$event.stopPropagation()">
 | 
					        <mat-slide-toggle class="mat-slide" [formControl]="mobileAppQRCodeWidgetSettingsForm.get('androidConfig.enabled')" (click)="$event.stopPropagation()">
 | 
				
			||||||
          {{ 'admin.mobile-app.android' | translate }}
 | 
					          {{ 'admin.mobile-app.android' | translate }}
 | 
				
			||||||
        </mat-slide-toggle>
 | 
					        </mat-slide-toggle>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="tb-form-panel no-border no-padding-top"
 | 
					 | 
				
			||||||
           *ngIf="!mobileAppQRCodeWidgetSettingsForm.get('useDefaultApp').value && mobileAppQRCodeWidgetSettingsForm.get('androidConfig.enabled').value">
 | 
					 | 
				
			||||||
        <div class="tb-form-row column-xs">
 | 
					 | 
				
			||||||
          <div class="tb-fixed-width">{{ 'admin.mobile-app.app-package-name' | translate }}</div>
 | 
					 | 
				
			||||||
          <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
					 | 
				
			||||||
            <input matInput formControlName="appPackage" placeholder="{{'admin.mobile-app.set' | translate}}">
 | 
					 | 
				
			||||||
            <mat-icon matSuffix
 | 
					 | 
				
			||||||
                      matTooltipPosition="above"
 | 
					 | 
				
			||||||
                      matTooltipClass="tb-error-tooltip"
 | 
					 | 
				
			||||||
                      [matTooltip]="'admin.mobile-app.app-package-name-required' | translate"
 | 
					 | 
				
			||||||
                      *ngIf="mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').hasError('required')
 | 
					 | 
				
			||||||
                          && mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').touched"
 | 
					 | 
				
			||||||
                      class="tb-error">
 | 
					 | 
				
			||||||
              warning
 | 
					 | 
				
			||||||
            </mat-icon>
 | 
					 | 
				
			||||||
          </mat-form-field>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
      <div class="tb-form-panel no-border no-padding-top"
 | 
					 | 
				
			||||||
           *ngIf="!mobileAppQRCodeWidgetSettingsForm.get('useDefaultApp').value && mobileAppQRCodeWidgetSettingsForm.get('androidConfig.enabled').value">
 | 
					 | 
				
			||||||
        <div class="tb-form-row column-xs">
 | 
					 | 
				
			||||||
          <div class="tb-fixed-width">{{ 'admin.mobile-app.sha256-certificate-fingerprints' | translate }}</div>
 | 
					 | 
				
			||||||
          <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
					 | 
				
			||||||
            <input matInput formControlName="sha256CertFingerprints" placeholder="{{'admin.mobile-app.set' | translate}}">
 | 
					 | 
				
			||||||
            <mat-icon matSuffix
 | 
					 | 
				
			||||||
                      matTooltipPosition="above"
 | 
					 | 
				
			||||||
                      matTooltipClass="tb-error-tooltip"
 | 
					 | 
				
			||||||
                      [matTooltip]="'admin.mobile-app.sha256-certificate-fingerprints-required' | translate"
 | 
					 | 
				
			||||||
                      *ngIf="mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').hasError('required')
 | 
					 | 
				
			||||||
                          && mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').touched"
 | 
					 | 
				
			||||||
                      class="tb-error">
 | 
					 | 
				
			||||||
              warning
 | 
					 | 
				
			||||||
            </mat-icon>
 | 
					 | 
				
			||||||
          </mat-form-field>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="tb-form-panel stroked no-padding no-gap" formGroupName="iosConfig">
 | 
					    <div class="tb-form-panel stroked no-padding no-gap" formGroupName="iosConfig">
 | 
				
			||||||
      <div class="tb-form-row no-border no-padding-bottom">
 | 
					      <div class="tb-form-row no-border no-padding-bottom">
 | 
				
			||||||
        <mat-slide-toggle class="mat-slide" formControlName="enabled" (click)="$event.stopPropagation()">
 | 
					        <mat-slide-toggle class="mat-slide" [formControl]="mobileAppQRCodeWidgetSettingsForm.get('iosConfig.enabled')" (click)="$event.stopPropagation()">
 | 
				
			||||||
          {{ 'admin.mobile-app.ios' | translate }}
 | 
					          {{ 'admin.mobile-app.ios' | translate }}
 | 
				
			||||||
        </mat-slide-toggle>
 | 
					        </mat-slide-toggle>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="tb-form-panel no-border no-padding-top"
 | 
					 | 
				
			||||||
           *ngIf="!mobileAppQRCodeWidgetSettingsForm.get('useDefaultApp').value && mobileAppQRCodeWidgetSettingsForm.get('iosConfig.enabled').value">
 | 
					 | 
				
			||||||
        <div class="tb-form-row column-xs">
 | 
					 | 
				
			||||||
          <div class="tb-fixed-width">{{ 'admin.mobile-app.app-id' | translate }}</div>
 | 
					 | 
				
			||||||
          <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
					 | 
				
			||||||
            <input matInput formControlName="appId" placeholder="{{'admin.mobile-app.set' | translate}}">
 | 
					 | 
				
			||||||
            <mat-icon matSuffix
 | 
					 | 
				
			||||||
                      matTooltipPosition="above"
 | 
					 | 
				
			||||||
                      matTooltipClass="tb-error-tooltip"
 | 
					 | 
				
			||||||
                      [matTooltip]="'admin.mobile-app.app-id-required' | translate"
 | 
					 | 
				
			||||||
                      *ngIf="mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').hasError('required')
 | 
					 | 
				
			||||||
                          && mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').touched"
 | 
					 | 
				
			||||||
                      class="tb-error">
 | 
					 | 
				
			||||||
              warning
 | 
					 | 
				
			||||||
            </mat-icon>
 | 
					 | 
				
			||||||
          </mat-form-field>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  <div class="tb-form-panel" formGroupName="qrCodeConfig">
 | 
					  <div class="tb-form-panel" formGroupName="qrCodeConfig" *ngIf="!mobileAppQRCodeWidgetSettingsForm.get('useSystemSettings').value">
 | 
				
			||||||
 | 
					    <div class="tb-form-panel-title" translate>admin.mobile-app.appearance</div>
 | 
				
			||||||
    <div class="tb-form-panel stroked no-padding no-gap">
 | 
					    <div class="tb-form-panel stroked no-padding no-gap">
 | 
				
			||||||
      <div class="tb-form-row space-between no-border no-padding-bottom column-xs">
 | 
					      <div class="tb-form-row space-between no-border no-padding-bottom column-xs">
 | 
				
			||||||
        <mat-slide-toggle class="mat-slide tb-fixed-width" formControlName="badgeEnabled"
 | 
					        <mat-slide-toggle class="mat-slide fixed-title-width-230" formControlName="badgeEnabled"
 | 
				
			||||||
                          (click)="$event.stopPropagation()">
 | 
					                          (click)="$event.stopPropagation()">
 | 
				
			||||||
          {{ 'admin.mobile-app.badges' | translate }}
 | 
					          {{ 'admin.mobile-app.badges' | translate }}
 | 
				
			||||||
        </mat-slide-toggle>
 | 
					        </mat-slide-toggle>
 | 
				
			||||||
@ -118,7 +66,7 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="tb-form-panel stroked no-padding no-gap">
 | 
					    <div class="tb-form-panel stroked no-padding no-gap">
 | 
				
			||||||
      <div class="tb-form-row space-between no-border no-padding-bottom column-xs">
 | 
					      <div class="tb-form-row space-between no-border no-padding-bottom column-xs">
 | 
				
			||||||
        <mat-slide-toggle class="mat-slide tb-fixed-width" formControlName="qrCodeLabelEnabled" (click)="$event.stopPropagation()">
 | 
					        <mat-slide-toggle class="mat-slide fixed-title-width-230" formControlName="qrCodeLabelEnabled" (click)="$event.stopPropagation()">
 | 
				
			||||||
          {{ 'admin.mobile-app.label' | translate }}
 | 
					          {{ 'admin.mobile-app.label' | translate }}
 | 
				
			||||||
        </mat-slide-toggle>
 | 
					        </mat-slide-toggle>
 | 
				
			||||||
        <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
					        <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
				
			||||||
 | 
				
			|||||||
@ -1,19 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Copyright © 2016-2024 The Thingsboard Authors
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 | 
				
			||||||
 * You may obtain a copy of the License at
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Unless required by applicable law or agreed to in writing, software
 | 
					 | 
				
			||||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
					 | 
				
			||||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					 | 
				
			||||||
 * See the License for the specific language governing permissions and
 | 
					 | 
				
			||||||
 * limitations under the License.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.tb-fixed-width {
 | 
					 | 
				
			||||||
  min-width: 230px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -25,7 +25,7 @@ import { mobileAppQrCodeWidgetDefaultSettings } from '@home/components/widget/li
 | 
				
			|||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'tb-mobile-app-qr-code-widget-settings',
 | 
					  selector: 'tb-mobile-app-qr-code-widget-settings',
 | 
				
			||||||
  templateUrl: './mobile-app-qr-code-widget-settings.component.html',
 | 
					  templateUrl: './mobile-app-qr-code-widget-settings.component.html',
 | 
				
			||||||
  styleUrls: ['/mobile-app-qr-code-widget-settings.component.scss', './../widget-settings.scss']
 | 
					  styleUrls: ['./../widget-settings.scss']
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class MobileAppQrCodeWidgetSettingsComponent extends WidgetSettingsComponent {
 | 
					export class MobileAppQrCodeWidgetSettingsComponent extends WidgetSettingsComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -49,15 +49,12 @@ export class MobileAppQrCodeWidgetSettingsComponent extends WidgetSettingsCompon
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  protected onSettingsSet(settings: WidgetSettings) {
 | 
					  protected onSettingsSet(settings: WidgetSettings) {
 | 
				
			||||||
    this.mobileAppQRCodeWidgetSettingsForm = this.fb.group({
 | 
					    this.mobileAppQRCodeWidgetSettingsForm = this.fb.group({
 | 
				
			||||||
      useDefaultApp: [settings.useDefaultApp],
 | 
					      useSystemSettings: [settings.useSystemSettings],
 | 
				
			||||||
      androidConfig: this.fb.group({
 | 
					      androidConfig: this.fb.group({
 | 
				
			||||||
        enabled: [settings.androidConfig.enabled],
 | 
					        enabled: [settings.androidConfig.enabled],
 | 
				
			||||||
        appPackage: [settings.androidConfig.appPackage, [Validators.required]],
 | 
					 | 
				
			||||||
        sha256CertFingerprints: [settings.androidConfig.sha256CertFingerprints, [Validators.required]]
 | 
					 | 
				
			||||||
      }),
 | 
					      }),
 | 
				
			||||||
      iosConfig: this.fb.group({
 | 
					      iosConfig: this.fb.group({
 | 
				
			||||||
        enabled: [settings.iosConfig.enabled],
 | 
					        enabled: [settings.iosConfig.enabled],
 | 
				
			||||||
        appId: [settings.iosConfig.appId, [Validators.required]]
 | 
					 | 
				
			||||||
      }),
 | 
					      }),
 | 
				
			||||||
      qrCodeConfig: this.fb.group({
 | 
					      qrCodeConfig: this.fb.group({
 | 
				
			||||||
        badgeEnabled: [settings.qrCodeConfig.badgeEnabled],
 | 
					        badgeEnabled: [settings.qrCodeConfig.badgeEnabled],
 | 
				
			||||||
@ -70,35 +67,16 @@ export class MobileAppQrCodeWidgetSettingsComponent extends WidgetSettingsCompon
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  protected validatorTriggers(): string[] {
 | 
					  protected validatorTriggers(): string[] {
 | 
				
			||||||
    return ['useDefaultApp', 'androidConfig.enabled', 'iosConfig.enabled', 'qrCodeConfig.badgeEnabled', 'qrCodeConfig.qrCodeLabelEnabled'];
 | 
					    return ['useSystemSettings', 'androidConfig.enabled', 'iosConfig.enabled', 'qrCodeConfig.badgeEnabled', 'qrCodeConfig.qrCodeLabelEnabled'];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  protected updateValidators(emitEvent: boolean) {
 | 
					  protected updateValidators(emitEvent: boolean) {
 | 
				
			||||||
    const useDefaultApp = this.mobileAppQRCodeWidgetSettingsForm.get('useDefaultApp').value;
 | 
					    const useSystemSettings = this.mobileAppQRCodeWidgetSettingsForm.get('useSystemSettings').value;
 | 
				
			||||||
    const androidEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.enabled').value;
 | 
					    const androidEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.enabled').value;
 | 
				
			||||||
    const iosEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.enabled').value;
 | 
					    const iosEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.enabled').value;
 | 
				
			||||||
    const badgeEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeEnabled').value;
 | 
					    const badgeEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeEnabled').value;
 | 
				
			||||||
    const qrCodeLabelEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabelEnabled').value;
 | 
					    const qrCodeLabelEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabelEnabled').value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (useDefaultApp) {
 | 
					 | 
				
			||||||
      this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').disable({emitEvent: false});
 | 
					 | 
				
			||||||
      this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').disable({emitEvent: false});
 | 
					 | 
				
			||||||
      this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').disable({emitEvent: false});
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      if (androidEnabled) {
 | 
					 | 
				
			||||||
        this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').enable({emitEvent: false});
 | 
					 | 
				
			||||||
        this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').enable({emitEvent: false});
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').disable({emitEvent: false});
 | 
					 | 
				
			||||||
        this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').disable({emitEvent: false});
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (iosEnabled) {
 | 
					 | 
				
			||||||
        this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').enable({emitEvent: false});
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').disable({emitEvent: false});
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!androidEnabled && !iosEnabled) {
 | 
					    if (!androidEnabled && !iosEnabled) {
 | 
				
			||||||
      this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeEnabled').disable({emitEvent: false});
 | 
					      this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeEnabled').disable({emitEvent: false});
 | 
				
			||||||
      this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeStyle').disable({emitEvent: false});
 | 
					      this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeStyle').disable({emitEvent: false});
 | 
				
			||||||
@ -116,7 +94,7 @@ export class MobileAppQrCodeWidgetSettingsComponent extends WidgetSettingsCompon
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (qrCodeLabelEnabled) {
 | 
					    if (qrCodeLabelEnabled && !useSystemSettings) {
 | 
				
			||||||
      this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabel').enable({emitEvent: false});
 | 
					      this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabel').enable({emitEvent: false});
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabel').disable({emitEvent: false});
 | 
					      this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabel').disable({emitEvent: false});
 | 
				
			||||||
 | 
				
			|||||||
@ -43,7 +43,7 @@
 | 
				
			|||||||
          <div class="tb-form-panel no-border no-padding-top"
 | 
					          <div class="tb-form-panel no-border no-padding-top"
 | 
				
			||||||
               *ngIf="!mobileAppSettingsForm.get('useDefaultApp').value && mobileAppSettingsForm.get('androidConfig.enabled').value">
 | 
					               *ngIf="!mobileAppSettingsForm.get('useDefaultApp').value && mobileAppSettingsForm.get('androidConfig.enabled').value">
 | 
				
			||||||
            <div class="tb-form-row column-xs">
 | 
					            <div class="tb-form-row column-xs">
 | 
				
			||||||
              <div class="tb-fixed-width">{{ 'admin.mobile-app.app-package-name' | translate }}</div>
 | 
					              <div class="fixed-title-width-230">{{ 'admin.mobile-app.app-package-name' | translate }}</div>
 | 
				
			||||||
              <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
					              <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
				
			||||||
                <input matInput formControlName="appPackage" placeholder="{{'admin.mobile-app.set' | translate}}">
 | 
					                <input matInput formControlName="appPackage" placeholder="{{'admin.mobile-app.set' | translate}}">
 | 
				
			||||||
                <mat-icon matSuffix
 | 
					                <mat-icon matSuffix
 | 
				
			||||||
@ -61,7 +61,7 @@
 | 
				
			|||||||
          <div class="tb-form-panel no-border no-padding-top"
 | 
					          <div class="tb-form-panel no-border no-padding-top"
 | 
				
			||||||
               *ngIf="!mobileAppSettingsForm.get('useDefaultApp').value && mobileAppSettingsForm.get('androidConfig.enabled').value">
 | 
					               *ngIf="!mobileAppSettingsForm.get('useDefaultApp').value && mobileAppSettingsForm.get('androidConfig.enabled').value">
 | 
				
			||||||
            <div class="tb-form-row column-xs">
 | 
					            <div class="tb-form-row column-xs">
 | 
				
			||||||
              <div class="tb-fixed-width">{{ 'admin.mobile-app.sha256-certificate-fingerprints' | translate }}</div>
 | 
					              <div class="fixed-title-width-230">{{ 'admin.mobile-app.sha256-certificate-fingerprints' | translate }}</div>
 | 
				
			||||||
              <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
					              <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
				
			||||||
                <input matInput formControlName="sha256CertFingerprints" placeholder="{{'admin.mobile-app.set' | translate}}">
 | 
					                <input matInput formControlName="sha256CertFingerprints" placeholder="{{'admin.mobile-app.set' | translate}}">
 | 
				
			||||||
                <mat-icon matSuffix
 | 
					                <mat-icon matSuffix
 | 
				
			||||||
@ -86,7 +86,7 @@
 | 
				
			|||||||
          <div class="tb-form-panel no-border no-padding-top"
 | 
					          <div class="tb-form-panel no-border no-padding-top"
 | 
				
			||||||
               *ngIf="!mobileAppSettingsForm.get('useDefaultApp').value && mobileAppSettingsForm.get('iosConfig.enabled').value">
 | 
					               *ngIf="!mobileAppSettingsForm.get('useDefaultApp').value && mobileAppSettingsForm.get('iosConfig.enabled').value">
 | 
				
			||||||
            <div class="tb-form-row column-xs">
 | 
					            <div class="tb-form-row column-xs">
 | 
				
			||||||
              <div class="tb-fixed-width">{{ 'admin.mobile-app.app-id' | translate }}</div>
 | 
					              <div class="fixed-title-width-230">{{ 'admin.mobile-app.app-id' | translate }}</div>
 | 
				
			||||||
              <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
					              <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
				
			||||||
                <input matInput formControlName="appId" placeholder="{{'admin.mobile-app.set' | translate}}">
 | 
					                <input matInput formControlName="appId" placeholder="{{'admin.mobile-app.set' | translate}}">
 | 
				
			||||||
                <mat-icon matSuffix
 | 
					                <mat-icon matSuffix
 | 
				
			||||||
@ -113,7 +113,7 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="tb-form-panel stroked no-padding no-gap" *ngIf="mobileAppSettingsForm.get('qrCodeConfig.showOnHomePage').value">
 | 
					        <div class="tb-form-panel stroked no-padding no-gap" *ngIf="mobileAppSettingsForm.get('qrCodeConfig.showOnHomePage').value">
 | 
				
			||||||
          <div class="tb-form-row space-between no-border no-padding-bottom column-xs">
 | 
					          <div class="tb-form-row space-between no-border no-padding-bottom column-xs">
 | 
				
			||||||
            <mat-slide-toggle class="mat-slide tb-fixed-width" formControlName="badgeEnabled"
 | 
					            <mat-slide-toggle class="mat-slide fixed-title-width-230" formControlName="badgeEnabled"
 | 
				
			||||||
                              (click)="$event.stopPropagation()">
 | 
					                              (click)="$event.stopPropagation()">
 | 
				
			||||||
              {{ 'admin.mobile-app.badges' | translate }}
 | 
					              {{ 'admin.mobile-app.badges' | translate }}
 | 
				
			||||||
            </mat-slide-toggle>
 | 
					            </mat-slide-toggle>
 | 
				
			||||||
@ -135,7 +135,7 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="tb-form-panel stroked no-padding no-gap" *ngIf="mobileAppSettingsForm.get('qrCodeConfig.showOnHomePage').value">
 | 
					        <div class="tb-form-panel stroked no-padding no-gap" *ngIf="mobileAppSettingsForm.get('qrCodeConfig.showOnHomePage').value">
 | 
				
			||||||
          <div class="tb-form-row space-between no-border no-padding-bottom column-xs">
 | 
					          <div class="tb-form-row space-between no-border no-padding-bottom column-xs">
 | 
				
			||||||
            <mat-slide-toggle class="mat-slide tb-fixed-width" formControlName="qrCodeLabelEnabled" (click)="$event.stopPropagation()">
 | 
					            <mat-slide-toggle class="mat-slide fixed-title-width-230" formControlName="qrCodeLabelEnabled" (click)="$event.stopPropagation()">
 | 
				
			||||||
              {{ 'admin.mobile-app.label' | translate }}
 | 
					              {{ 'admin.mobile-app.label' | translate }}
 | 
				
			||||||
            </mat-slide-toggle>
 | 
					            </mat-slide-toggle>
 | 
				
			||||||
            <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
					            <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
 | 
				
			||||||
@ -154,7 +154,7 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="tb-form-panel tb-qrcode-preview" *ngIf="mobileAppSettingsForm.get('qrCodeConfig.showOnHomePage').value">
 | 
					        <div class="tb-form-panel tb-qrcode-preview" *ngIf="mobileAppSettingsForm.get('qrCodeConfig.showOnHomePage').value">
 | 
				
			||||||
          <div class="tb-form-panel-title" translate>admin.mobile-app.preview</div>
 | 
					          <div class="tb-form-panel-title" translate>admin.mobile-app.preview</div>
 | 
				
			||||||
          <tb-mobile-app-qrcode-widget previewMode
 | 
					          <tb-mobile-app-qrcode-widget
 | 
				
			||||||
            [mobileAppSettings]="mobileAppSettingsForm.getRawValue()">
 | 
					            [mobileAppSettings]="mobileAppSettingsForm.getRawValue()">
 | 
				
			||||||
          </tb-mobile-app-qrcode-widget>
 | 
					          </tb-mobile-app-qrcode-widget>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -14,10 +14,6 @@
 | 
				
			|||||||
 * limitations under the License.
 | 
					 * limitations under the License.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tb-fixed-width {
 | 
					 | 
				
			||||||
  min-width: 230px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.tb-qrcode-preview {
 | 
					.tb-qrcode-preview {
 | 
				
			||||||
  background-color: rgba(0, 0, 0, 0.04);
 | 
					  background-color: rgba(0, 0, 0, 0.04);
 | 
				
			||||||
  box-shadow: none;
 | 
					  box-shadow: none;
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ import {
 | 
				
			|||||||
  badgePositionTranslationsMap,
 | 
					  badgePositionTranslationsMap,
 | 
				
			||||||
  BadgeStyle,
 | 
					  BadgeStyle,
 | 
				
			||||||
  badgeStyleTranslationsMap,
 | 
					  badgeStyleTranslationsMap,
 | 
				
			||||||
  MobileAppQRCodeSettings
 | 
					  MobileAppSettings
 | 
				
			||||||
} from '@shared/models/mobile-app.models';
 | 
					} from '@shared/models/mobile-app.models';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
@ -39,7 +39,7 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  mobileAppSettingsForm: FormGroup;
 | 
					  mobileAppSettingsForm: FormGroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mobileAppSettings: MobileAppQRCodeSettings;
 | 
					  mobileAppSettings: MobileAppSettings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private readonly destroy$ = new Subject<void>();
 | 
					  private readonly destroy$ = new Subject<void>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -133,7 +133,7 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private processMobileAppSettings(mobileAppSettings: MobileAppQRCodeSettings): void {
 | 
					  private processMobileAppSettings(mobileAppSettings: MobileAppSettings): void {
 | 
				
			||||||
    this.mobileAppSettings = {...mobileAppSettings};
 | 
					    this.mobileAppSettings = {...mobileAppSettings};
 | 
				
			||||||
    this.mobileAppSettingsForm.reset(this.mobileAppSettings);
 | 
					    this.mobileAppSettingsForm.reset(this.mobileAppSettings);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -27,8 +27,9 @@ import { AppState } from '@core/core.state';
 | 
				
			|||||||
import { map } from 'rxjs/operators';
 | 
					import { map } from 'rxjs/operators';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  getCurrentAuthUser,
 | 
					  getCurrentAuthUser,
 | 
				
			||||||
 | 
					  selectHomeDashboardParams,
 | 
				
			||||||
  selectMobileQrEnabled,
 | 
					  selectMobileQrEnabled,
 | 
				
			||||||
  selectPersistDeviceStateToTelemetryAndMobileQrEnabled
 | 
					  selectPersistDeviceStateToTelemetry
 | 
				
			||||||
} from '@core/auth/auth.selectors';
 | 
					} from '@core/auth/auth.selectors';
 | 
				
			||||||
import { EntityKeyType } from '@shared/models/query/query.models';
 | 
					import { EntityKeyType } from '@shared/models/query/query.models';
 | 
				
			||||||
import { ResourcesService } from '@core/services/resources.service';
 | 
					import { ResourcesService } from '@core/services/resources.service';
 | 
				
			||||||
@ -37,9 +38,42 @@ const sysAdminHomePageJson = '/assets/dashboard/sys_admin_home_page.json';
 | 
				
			|||||||
const tenantAdminHomePageJson = '/assets/dashboard/tenant_admin_home_page.json';
 | 
					const tenantAdminHomePageJson = '/assets/dashboard/tenant_admin_home_page.json';
 | 
				
			||||||
const customerUserHomePageJson = '/assets/dashboard/customer_user_home_page.json';
 | 
					const customerUserHomePageJson = '/assets/dashboard/customer_user_home_page.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const updateDeviceActivityKeyFilterIfNeeded = (store: Store<AppState>,
 | 
					const getHomeDashboard = (store: Store<AppState>, resourcesService: ResourcesService) => {
 | 
				
			||||||
                                               dashboard$: Observable<HomeDashboard>): Observable<HomeDashboard> =>
 | 
					  const authority = getCurrentAuthUser(store).authority;
 | 
				
			||||||
  store.pipe(select(selectPersistDeviceStateToTelemetryAndMobileQrEnabled)).pipe(
 | 
					  switch (authority) {
 | 
				
			||||||
 | 
					    case Authority.SYS_ADMIN:
 | 
				
			||||||
 | 
					      return applySystemParametersToHomeDashboard(store, resourcesService.loadJsonResource(sysAdminHomePageJson), authority);
 | 
				
			||||||
 | 
					    case Authority.TENANT_ADMIN:
 | 
				
			||||||
 | 
					      return applySystemParametersToHomeDashboard(store, resourcesService.loadJsonResource(tenantAdminHomePageJson), authority);
 | 
				
			||||||
 | 
					    case Authority.CUSTOMER_USER:
 | 
				
			||||||
 | 
					      return applySystemParametersToHomeDashboard(store, resourcesService.loadJsonResource(customerUserHomePageJson), authority);
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      return of(null);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const applySystemParametersToHomeDashboard = (store: Store<AppState>,
 | 
				
			||||||
 | 
					                                              dashboard$: Observable<HomeDashboard>,
 | 
				
			||||||
 | 
					                                              authority: Authority): Observable<HomeDashboard> => {
 | 
				
			||||||
 | 
					  let selectParams$: Observable<{persistDeviceStateToTelemetry?: boolean, mobileQrEnabled?: boolean}>;
 | 
				
			||||||
 | 
					  switch (authority) {
 | 
				
			||||||
 | 
					    case Authority.SYS_ADMIN:
 | 
				
			||||||
 | 
					      selectParams$ = store.pipe(
 | 
				
			||||||
 | 
					        select(selectMobileQrEnabled),
 | 
				
			||||||
 | 
					        map(mobileQrEnabled => ({mobileQrEnabled}))
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case Authority.TENANT_ADMIN:
 | 
				
			||||||
 | 
					      selectParams$ = store.pipe(select(selectHomeDashboardParams));
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case Authority.CUSTOMER_USER:
 | 
				
			||||||
 | 
					      selectParams$ = store.pipe(
 | 
				
			||||||
 | 
					        select(selectPersistDeviceStateToTelemetry),
 | 
				
			||||||
 | 
					        map(persistDeviceStateToTelemetry => ({persistDeviceStateToTelemetry}))
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return selectParams$.pipe(
 | 
				
			||||||
    mergeMap((params) => dashboard$.pipe(
 | 
					    mergeMap((params) => dashboard$.pipe(
 | 
				
			||||||
      map((dashboard) => {
 | 
					      map((dashboard) => {
 | 
				
			||||||
        if (params.persistDeviceStateToTelemetry) {
 | 
					        if (params.persistDeviceStateToTelemetry) {
 | 
				
			||||||
@ -49,31 +83,21 @@ const updateDeviceActivityKeyFilterIfNeeded = (store: Store<AppState>,
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return params.mobileQrEnabled ? toggleMobileQRCodeDisplay(dashboard) : dashboard;
 | 
					        if (params.mobileQrEnabled) {
 | 
				
			||||||
 | 
					          for (const widgetId of Object.keys(dashboard.configuration.widgets)) {
 | 
				
			||||||
 | 
					            if (dashboard.configuration.widgets[widgetId].config.title === 'Select show mobile QR code') {
 | 
				
			||||||
 | 
					              dashboard.configuration.widgets[widgetId].config.settings.markdownTextFunction =
 | 
				
			||||||
 | 
					                (dashboard.configuration.widgets[widgetId].config.settings.markdownTextFunction as string)
 | 
				
			||||||
 | 
					                  .replace('\'${mobileQrEnabled}\'', String(true));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        dashboard.hideDashboardToolbar = true;
 | 
				
			||||||
 | 
					        return dashboard;
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    ))
 | 
					    ))
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
const toggleMobileQRCodeDisplayIfNeeded = (store: Store<AppState>,
 | 
					 | 
				
			||||||
              dashboard$: Observable<HomeDashboard>): Observable<HomeDashboard> =>
 | 
					 | 
				
			||||||
  store.pipe(select(selectMobileQrEnabled)).pipe(
 | 
					 | 
				
			||||||
    mergeMap((mobileQrEnabled) => dashboard$.pipe(
 | 
					 | 
				
			||||||
      map((dashboard) => {
 | 
					 | 
				
			||||||
        return mobileQrEnabled ? toggleMobileQRCodeDisplay(dashboard) : dashboard;
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    ))
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const toggleMobileQRCodeDisplay = (dashboard: HomeDashboard) => {
 | 
					 | 
				
			||||||
  for (const widgetId of Object.keys(dashboard.configuration.widgets)) {
 | 
					 | 
				
			||||||
    if (dashboard.configuration.widgets[widgetId].config.title === 'Select show mobile QR code') {
 | 
					 | 
				
			||||||
      dashboard.configuration.widgets[widgetId].config.settings.markdownTextFunction =
 | 
					 | 
				
			||||||
        (dashboard.configuration.widgets[widgetId].config.settings.markdownTextFunction as string)
 | 
					 | 
				
			||||||
          .replace('\'${mobileQrEnabled}\'', String(true));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return dashboard;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const homeDashboardResolver: ResolveFn<HomeDashboard> = (
 | 
					export const homeDashboardResolver: ResolveFn<HomeDashboard> = (
 | 
				
			||||||
  route: ActivatedRouteSnapshot,
 | 
					  route: ActivatedRouteSnapshot,
 | 
				
			||||||
@ -85,27 +109,7 @@ export const homeDashboardResolver: ResolveFn<HomeDashboard> = (
 | 
				
			|||||||
  dashboardService.getHomeDashboard().pipe(
 | 
					  dashboardService.getHomeDashboard().pipe(
 | 
				
			||||||
    mergeMap((dashboard) => {
 | 
					    mergeMap((dashboard) => {
 | 
				
			||||||
      if (!dashboard) {
 | 
					      if (!dashboard) {
 | 
				
			||||||
        let dashboard$: Observable<HomeDashboard>;
 | 
					        return getHomeDashboard(store, resourcesService);
 | 
				
			||||||
        const authority = getCurrentAuthUser(store).authority;
 | 
					 | 
				
			||||||
        switch (authority) {
 | 
					 | 
				
			||||||
          case Authority.SYS_ADMIN:
 | 
					 | 
				
			||||||
            dashboard$ = toggleMobileQRCodeDisplayIfNeeded(store, resourcesService.loadJsonResource(sysAdminHomePageJson));
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
          case Authority.TENANT_ADMIN:
 | 
					 | 
				
			||||||
            dashboard$ = updateDeviceActivityKeyFilterIfNeeded(store, resourcesService.loadJsonResource(tenantAdminHomePageJson));
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
          case Authority.CUSTOMER_USER:
 | 
					 | 
				
			||||||
            dashboard$ = updateDeviceActivityKeyFilterIfNeeded(store, resourcesService.loadJsonResource(customerUserHomePageJson));
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (dashboard$) {
 | 
					 | 
				
			||||||
          return dashboard$.pipe(
 | 
					 | 
				
			||||||
            map((homeDashboard) => {
 | 
					 | 
				
			||||||
              homeDashboard.hideDashboardToolbar = true;
 | 
					 | 
				
			||||||
              return homeDashboard;
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return of(dashboard);
 | 
					      return of(dashboard);
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
				
			|||||||
@ -14,10 +14,9 @@
 | 
				
			|||||||
/// limitations under the License.
 | 
					/// limitations under the License.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { TenantId } from '@shared/models/id/tenant-id';
 | 
					import { HasTenantId } from '@shared/models/entity.models';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface MobileAppQRCodeSettings {
 | 
					export interface MobileAppSettings extends HasTenantId {
 | 
				
			||||||
  tenantId: TenantId;
 | 
					 | 
				
			||||||
  useDefaultApp: boolean;
 | 
					  useDefaultApp: boolean;
 | 
				
			||||||
  androidConfig: AndroidConfig;
 | 
					  androidConfig: AndroidConfig;
 | 
				
			||||||
  iosConfig: IosConfig;
 | 
					  iosConfig: IosConfig;
 | 
				
			||||||
 | 
				
			|||||||
@ -2634,22 +2634,24 @@
 | 
				
			|||||||
        "typeFullFqn": "system.home_page_widgets.getting_started"
 | 
					        "typeFullFqn": "system.home_page_widgets.getting_started"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "53d5f2dd-d432-5362-745f-63bf4487dc96": {
 | 
					      "53d5f2dd-d432-5362-745f-63bf4487dc96": {
 | 
				
			||||||
        "typeFullFqn": "system.home_page_widgets.home_page_mobile_app_qr_code",
 | 
					        "typeFullFqn": "system.mobile_app_qr_code",
 | 
				
			||||||
        "type": "static",
 | 
					        "type": "static",
 | 
				
			||||||
        "sizeX": 6,
 | 
					        "sizeX": 6,
 | 
				
			||||||
        "sizeY": 3,
 | 
					        "sizeY": 3,
 | 
				
			||||||
        "config": {
 | 
					        "config": {
 | 
				
			||||||
          "showTitle": false,
 | 
					          "showTitle": true,
 | 
				
			||||||
          "backgroundColor": "rgb(255, 255, 255)",
 | 
					          "backgroundColor": "rgb(255, 255, 255)",
 | 
				
			||||||
          "color": "rgba(0, 0, 0, 0.87)",
 | 
					          "color": "rgba(0, 0, 0, 0.87)",
 | 
				
			||||||
          "padding": "8px",
 | 
					          "padding": "8px",
 | 
				
			||||||
          "settings": {},
 | 
					          "settings": {},
 | 
				
			||||||
          "title": "Mobile app QR code",
 | 
					          "title": "{i18n:admin.mobile-app.connect-mobile-app}",
 | 
				
			||||||
          "dropShadow": false,
 | 
					          "dropShadow": false,
 | 
				
			||||||
          "enableFullscreen": false,
 | 
					          "enableFullscreen": false,
 | 
				
			||||||
          "widgetStyle": {},
 | 
					          "widgetStyle": {},
 | 
				
			||||||
          "widgetCss": "",
 | 
					          "widgetCss": ".tb-widget-container > .tb-widget > .tb-widget-header > .tb-widget-title {\n    padding: 0;\n}\n\n.tb-widget-container > .tb-widget > .tb-widget-header > .tb-widget-title > .title-row > .title {\n    padding-bottom: 12px;\n    font-weight: 600;\n    font-size: 20px;\n    line-height: 24px;\n    letter-spacing: 0.1px;\n    color: rgba(0, 0, 0, 0.76);\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n    .tb-widget-container > .tb-widget > .tb-widget-header > .tb-widget-title > .title-row > .title {\n        padding-bottom: 0;\n        font-weight: 500;\n        font-size: 14px;\n        line-height: 20px;\n        letter-spacing: 0.25px;\n  }\n}\n",
 | 
				
			||||||
          "noDataDisplayMessage": ""
 | 
					          "showTitleIcon": false,
 | 
				
			||||||
 | 
					          "titleTooltip": "",
 | 
				
			||||||
 | 
					          "titleStyle": null
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "row": 0,
 | 
					        "row": 0,
 | 
				
			||||||
        "col": 0,
 | 
					        "col": 0,
 | 
				
			||||||
 | 
				
			|||||||
@ -1177,19 +1177,24 @@
 | 
				
			|||||||
        "typeFullFqn": "system.home_page_widgets.getting_started"
 | 
					        "typeFullFqn": "system.home_page_widgets.getting_started"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "8c5207d8-7103-4dc2-db48-d61c0c8c61fd": {
 | 
					      "8c5207d8-7103-4dc2-db48-d61c0c8c61fd": {
 | 
				
			||||||
        "typeFullFqn": "system.home_page_widgets.home_page_mobile_app_qr_code",
 | 
					        "typeFullFqn": "system.mobile_app_qr_code",
 | 
				
			||||||
        "type": "static",
 | 
					        "type": "static",
 | 
				
			||||||
        "sizeX": 6,
 | 
					        "sizeX": 6,
 | 
				
			||||||
        "sizeY": 3,
 | 
					        "sizeY": 3,
 | 
				
			||||||
        "config": {
 | 
					        "config": {
 | 
				
			||||||
          "showTitle": false,
 | 
					          "showTitle": true,
 | 
				
			||||||
          "backgroundColor": "rgb(255, 255, 255)",
 | 
					          "backgroundColor": "rgb(255, 255, 255)",
 | 
				
			||||||
          "color": "rgba(0, 0, 0, 0.87)",
 | 
					          "color": "rgba(0, 0, 0, 0.87)",
 | 
				
			||||||
          "padding": "8px",
 | 
					          "padding": "8px",
 | 
				
			||||||
          "settings": {},
 | 
					          "settings": {},
 | 
				
			||||||
          "title": "Mobile app QR code",
 | 
					          "title": "{i18n:admin.mobile-app.connect-mobile-app}",
 | 
				
			||||||
          "dropShadow": false,
 | 
					          "dropShadow": false,
 | 
				
			||||||
          "enableFullscreen": false
 | 
					          "enableFullscreen": false,
 | 
				
			||||||
 | 
					          "widgetStyle": {},
 | 
				
			||||||
 | 
					          "widgetCss": ".tb-widget-container > .tb-widget > .tb-widget-header > .tb-widget-title {\n    padding: 0;\n}\n\n.tb-widget-container > .tb-widget > .tb-widget-header > .tb-widget-title > .title-row > .title {\n    padding-bottom: 12px;\n    font-weight: 600;\n    font-size: 20px;\n    line-height: 24px;\n    letter-spacing: 0.1px;\n    color: rgba(0, 0, 0, 0.76);\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n    .tb-widget-container > .tb-widget > .tb-widget-header > .tb-widget-title > .title-row > .title {\n        padding-bottom: 0;\n        font-weight: 500;\n        font-size: 14px;\n        line-height: 20px;\n        letter-spacing: 0.25px;\n  }\n}\n",
 | 
				
			||||||
 | 
					          "showTitleIcon": false,
 | 
				
			||||||
 | 
					          "titleTooltip": "",
 | 
				
			||||||
 | 
					          "titleStyle": null
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "row": 0,
 | 
					        "row": 0,
 | 
				
			||||||
        "col": 0,
 | 
					        "col": 0,
 | 
				
			||||||
 | 
				
			|||||||
@ -433,6 +433,7 @@
 | 
				
			|||||||
            "ios": "iOS",
 | 
					            "ios": "iOS",
 | 
				
			||||||
            "app-id": "App ID",
 | 
					            "app-id": "App ID",
 | 
				
			||||||
            "app-id-required": "App ID is required",
 | 
					            "app-id-required": "App ID is required",
 | 
				
			||||||
 | 
					            "appearance": "Appearance",
 | 
				
			||||||
            "appearance-on-home-page": "Appearance on Home page",
 | 
					            "appearance-on-home-page": "Appearance on Home page",
 | 
				
			||||||
            "enabled": "Enabled",
 | 
					            "enabled": "Enabled",
 | 
				
			||||||
            "disabled": "Disabled",
 | 
					            "disabled": "Disabled",
 | 
				
			||||||
@ -445,7 +446,8 @@
 | 
				
			|||||||
            "left": "Left",
 | 
					            "left": "Left",
 | 
				
			||||||
            "set": "Set",
 | 
					            "set": "Set",
 | 
				
			||||||
            "preview": "Preview",
 | 
					            "preview": "Preview",
 | 
				
			||||||
            "connect-mobile-app": "Connect mobile app"
 | 
					            "connect-mobile-app": "Connect mobile app",
 | 
				
			||||||
 | 
					            "use-system-settings": "Use system settings"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "2fa":  {
 | 
					        "2fa":  {
 | 
				
			||||||
            "2fa": "Two-factor authentication",
 | 
					            "2fa": "Two-factor authentication",
 | 
				
			||||||
 | 
				
			|||||||
@ -234,6 +234,12 @@
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    .fixed-title-width {
 | 
					    .fixed-title-width {
 | 
				
			||||||
      min-width: 200px;
 | 
					      min-width: 200px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      &-230 {
 | 
				
			||||||
 | 
					        min-width: 230px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    [class^="fixed-title-width"] {
 | 
				
			||||||
      @media #{$mat-xs} {
 | 
					      @media #{$mat-xs} {
 | 
				
			||||||
        min-width: fit-content;
 | 
					        min-width: fit-content;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user