UI: Add mobile configure commands and add useSystemSettings in qr code widget
This commit is contained in:
		
							parent
							
								
									b0e11e130a
								
							
						
					
					
						commit
						c6396e4074
					
				@ -35,6 +35,8 @@ public class QrCodeSettings extends BaseData<QrCodeSettingsId> implements HasTen
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY)
 | 
			
		||||
    private TenantId tenantId;
 | 
			
		||||
    @Schema(description = "Use settings from system level", example = "true")
 | 
			
		||||
    private boolean useSystemSettings;
 | 
			
		||||
    @Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Type of application: true means use default Thingsboard app", example = "true")
 | 
			
		||||
    private boolean useDefaultApp;
 | 
			
		||||
    @Schema(description = "Mobile app bundle.")
 | 
			
		||||
 | 
			
		||||
@ -23,10 +23,53 @@
 | 
			
		||||
    <mat-icon class="material-icons">close</mat-icon>
 | 
			
		||||
  </button>
 | 
			
		||||
</mat-toolbar>
 | 
			
		||||
<div mat-dialog-content>
 | 
			
		||||
 | 
			
		||||
<div mat-dialog-content class="flex flex-col gap-4 xs:gap-2 gt-xs:max-h-[80vh]">
 | 
			
		||||
  <div class="tb-form-panel stroked">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>mobile.configuration-step.prepare-environment-title</div>
 | 
			
		||||
    <div class="flex gap-4">
 | 
			
		||||
      <div class="flex-1" translate>mobile.configuration-step.prepare-environment-text</div>
 | 
			
		||||
      <a mat-stroked-button
 | 
			
		||||
         color="primary"
 | 
			
		||||
         href="https://docs.flutter.dev/get-started/install"
 | 
			
		||||
         target="_blank">
 | 
			
		||||
        <mat-icon class="tb-mat-24">description</mat-icon>{{ 'common.documentation' | translate }}
 | 
			
		||||
      </a>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="tb-form-panel stroked">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>mobile.configuration-step.get-source-code-title</div>
 | 
			
		||||
    <div translate>mobile.configuration-step.get-source-code-text</div>
 | 
			
		||||
    <tb-markdown usePlainMarkdown containerClass="tb-command-code"
 | 
			
		||||
                 [data]=createMarkDownCommand(gitRepositoryLink)></tb-markdown>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="tb-form-panel stroked">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>mobile.configuration-step.configure-api-title</div>
 | 
			
		||||
    <div translate>mobile.configuration-step.configure-api-text</div>
 | 
			
		||||
    <tb-markdown usePlainMarkdown containerClass="tb-command-code"
 | 
			
		||||
                 [data]=createMarkDownCommand(pathToConstants)></tb-markdown>
 | 
			
		||||
    <div translate>mobile.configuration-step.configure-api-hint</div>
 | 
			
		||||
    <tb-markdown usePlainMarkdown containerClass="tb-command-code"
 | 
			
		||||
                 [data]=createMarkDownCommand(configureApi)></tb-markdown>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="tb-form-panel stroked">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>mobile.configuration-step.run-app-title</div>
 | 
			
		||||
    <div translate>mobile.configuration-step.run-app-text</div>
 | 
			
		||||
    <tb-markdown usePlainMarkdown containerClass="tb-command-code"
 | 
			
		||||
                 [data]=createMarkDownCommand(flutterRunCommand)></tb-markdown>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="tb-form-panel stroked">
 | 
			
		||||
    <div class="flex items-center gap-4">
 | 
			
		||||
      <div class="flex-1" translate>mobile.configuration-step.more-information</div>
 | 
			
		||||
      <a mat-stroked-button
 | 
			
		||||
         color="primary"
 | 
			
		||||
         href="https://docs.flutter.dev/get-started/install"
 | 
			
		||||
         target="_blank">
 | 
			
		||||
        <mat-icon class="tb-mat-24">rocket_launch</mat-icon>{{ 'mobile.configuration-step.getting-started' | translate }}
 | 
			
		||||
      </a>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
<div mat-dialog-actions class="tb-dialog-actions">
 | 
			
		||||
<div mat-dialog-actions class="tb-dialog-actions gap-2">
 | 
			
		||||
  <mat-slide-toggle [class.!hidden]="!showDontShowAgain" [(ngModel)]="notShowAgain">{{ 'action.dont-show-again' | translate}}</mat-slide-toggle>
 | 
			
		||||
  <span class="flex-1"></span>
 | 
			
		||||
  <button mat-button
 | 
			
		||||
 | 
			
		||||
@ -13,10 +13,84 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
@import "./../scss/constants";
 | 
			
		||||
:host {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  max-height: 100vh;
 | 
			
		||||
  display: grid;
 | 
			
		||||
  width: 800px;
 | 
			
		||||
  width: 870px;
 | 
			
		||||
  max-width: 100%;
 | 
			
		||||
  grid-template-rows: min-content minmax(auto, 1fr) min-content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:host-context(.mat-mdc-dialog-container) {
 | 
			
		||||
  .tb-dialog-actions {
 | 
			
		||||
    padding: 8px 16px 8px 24px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:host ::ng-deep {
 | 
			
		||||
  .tb-markdown-view {
 | 
			
		||||
    .tb-command-code {
 | 
			
		||||
      .code-wrapper {
 | 
			
		||||
        padding: 0;
 | 
			
		||||
        pre[class*=language-] {
 | 
			
		||||
          margin: 0;
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
          background: #F3F6FA;
 | 
			
		||||
          border-color: $tb-primary-color;
 | 
			
		||||
          padding-right: 38px;
 | 
			
		||||
          overflow: scroll;
 | 
			
		||||
          padding-bottom: 4px;
 | 
			
		||||
          min-height: 42px;
 | 
			
		||||
          scrollbar-width: thin;
 | 
			
		||||
 | 
			
		||||
          &::-webkit-scrollbar {
 | 
			
		||||
            width: 4px;
 | 
			
		||||
            height: 4px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      button.clipboard-btn {
 | 
			
		||||
        right: -2px;
 | 
			
		||||
        p {
 | 
			
		||||
          color: $tb-primary-color;
 | 
			
		||||
        }
 | 
			
		||||
        p, div {
 | 
			
		||||
          background-color: #F3F6FA;
 | 
			
		||||
        }
 | 
			
		||||
        div {
 | 
			
		||||
          img {
 | 
			
		||||
            display: none;
 | 
			
		||||
          }
 | 
			
		||||
          &:after {
 | 
			
		||||
            content: "";
 | 
			
		||||
            position: initial;
 | 
			
		||||
            display: block;
 | 
			
		||||
            width: 18px;
 | 
			
		||||
            height: 18px;
 | 
			
		||||
            background: $tb-primary-color;
 | 
			
		||||
            mask-image: url(/assets/copy-code-icon.svg);
 | 
			
		||||
            -webkit-mask-image: url(/assets/copy-code-icon.svg);
 | 
			
		||||
            mask-repeat: no-repeat;
 | 
			
		||||
            -webkit-mask-repeat: no-repeat;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .mdc-button__label > span {
 | 
			
		||||
    .mat-icon {
 | 
			
		||||
      vertical-align: text-bottom;
 | 
			
		||||
      box-sizing: initial;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tabs-icon {
 | 
			
		||||
    margin-right: 8px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tb-form-panel.tb-tab-body {
 | 
			
		||||
    padding: 16px 0 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -20,9 +20,11 @@ import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { Router } from '@angular/router';
 | 
			
		||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
 | 
			
		||||
import { ActionPreferencesPutUserSettings } from '@core/auth/auth.actions';
 | 
			
		||||
 | 
			
		||||
export interface MobileAppConfigurationDialogData {
 | 
			
		||||
  afterAdd: boolean;
 | 
			
		||||
  appSecret: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
@ -36,6 +38,12 @@ export class MobileAppConfigurationDialogComponent extends DialogComponent<Mobil
 | 
			
		||||
 | 
			
		||||
  showDontShowAgain: boolean;
 | 
			
		||||
 | 
			
		||||
  gitRepositoryLink = 'git clone -b master https://github.com/thingsboard/flutter_thingsboard_app.git';
 | 
			
		||||
  pathToConstants = 'lib/constants/app_constants.dart';
 | 
			
		||||
  flutterRunCommand = 'flutter run';
 | 
			
		||||
 | 
			
		||||
  configureApi: string[] = [];
 | 
			
		||||
 | 
			
		||||
  constructor(protected store: Store<AppState>,
 | 
			
		||||
              protected router: Router,
 | 
			
		||||
              @Inject(MAT_DIALOG_DATA) private data: MobileAppConfigurationDialogData,
 | 
			
		||||
@ -45,14 +53,33 @@ export class MobileAppConfigurationDialogComponent extends DialogComponent<Mobil
 | 
			
		||||
 | 
			
		||||
    this.showDontShowAgain = this.data.afterAdd;
 | 
			
		||||
 | 
			
		||||
    this.configureApi.push(`static final thingsBoardApiEndpoint = '${window.location.origin}';`);
 | 
			
		||||
    this.configureApi.push(`static const thingsboardOAuth2AppSecret = '${this.data.appSecret}';`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  close(): void {
 | 
			
		||||
    if (this.notShowAgain && this.showDontShowAgain) {
 | 
			
		||||
      // this.store.dispatch(new ActionPreferencesPutUserSettings({ notDisplayConnectivityAfterAddDevice: true }));
 | 
			
		||||
      this.store.dispatch(new ActionPreferencesPutUserSettings({ notDisplayConfigurationAfterAddMobileApp: true }));
 | 
			
		||||
      this.dialogRef.close(null);
 | 
			
		||||
    } else {
 | 
			
		||||
      this.dialogRef.close(null);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  createMarkDownCommand(commands: string | string[]): string {
 | 
			
		||||
    if (Array.isArray(commands)) {
 | 
			
		||||
      const formatCommands: Array<string> = [];
 | 
			
		||||
      commands.forEach(command => formatCommands.push(this.createMarkDownSingleCommand(command)));
 | 
			
		||||
      return formatCommands.join(`\n<br />\n\n`);
 | 
			
		||||
    } else {
 | 
			
		||||
      return this.createMarkDownSingleCommand(commands);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private createMarkDownSingleCommand(command: string): string {
 | 
			
		||||
    return '```bash\n' +
 | 
			
		||||
      command +
 | 
			
		||||
      '{:copy-code}\n' +
 | 
			
		||||
      '```';
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -52,6 +52,10 @@ import {
 | 
			
		||||
import {
 | 
			
		||||
  MobileAppConfigurationDialogComponent, MobileAppConfigurationDialogData
 | 
			
		||||
} from '@home/pages/mobile/applications/mobile-app-configuration-dialog.component';
 | 
			
		||||
import { select, Store } from '@ngrx/store';
 | 
			
		||||
import { selectUserSettingsProperty } from '@core/auth/auth.selectors';
 | 
			
		||||
import { take } from 'rxjs/operators';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class MobileAppTableConfigResolver  {
 | 
			
		||||
@ -62,7 +66,9 @@ export class MobileAppTableConfigResolver  {
 | 
			
		||||
              private datePipe: DatePipe,
 | 
			
		||||
              private mobileAppService: MobileAppService,
 | 
			
		||||
              private truncatePipe: TruncatePipe,
 | 
			
		||||
              private dialog: MatDialog,) {
 | 
			
		||||
              private dialog: MatDialog,
 | 
			
		||||
              private store: Store<AppState>,
 | 
			
		||||
              ) {
 | 
			
		||||
    this.config.selectionEnabled = false;
 | 
			
		||||
    this.config.entityType = EntityType.MOBILE_APP;
 | 
			
		||||
    this.config.addEnabled = false;
 | 
			
		||||
@ -124,6 +130,18 @@ export class MobileAppTableConfigResolver  {
 | 
			
		||||
    this.config.saveEntity = (mobileApp) => this.mobileAppService.saveMobileApp(mobileApp);
 | 
			
		||||
    this.config.deleteEntity = id => this.mobileAppService.deleteMobileApp(id.id);
 | 
			
		||||
 | 
			
		||||
    this.config.entityAdded = (mobileApp) => {
 | 
			
		||||
      this.store.pipe(select(selectUserSettingsProperty( 'notDisplayConfigurationAfterAddMobileApp'))).pipe(
 | 
			
		||||
        take(1)
 | 
			
		||||
      ).subscribe((settings: boolean) => {
 | 
			
		||||
        if(!settings) {
 | 
			
		||||
          this.configurationApp(null, mobileApp, true);
 | 
			
		||||
        } else {
 | 
			
		||||
          this.config.updateData();
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.config.cellActionDescriptors = this.configureCellActions();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -176,7 +194,8 @@ export class MobileAppTableConfigResolver  {
 | 
			
		||||
      disableClose: true,
 | 
			
		||||
      panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
 | 
			
		||||
      data: {
 | 
			
		||||
        afterAdd
 | 
			
		||||
        afterAdd,
 | 
			
		||||
        appSecret: entity.appSecret
 | 
			
		||||
      }
 | 
			
		||||
    }).afterClosed()
 | 
			
		||||
      .subscribe(() => {
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,12 @@
 | 
			
		||||
  <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
 | 
			
		||||
  <mat-card-content style="padding-top: 16px">
 | 
			
		||||
    <div class="tb-form-panel no-border no-padding" [formGroup]="mobileAppSettingsForm">
 | 
			
		||||
      <div class="tb-form-panel">
 | 
			
		||||
      <div class="tb-form-row no-border no-padding-bottom" *ngIf="isTenantAdmin()">
 | 
			
		||||
        <mat-slide-toggle class="mat-slide" formControlName="useSystemSettings">
 | 
			
		||||
          {{ 'admin.mobile-app.use-system-settings' | translate }}
 | 
			
		||||
        </mat-slide-toggle>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="tb-form-panel" *ngIf="!mobileAppSettingsForm.get('useSystemSettings').value">
 | 
			
		||||
        <div class="tb-form-row column-xs no-border no-padding space-between">
 | 
			
		||||
          <div class="tb-form-panel-title" translate>admin.mobile-app.applications</div>
 | 
			
		||||
          <tb-toggle-select formControlName="useDefaultApp">
 | 
			
		||||
@ -151,7 +156,7 @@
 | 
			
		||||
<!--          </div>-->
 | 
			
		||||
<!--        </div>-->
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="tb-form-panel" formGroupName="qrCodeConfig">
 | 
			
		||||
      <div class="tb-form-panel" formGroupName="qrCodeConfig" *ngIf="!mobileAppSettingsForm.get('useSystemSettings').value">
 | 
			
		||||
        <div class="tb-form-row column-xs no-border no-padding space-between">
 | 
			
		||||
          <div class="tb-form-panel-title" translate>admin.mobile-app.appearance-on-home-page</div>
 | 
			
		||||
          <tb-toggle-select formControlName="showOnHomePage">
 | 
			
		||||
 | 
			
		||||
@ -14,28 +14,26 @@
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import { Component, OnDestroy } from '@angular/core';
 | 
			
		||||
import { Component } from '@angular/core';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { PageComponent } from '@shared/components/page.component';
 | 
			
		||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
			
		||||
import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard';
 | 
			
		||||
import { Subject, takeUntil } from 'rxjs';
 | 
			
		||||
import { MobileApplicationService } from '@core/http/mobile-application.service';
 | 
			
		||||
import {
 | 
			
		||||
  BadgePosition,
 | 
			
		||||
  badgePositionTranslationsMap,
 | 
			
		||||
  QrCodeSettings
 | 
			
		||||
} from '@shared/models/mobile-app.models';
 | 
			
		||||
import { BadgePosition, badgePositionTranslationsMap, QrCodeSettings } from '@shared/models/mobile-app.models';
 | 
			
		||||
import { ActionUpdateMobileQrCodeEnabled } from '@core/auth/auth.actions';
 | 
			
		||||
import { EntityType } from '@shared/models/entity-type.models';
 | 
			
		||||
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
 | 
			
		||||
import { Authority } from '@shared/models/authority.enum';
 | 
			
		||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-mobile-qr-code-widget',
 | 
			
		||||
  templateUrl: './mobile-qr-code-widget-settings.component.html',
 | 
			
		||||
  styleUrls: ['mobile-qr-code-widget-settings.component.scss', '../../admin/settings-card.scss']
 | 
			
		||||
})
 | 
			
		||||
export class MobileQrCodeWidgetSettingsComponent extends PageComponent implements HasConfirmForm, OnDestroy {
 | 
			
		||||
export class MobileQrCodeWidgetSettingsComponent extends PageComponent implements HasConfirmForm {
 | 
			
		||||
 | 
			
		||||
  mobileAppSettingsForm: FormGroup;
 | 
			
		||||
  mobileAppSettings: QrCodeSettings;
 | 
			
		||||
@ -43,7 +41,7 @@ export class MobileQrCodeWidgetSettingsComponent extends PageComponent implement
 | 
			
		||||
  readonly badgePositionTranslationsMap = badgePositionTranslationsMap;
 | 
			
		||||
  readonly entityType = EntityType;
 | 
			
		||||
 | 
			
		||||
  private readonly destroy$ = new Subject<void>();
 | 
			
		||||
  private authUser = getCurrentAuthUser(this.store);
 | 
			
		||||
 | 
			
		||||
  constructor(protected store: Store<AppState>,
 | 
			
		||||
              private mobileAppService: MobileApplicationService,
 | 
			
		||||
@ -52,8 +50,23 @@ export class MobileQrCodeWidgetSettingsComponent extends PageComponent implement
 | 
			
		||||
    this.buildMobileAppSettingsForm();
 | 
			
		||||
    this.mobileAppService.getMobileAppSettings()
 | 
			
		||||
      .subscribe(settings => this.processMobileAppSettings(settings));
 | 
			
		||||
    if (this.isTenantAdmin()) {
 | 
			
		||||
      // this.mobileAppSettingsForm.get('useSystemSettings').valueChanges.pipe(
 | 
			
		||||
      //   takeUntilDestroyed()
 | 
			
		||||
      // ).subscribe(value => {
 | 
			
		||||
      //   if (value) {
 | 
			
		||||
      //     this.mobileAppSettingsForm.get('androidConfig.enabled').disable();
 | 
			
		||||
      //     this.mobileAppSettingsForm.get('iosConfig.enabled').disable();
 | 
			
		||||
      //     this.mobileAppSettingsForm.get('qrCodeConfig.qrCodeLabelEnabled').disable();
 | 
			
		||||
      //   } else {
 | 
			
		||||
      //     this.mobileAppSettingsForm.get('androidConfig.enabled').enable();
 | 
			
		||||
      //     this.mobileAppSettingsForm.get('iosConfig.enabled').enable();
 | 
			
		||||
      //     this.mobileAppSettingsForm.get('qrCodeConfig.qrCodeLabelEnabled').enable();
 | 
			
		||||
      //   }
 | 
			
		||||
      // });
 | 
			
		||||
    }
 | 
			
		||||
    this.mobileAppSettingsForm.get('useDefaultApp').valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.destroy$)
 | 
			
		||||
      takeUntilDestroyed()
 | 
			
		||||
    ).subscribe(value => {
 | 
			
		||||
      if (value) {
 | 
			
		||||
        this.mobileAppSettingsForm.get('mobileAppBundleId').disable({emitEvent: false});
 | 
			
		||||
@ -77,17 +90,17 @@ export class MobileQrCodeWidgetSettingsComponent extends PageComponent implement
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    // this.mobileAppSettingsForm.get('androidConfig.enabled').valueChanges.pipe(
 | 
			
		||||
    //   takeUntil(this.destroy$)
 | 
			
		||||
    //   takeUntilDestroyed()
 | 
			
		||||
    // ).subscribe(value => {
 | 
			
		||||
    //   this.androidEnableChanged(value);
 | 
			
		||||
    // });
 | 
			
		||||
    // this.mobileAppSettingsForm.get('iosConfig.enabled').valueChanges.pipe(
 | 
			
		||||
    //   takeUntil(this.destroy$)
 | 
			
		||||
    //   takeUntilDestroyed()
 | 
			
		||||
    // ).subscribe(value => {
 | 
			
		||||
    //   this.iosEnableChanged(value);
 | 
			
		||||
    // });
 | 
			
		||||
    this.mobileAppSettingsForm.get('qrCodeConfig.showOnHomePage').valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.destroy$)
 | 
			
		||||
      takeUntilDestroyed()
 | 
			
		||||
    ).subscribe(value => {
 | 
			
		||||
      if (value) {
 | 
			
		||||
        this.mobileAppSettingsForm.get('qrCodeConfig').enable({emitEvent: false});
 | 
			
		||||
@ -99,7 +112,7 @@ export class MobileQrCodeWidgetSettingsComponent extends PageComponent implement
 | 
			
		||||
      this.mobileAppSettingsForm.get('qrCodeConfig.qrCodeLabelEnabled').updateValueAndValidity({onlySelf: true});
 | 
			
		||||
    });
 | 
			
		||||
    this.mobileAppSettingsForm.get('qrCodeConfig.badgeEnabled').valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.destroy$)
 | 
			
		||||
      takeUntilDestroyed()
 | 
			
		||||
    ).subscribe(value => {
 | 
			
		||||
      if (value) {
 | 
			
		||||
        // if (this.mobileAppSettingsForm.get('androidConfig.enabled').value || this.mobileAppSettingsForm.get('iosConfig.enabled').value) {
 | 
			
		||||
@ -114,7 +127,7 @@ export class MobileQrCodeWidgetSettingsComponent extends PageComponent implement
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    this.mobileAppSettingsForm.get('qrCodeConfig.qrCodeLabelEnabled').valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.destroy$)
 | 
			
		||||
      takeUntilDestroyed()
 | 
			
		||||
    ).subscribe(value => {
 | 
			
		||||
      if (value && this.mobileAppSettingsForm.get('qrCodeConfig.showOnHomePage').value) {
 | 
			
		||||
        this.mobileAppSettingsForm.get('qrCodeConfig.qrCodeLabel').enable({emitEvent: false});
 | 
			
		||||
@ -124,14 +137,13 @@ export class MobileQrCodeWidgetSettingsComponent extends PageComponent implement
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    super.ngOnDestroy();
 | 
			
		||||
    this.destroy$.next();
 | 
			
		||||
    this.destroy$.complete();
 | 
			
		||||
  public isTenantAdmin(): boolean {
 | 
			
		||||
    return this.authUser.authority === Authority.TENANT_ADMIN;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private buildMobileAppSettingsForm() {
 | 
			
		||||
    this.mobileAppSettingsForm = this.fb.group({
 | 
			
		||||
      useSystemSettings: [false],
 | 
			
		||||
      useDefaultApp: [true],
 | 
			
		||||
      mobileAppBundleId: [{value: null, disabled: true}, Validators.required],
 | 
			
		||||
      // androidConfig: this.fb.group({
 | 
			
		||||
@ -157,6 +169,9 @@ export class MobileQrCodeWidgetSettingsComponent extends PageComponent implement
 | 
			
		||||
 | 
			
		||||
  private processMobileAppSettings(mobileAppSettings: QrCodeSettings): void {
 | 
			
		||||
    this.mobileAppSettings = {...mobileAppSettings};
 | 
			
		||||
    if (!this.isTenantAdmin()) {
 | 
			
		||||
      this.mobileAppSettings.useSystemSettings = false;
 | 
			
		||||
    }
 | 
			
		||||
    this.mobileAppSettingsForm.reset(this.mobileAppSettings);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@ import { MobileAppBundleId } from '@shared/models/id/mobile-app-bundle-id';
 | 
			
		||||
import { deepClone, isNotEmptyStr } from '@core/utils';
 | 
			
		||||
 | 
			
		||||
export interface QrCodeSettings extends HasTenantId {
 | 
			
		||||
  useSystemSettings: boolean;
 | 
			
		||||
  useDefaultApp: boolean;
 | 
			
		||||
  mobileAppBundleId: MobileAppBundleId
 | 
			
		||||
  androidConfig: any; //TODO: need remove
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@ export interface UserSettings {
 | 
			
		||||
  openedMenuSections?: string[];
 | 
			
		||||
  notDisplayConnectivityAfterAddDevice?: boolean;
 | 
			
		||||
  notDisplayInstructionsAfterAddEdge?: boolean;
 | 
			
		||||
  notDisplayConfigurationAfterAddMobileApp?: boolean;
 | 
			
		||||
  includeBundleWidgetsInExport?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3489,7 +3489,20 @@
 | 
			
		||||
        "qr-code-widget": "QR code widget",
 | 
			
		||||
        "type-here": "Type hero",
 | 
			
		||||
        "configuration-dialog": "Configuration dialog",
 | 
			
		||||
        "configuration-app": "Configuration app"
 | 
			
		||||
        "configuration-app": "Configuration app",
 | 
			
		||||
        "configuration-step": {
 | 
			
		||||
            "prepare-environment-title": "Prepare development environment",
 | 
			
		||||
            "prepare-environment-text": "Flutter ThingsBoard Mobile Application requires Flutter SDK. Follow instructions to set up Flutter SDK.",
 | 
			
		||||
            "get-source-code-title": "Get app source code",
 | 
			
		||||
            "get-source-code-text": "You can get Flutter ThingsBoard Mobile Application source code by cloning it from the GitHub repository:",
 | 
			
		||||
            "configure-api-title": "Configure ThingsBoard API endpoint",
 | 
			
		||||
            "configure-api-text": "Open the flutter_thingsboard_app project in your editor/IDE. Edit:",
 | 
			
		||||
            "configure-api-hint": "Set the value of the thingsBoardApiEndpoint constant to match the API endpoint of your ThingsBoard server instance. Do not use “localhost” or “127.0.0.1” hostnames.",
 | 
			
		||||
            "run-app-title": "Run the app",
 | 
			
		||||
            "run-app-text": "Run the app as described in your IDE.\nIf using the terminal, run the app with the following command:",
 | 
			
		||||
            "more-information": "Detailed information may be found in our Getting Started documentation.",
 | 
			
		||||
            "getting-started": "Getting Started"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "notification": {
 | 
			
		||||
        "action-button": "Action button",
 | 
			
		||||
 | 
			
		||||
@ -907,6 +907,9 @@ pre.tb-highlight {
 | 
			
		||||
    &.tb-mat-20 {
 | 
			
		||||
      @include tb-mat-icon-size(20);
 | 
			
		||||
    }
 | 
			
		||||
    &.tb-mat-24 {
 | 
			
		||||
      @include tb-mat-icon-size(24);
 | 
			
		||||
    }
 | 
			
		||||
    &.tb-mat-28 {
 | 
			
		||||
      @include tb-mat-icon-size(28);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user