Merge pull request #12139 from vvlladd28/improvement/mobile-center/minor-bug

Fixed and imporvements mobile center
This commit is contained in:
Igor Kulikov 2024-11-29 18:02:22 +02:00 committed by GitHub
commit 9bb2239938
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 101 additions and 30 deletions

View File

@ -114,6 +114,8 @@ export class MobileAppTableConfigResolver {
this.config.entitiesFetchFunction = pageLink => this.mobileAppService.getTenantMobileAppInfos(pageLink);
this.config.loadEntity = id => this.mobileAppService.getMobileAppInfoById(id.id);
this.config.saveEntity = (mobileApp) => this.mobileAppService.saveMobileApp(mobileApp);
this.config.deleteEntityTitle = (mobileApp) => this.translate.instant('mobile.delete-application-title-short', {name: mobileApp.name});
this.config.deleteEntityContent = () => this.translate.instant('mobile.delete-application-text-short');
this.config.deleteEntity = id => this.mobileAppService.deleteMobileApp(id.id);
this.config.cellActionDescriptors = this.configureCellActions();
@ -138,6 +140,7 @@ export class MobileAppTableConfigResolver {
if ($event) {
$event.stopPropagation();
}
if(entity.status === MobileAppStatus.PUBLISHED) {
this.dialog.open<RemoveAppDialogComponent, MobileAppDeleteDialogData,
MobileAppBundleInfo>(RemoveAppDialogComponent, {
disableClose: true,
@ -151,6 +154,9 @@ export class MobileAppTableConfigResolver {
this.config.updateData();
}
});
} else {
this.config.getTable().deleteEntity($event, entity);
}
}
private mobileStatus(status: MobileAppStatus): string {

View File

@ -148,7 +148,7 @@
</mat-form-field>
<mat-form-field appearance="outline" *ngIf="entityForm.get('platformType').value === PlatformType.ANDROID">
<mat-label translate>mobile.sha256-certificate-fingerprints</mat-label>
<input matInput [required]="entityForm.get('status').value === MobileAppStatus.PUBLISHED" formControlName="sha256CertFingerprints">
<input matInput [required]="entityForm.get('status').value !== MobileAppStatus.DRAFT" formControlName="sha256CertFingerprints">
<tb-copy-button
matSuffix
miniButton="false"
@ -166,7 +166,7 @@
</mat-form-field>
<mat-form-field appearance="outline" *ngIf="entityForm.get('platformType').value === PlatformType.IOS">
<mat-label translate>mobile.app-id</mat-label>
<input matInput [required]="entityForm.get('status').value === MobileAppStatus.PUBLISHED" formControlName="appId">
<input matInput [required]="entityForm.get('status').value !== MobileAppStatus.DRAFT" formControlName="appId">
<tb-copy-button
matSuffix
miniButton="false"

View File

@ -79,7 +79,7 @@ export class MobileAppComponent extends EntityComponent<MobileApp> {
Validators.pattern(/^https?:\/\/play\.google\.com\/store\/apps\/details\?id=[a-zA-Z0-9._]+$/)],
sha256CertFingerprints: [entity?.storeInfo?.sha256CertFingerprints ? entity.storeInfo.sha256CertFingerprints : '',
Validators.pattern(/^[A-Fa-f0-9]{2}(:[A-Fa-f0-9]{2}){1,31}$/)],
appId: [entity?.storeInfo?.appId ? entity.storeInfo.appId : '', Validators.pattern(/^\d{7,10}$/)],
appId: [entity?.storeInfo?.appId ? entity.storeInfo.appId : '', Validators.pattern(/^[A-Z0-9]{10}\.[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*$/)],
}),
});
@ -126,7 +126,8 @@ export class MobileAppComponent extends EntityComponent<MobileApp> {
override updateFormState(): void {
super.updateFormState();
if (this.isEdit && this.entityForm && !this.isAdd) {
this.entityForm.get('status').updateValueAndValidity({onlySelf: false});
this.entityForm.get('status').updateValueAndValidity({onlySelf: true});
this.entityForm.get('platformType').updateValueAndValidity({onlySelf: true});
this.entityForm.get('platformType').disable({emitEvent: false});
if (this.entityForm.get('platformType').value === PlatformType.ANDROID) {
this.entityForm.get('storeInfo.appId').disable({emitEvent: false});

View File

@ -36,7 +36,7 @@
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
(click)="suspend()" cdkFocusInitial>
{{ 'action.suspend' | translate }}
</button>
<button mat-button mat-raised-button color="warn"

View File

@ -24,6 +24,8 @@ import { TranslateService } from '@ngx-translate/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { FormBuilder } from '@angular/forms';
import { MobileAppService } from '@core/http/mobile-app.service';
import { mergeMap } from 'rxjs';
import { MobileAppStatus } from '@shared/models/mobile-app.models';
export interface MobileAppDeleteDialogData {
id: string;
@ -60,6 +62,17 @@ export class RemoveAppDialogComponent extends DialogComponent<RemoveAppDialogCom
this.dialogRef.close(false);
}
suspend(): void {
this.mobileAppService.getMobileAppInfoById(this.data.id).pipe(
mergeMap(value => {
value.status = MobileAppStatus.SUSPENDED;
return this.mobileAppService.saveMobileApp(value)
})
).subscribe(() => {
this.dialogRef.close(true);
});
}
delete(): void {
this.mobileAppService.deleteMobileApp(this.data.id).subscribe(() => {
this.dialogRef.close(true);

View File

@ -62,7 +62,7 @@ export class CustomMobilePageComponent implements ControlValueAccessor, Validato
icon: ['star'],
label: ['', Validators.required],
type: [MobilePageType.DASHBOARD],
dashboardId: ['', Validators.required],
dashboardId: this.fb.control<string>(null, Validators.required),
url: [{value:'', disabled: true}, [Validators.required, Validators.pattern(/^(https?:\/\/)?(localhost|([\w\-]+\.)+[\w\-]+)(:\d+)?(\/[\w\-._~:\/?#[\]@!$&'()*+,;=%]*)?$/)]],
path: [{value:'', disabled: true}, [Validators.required, Validators.pattern(/^(\/[\w\-._~:\/?#[\]@!$&'()*+,;=%]*)?$/)]]
});

View File

@ -51,6 +51,16 @@
<tb-markdown usePlainMarkdown containerClass="tb-command-code"
[data]=createMarkDownCommand(configureApi)></tb-markdown>
</div>
<div class="tb-form-panel stroked" *ngIf="setApplication">
<div class="tb-form-panel-title" translate>mobile.configuration-step.configure-package-title</div>
<div translate>mobile.configuration-step.configure-package-text</div>
<div translate>mobile.configuration-step.configure-package-text-install</div>
<tb-markdown usePlainMarkdown containerClass="tb-command-code"
[data]=createMarkDownCommand(flutterInstallRenameCommand)></tb-markdown>
<div translate>mobile.configuration-step.configure-package-run-commands</div>
<tb-markdown usePlainMarkdown containerClass="tb-command-code"
[data]=createMarkDownCommand(renameCommands)></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>
@ -62,7 +72,7 @@
<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"
href="https://docs.flutter.dev/learn-flutter"
target="_blank">
<mat-icon class="tb-mat-24">rocket_launch</mat-icon>{{ 'mobile.configuration-step.getting-started' | translate }}
</a>

View File

@ -40,7 +40,8 @@
background: #F3F6FA;
border-color: $tb-primary-color;
padding-right: 38px;
overflow: scroll;
overflow: hidden;
overflow-x: auto;
padding-bottom: 4px;
min-height: 42px;
scrollbar-width: thin;
@ -51,7 +52,7 @@
}
}
}
button.clipboard-btn {
button.clipboard-btn, button.clipboard-btn.multiline {
right: -2px;
p {
color: $tb-primary-color;
@ -70,8 +71,8 @@
width: 18px;
height: 18px;
background: $tb-primary-color;
mask-image: url(/src/assets/copy-code-icon.svg);
-webkit-mask-image: url(/src/assets/copy-code-icon.svg);
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;
}

View File

@ -21,10 +21,12 @@ 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';
import { MobileApp } from '@shared/models/mobile-app.models';
export interface MobileAppConfigurationDialogData {
afterAdd: boolean;
appSecret: string;
androidApp: MobileApp;
iosApp: MobileApp;
}
@Component({
@ -35,14 +37,18 @@ export interface MobileAppConfigurationDialogData {
export class MobileAppConfigurationDialogComponent extends DialogComponent<MobileAppConfigurationDialogComponent> {
notShowAgain = false;
setApplication = false;
showDontShowAgain: boolean;
gitRepositoryLink = 'git clone -b master https://github.com/thingsboard/flutter_thingsboard_app.git';
pathToConstants = 'lib/constants/app_constants.dart';
flutterRunCommand = 'flutter run';
flutterInstallRenameCommand = 'flutter pub global activate rename';
configureApi: string[] = [];
configureApi: string;
renameCommands: string[] = [];
constructor(protected store: Store<AppState>,
protected router: Router,
@ -53,8 +59,30 @@ export class MobileAppConfigurationDialogComponent extends DialogComponent<Mobil
this.showDontShowAgain = this.data.afterAdd;
this.configureApi.push(`static const thingsBoardApiEndpoint = '${window.location.origin}';`);
this.configureApi.push(`static const thingsboardOAuth2AppSecret = '${this.data.appSecret}';`);
this.setApplication = !!this.data.androidApp || !!this.data.iosApp;
this.configureApi = `static const thingsBoardApiEndpoint = '${window.location.origin}';`;
if (this.setApplication) {
this.configureApi += '\n';
if (!!this.data.androidApp) {
this.configureApi += `\nstatic const thingsboardAndroidAppSecret = '${this.data.androidApp.appSecret}';`;
}
if (!!this.data.iosApp) {
this.configureApi += `\nstatic const thingsboardIOSAppSecret = '${this.data.iosApp.appSecret}';`;
}
}
if (this.setApplication) {
if (this.data.androidApp?.pkgName === this.data.iosApp?.pkgName) {
this.renameCommands.push(`rename setBundleId --targets android, ios --value "${this.data.androidApp.pkgName}"`);
} else {
if (!!this.data.androidApp) {
this.renameCommands.push(`rename setBundleId --targets android --value "${this.data.androidApp.pkgName}"`);
}
if (!!this.data.iosApp) {
this.renameCommands.push(`rename setBundleId --targets ios --value "${this.data.iosApp.pkgName}"`);
}
}
}
}
close(): void {

View File

@ -188,7 +188,8 @@ export class MobileBundleTableConfigResolver {
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: {
afterAdd,
appSecret: data.androidApp?.appSecret || data.iosApp?.appSecret
androidApp: data.androidApp,
iosApp: data.iosApp
}
}).afterClosed()
.subscribe(() => {

View File

@ -28,6 +28,7 @@
<button mat-raised-button
color="primary"
type="button"
*ngIf="!disabled"
(click)="apply()"
[disabled]="editorControl.invalid || !editorControl.dirty">
{{ 'action.apply' | translate }}

View File

@ -54,7 +54,8 @@ export class EditorPanelComponent implements OnInit {
height: 400,
autofocus: false,
branding: false,
promotion: false
promotion: false,
resize: false
};
constructor(private fb: FormBuilder) {
@ -64,6 +65,9 @@ export class EditorPanelComponent implements OnInit {
this.editorControl = this.fb.control(this.content);
if (this.disabled) {
this.editorControl.disable({emitEvent: false});
this.tinyMceOptions.toolbar = false;
this.tinyMceOptions.menubar = false;
this.tinyMceOptions.statusbar = false;
}
}

View File

@ -3443,6 +3443,8 @@
"delete-application": "Delete application",
"delete-application-button-text": "I understand consequences, delete application",
"delete-application-text": "This action can not be undone. This will permanently delete your application.<br/>If you dont want to delete it permanently you can <b>suspend</b> application temporary.<br/><b>To delete</b> the application anyway please type <b>\"{{phrase}}\"</b> to confirm.",
"delete-application-title-short": "Are you sure you want to delete the application '{{name}}'?",
"delete-application-text-short": "Be careful, after the confirmation the applications and all related data will become unrecoverable.",
"delete-application-phrase": "delete application",
"delete-applications-bundle-text": "Be careful, after the confirmation the mobile bundle and all related data will become unrecoverable.",
"delete-applications-bundle-title": "Are you sure you want to delete the mobile bundle '{{bundleName}}'?",
@ -3542,7 +3544,11 @@
"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"
"getting-started": "Getting Started",
"configure-package-title": "Configure application package",
"configure-package-text": "You can manually change the Application Package or use third party CLI tool.",
"configure-package-text-install": "To install the Rename CLI Tool, execute the following command:",
"configure-package-run-commands": "Run these commands in the root directory of your project:"
}
},
"notification": {