UI: qr code: extended mobile app settings with default links, refactored badges, removed redundant apis

This commit is contained in:
rusikv 2024-06-06 13:25:23 +03:00
parent 9ae3bd167a
commit 9eb4a8fbe6
8 changed files with 66 additions and 39 deletions

View File

@ -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 { MobileAppSettings, MobileAppStoreLinks } from '@shared/models/mobile-app.models'; import { MobileAppSettings } from '@shared/models/mobile-app.models';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -42,8 +42,4 @@ export class MobileAppService {
return this.http.get<string>(`/api/mobile/deepLink`, defaultHttpOptionsFromConfig(config)); return this.http.get<string>(`/api/mobile/deepLink`, defaultHttpOptionsFromConfig(config));
} }
public getMobileAppStoreLinks(config?: RequestConfig): Observable<MobileAppStoreLinks> {
return this.http.get<MobileAppStoreLinks>('/api/mobile/app/storeLinks', defaultHttpOptionsFromConfig(config));
}
} }

View File

@ -26,14 +26,17 @@
[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">
<div class="tb-qrcode" (click)="navigateByDeepLink($event)" [innerHTML]="qrCodeSVG | safe: 'html'" ></div> <div class="tb-qrcode" (click)="navigateByDeepLink($event)" [innerHTML]="qrCodeSVG | safe: 'html'" ></div>
<div class="tb-badges" *ngIf="(mobileAppSettings?.iosConfig.enabled || mobileAppSettings?.androidConfig.enabled) && <div class="tb-badges" [class.tb-no-interaction]="previewMode"
mobileAppSettings?.qrCodeConfig.badgeEnabled && showBadgeContainer"> *ngIf="(mobileAppSettings?.iosConfig.enabled || mobileAppSettings?.androidConfig.enabled) &&
<img *ngIf="mobileAppSettings?.iosConfig.enabled" mobileAppSettings?.qrCodeConfig.badgeEnabled && showBadgeContainer">
(click)="navigateByStoreLink($event, appStoreLink)" <a *ngIf="mobileAppSettings?.iosConfig.enabled" [href]="appStoreLink" target="_blank">
src="assets/android-ios-stores-badges/ios_store_en_black_badge.svg"> <img alt="{{ 'widgets.mobile-app-qr-code.download-on-the-app-store' | translate }}"
<img *ngIf="mobileAppSettings?.androidConfig.enabled" src="assets/android-ios-stores-badges/ios_store_en_black_badge.svg">
(click)="navigateByStoreLink($event, googlePlayLink)" </a>
src="assets/android-ios-stores-badges/android_store_en_black_badge.svg"> <a *ngIf="mobileAppSettings?.androidConfig.enabled" [href]="googlePlayLink" target="_blank">
<img alt="{{ 'widgets.mobile-app-qr-code.get-it-on-google-play' | translate }}"
src="assets/android-ios-stores-badges/android_store_en_black_badge.svg">
</a>
</div> </div>
</div> </div>
<div class="tb-qrcode-label" *ngIf="mobileAppSettings?.qrCodeConfig.qrCodeLabelEnabled"> <div class="tb-qrcode-label" *ngIf="mobileAppSettings?.qrCodeConfig.qrCodeLabelEnabled">

View File

@ -68,17 +68,22 @@
flex-direction: column; flex-direction: column;
flex: 0.44; flex: 0.44;
gap: 8px; gap: 8px;
img { &.tb-no-interaction {
cursor: pointer; pointer-events: none;
}
a {
display: contents;
border-bottom: none;
&:hover {
border-bottom: none;
}
} }
} }
} }
:host ::ng-deep { :host ::ng-deep {
.tb-mobile-app-qrcode-panel { .tb-mobile-app-qrcode-panel .tb-widget-title {
> div.tb-widget-title { padding: 0;
padding: 0; z-index: 1;
z-index: 1;
}
} }
} }

View File

@ -90,6 +90,13 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
if (!this.mobileAppSettings) { if (!this.mobileAppSettings) {
this.mobileAppService.getMobileAppSettings().subscribe((settings => { this.mobileAppService.getMobileAppSettings().subscribe((settings => {
this.mobileAppSettings = settings; this.mobileAppSettings = settings;
const useDefaultApp = this.mobileAppSettings.useDefaultApp;
this.appStoreLink = useDefaultApp ? this.mobileAppSettings.defaultAppStoreLink :
this.mobileAppSettings.iosConfig.storeLink;
this.googlePlayLink = useDefaultApp ? this.mobileAppSettings.defaultGooglePlayLink :
this.mobileAppSettings.androidConfig.storeLink;
if (isDefinedAndNotNull(this.ctx.settings.useSystemSettings) && !this.ctx.settings.useSystemSettings) { if (isDefinedAndNotNull(this.ctx.settings.useSystemSettings) && !this.ctx.settings.useSystemSettings) {
this.mobileAppSettings = mergeDeep(this.mobileAppSettings, this.ctx.settings); this.mobileAppSettings = mergeDeep(this.mobileAppSettings, this.ctx.settings);
} }
@ -111,10 +118,6 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
} else { } else {
this.previewMode = true; this.previewMode = true;
} }
this.mobileAppService.getMobileAppStoreLinks().subscribe(storeLinks => {
this.googlePlayLink = storeLinks.googlePlayLink;
this.appStoreLink = storeLinks.appStoreLink;
});
this.initMobileAppQRCode(); this.initMobileAppQRCode();
} }
@ -137,13 +140,6 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
} }
} }
navigateByStoreLink($event, storeLink: string) {
if ($event) {
$event.stopPropagation();
}
window.open(storeLink, '_blank');
}
private initMobileAppQRCode() { private initMobileAppQRCode() {
if (this.deepLinkTTLTimeoutID) { if (this.deepLinkTTLTimeoutID) {
clearTimeout(this.deepLinkTTLTimeoutID); clearTimeout(this.deepLinkTTLTimeoutID);

View File

@ -82,6 +82,15 @@
<div class="fixed-title-width-230">{{ 'admin.mobile-app.google-play-link' | translate }}</div> <div class="fixed-title-width-230">{{ 'admin.mobile-app.google-play-link' | translate }}</div>
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic"> <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="storeLink" placeholder="{{'admin.mobile-app.set' | translate}}"> <input matInput formControlName="storeLink" placeholder="{{'admin.mobile-app.set' | translate}}">
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="'admin.mobile-app.google-play-link-required' | translate"
*ngIf="mobileAppSettingsForm.get('androidConfig.storeLink').hasError('required')
&& mobileAppSettingsForm.get('androidConfig.storeLink').touched"
class="tb-error">
warning
</mat-icon>
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
@ -116,6 +125,15 @@
<div class="fixed-title-width-230">{{ 'admin.mobile-app.app-store-link' | translate }}</div> <div class="fixed-title-width-230">{{ 'admin.mobile-app.app-store-link' | translate }}</div>
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic"> <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="storeLink" placeholder="{{'admin.mobile-app.set' | translate}}"> <input matInput formControlName="storeLink" placeholder="{{'admin.mobile-app.set' | translate}}">
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="'admin.mobile-app.app-store-link-required' | translate"
*ngIf="mobileAppSettingsForm.get('iosConfig.storeLink').hasError('required')
&& mobileAppSettingsForm.get('iosConfig.storeLink').touched"
class="tb-error">
warning
</mat-icon>
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>

View File

@ -57,14 +57,18 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf
if (value) { if (value) {
this.mobileAppSettingsForm.get('androidConfig.appPackage').disable({emitEvent: false}); this.mobileAppSettingsForm.get('androidConfig.appPackage').disable({emitEvent: false});
this.mobileAppSettingsForm.get('androidConfig.sha256CertFingerprints').disable({emitEvent: false}); this.mobileAppSettingsForm.get('androidConfig.sha256CertFingerprints').disable({emitEvent: false});
this.mobileAppSettingsForm.get('androidConfig.storeLink').disable({emitEvent: false});
this.mobileAppSettingsForm.get('iosConfig.appId').disable({emitEvent: false}); this.mobileAppSettingsForm.get('iosConfig.appId').disable({emitEvent: false});
this.mobileAppSettingsForm.get('iosConfig.storeLink').disable({emitEvent: false});
} else { } else {
if (this.mobileAppSettingsForm.get('androidConfig.enabled').value) { if (this.mobileAppSettingsForm.get('androidConfig.enabled').value) {
this.mobileAppSettingsForm.get('androidConfig.appPackage').enable({emitEvent: false}); this.mobileAppSettingsForm.get('androidConfig.appPackage').enable({emitEvent: false});
this.mobileAppSettingsForm.get('androidConfig.sha256CertFingerprints').enable({emitEvent: false}); this.mobileAppSettingsForm.get('androidConfig.sha256CertFingerprints').enable({emitEvent: false});
this.mobileAppSettingsForm.get('androidConfig.storeLink').enable({emitEvent: false});
} }
if (this.mobileAppSettingsForm.get('iosConfig.enabled').value) { if (this.mobileAppSettingsForm.get('iosConfig.enabled').value) {
this.mobileAppSettingsForm.get('iosConfig.appId').enable({emitEvent: false}); this.mobileAppSettingsForm.get('iosConfig.appId').enable({emitEvent: false});
this.mobileAppSettingsForm.get('iosConfig.storeLink').enable({emitEvent: false});
} }
} }
}); });
@ -129,12 +133,12 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf
enabled: [true], enabled: [true],
appPackage: [{value: '', disabled: true}, [Validators.required]], appPackage: [{value: '', disabled: true}, [Validators.required]],
sha256CertFingerprints: [{value: '', disabled: true}, [Validators.required]], sha256CertFingerprints: [{value: '', disabled: true}, [Validators.required]],
storeLink: [''] storeLink: ['', [Validators.required]]
}), }),
iosConfig: this.fb.group({ iosConfig: this.fb.group({
enabled: [true], enabled: [true],
appId: [{value: '', disabled: true}, [Validators.required]], appId: [{value: '', disabled: true}, [Validators.required]],
storeLink: [''] storeLink: ['', [Validators.required]]
}), }),
qrCodeConfig: this.fb.group({ qrCodeConfig: this.fb.group({
showOnHomePage: [true], showOnHomePage: [true],
@ -156,10 +160,12 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf
if (!this.mobileAppSettingsForm.get('useDefaultApp').value) { if (!this.mobileAppSettingsForm.get('useDefaultApp').value) {
this.mobileAppSettingsForm.get('androidConfig.appPackage').enable({emitEvent: false}); this.mobileAppSettingsForm.get('androidConfig.appPackage').enable({emitEvent: false});
this.mobileAppSettingsForm.get('androidConfig.sha256CertFingerprints').enable({emitEvent: false}); this.mobileAppSettingsForm.get('androidConfig.sha256CertFingerprints').enable({emitEvent: false});
this.mobileAppSettingsForm.get('androidConfig.storeLink').enable({emitEvent: false});
} }
} else { } else {
this.mobileAppSettingsForm.get('androidConfig.appPackage').disable({emitEvent: false}); this.mobileAppSettingsForm.get('androidConfig.appPackage').disable({emitEvent: false});
this.mobileAppSettingsForm.get('androidConfig.sha256CertFingerprints').disable({emitEvent: false}); this.mobileAppSettingsForm.get('androidConfig.sha256CertFingerprints').disable({emitEvent: false});
this.mobileAppSettingsForm.get('androidConfig.storeLink').disable({emitEvent: false});
} }
this.mobileAppSettingsForm.get('qrCodeConfig.badgeEnabled').updateValueAndValidity({onlySelf: true}); this.mobileAppSettingsForm.get('qrCodeConfig.badgeEnabled').updateValueAndValidity({onlySelf: true});
} }
@ -168,9 +174,11 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf
if (value) { if (value) {
if (!this.mobileAppSettingsForm.get('useDefaultApp').value) { if (!this.mobileAppSettingsForm.get('useDefaultApp').value) {
this.mobileAppSettingsForm.get('iosConfig.appId').enable({emitEvent: false}); this.mobileAppSettingsForm.get('iosConfig.appId').enable({emitEvent: false});
this.mobileAppSettingsForm.get('iosConfig.storeLink').enable({emitEvent: false});
} }
} else { } else {
this.mobileAppSettingsForm.get('iosConfig.appId').disable({emitEvent: false}); this.mobileAppSettingsForm.get('iosConfig.appId').disable({emitEvent: false});
this.mobileAppSettingsForm.get('iosConfig.storeLink').disable({emitEvent: false});
} }
this.mobileAppSettingsForm.get('qrCodeConfig.badgeEnabled').updateValueAndValidity({onlySelf: true}); this.mobileAppSettingsForm.get('qrCodeConfig.badgeEnabled').updateValueAndValidity({onlySelf: true});
} }

View File

@ -21,6 +21,8 @@ export interface MobileAppSettings extends HasTenantId {
androidConfig: AndroidConfig; androidConfig: AndroidConfig;
iosConfig: IosConfig; iosConfig: IosConfig;
qrCodeConfig: QRCodeConfig; qrCodeConfig: QRCodeConfig;
defaultGooglePlayLink: string;
defaultAppStoreLink: string;
} }
export interface AndroidConfig { export interface AndroidConfig {
@ -54,11 +56,6 @@ export enum BadgePosition {
LEFT = 'LEFT' LEFT = 'LEFT'
} }
export interface MobileAppStoreLinks {
googlePlayLink: string;
appStoreLink: string;
}
export const badgePositionTranslationsMap = new Map<BadgePosition, string>([ export const badgePositionTranslationsMap = new Map<BadgePosition, string>([
[BadgePosition.RIGHT, 'admin.mobile-app.right'], [BadgePosition.RIGHT, 'admin.mobile-app.right'],
[BadgePosition.LEFT, 'admin.mobile-app.left'] [BadgePosition.LEFT, 'admin.mobile-app.left']

View File

@ -438,7 +438,9 @@
"app-id": "App ID", "app-id": "App ID",
"app-id-required": "App ID is required", "app-id-required": "App ID is required",
"google-play-link": "Google Play link", "google-play-link": "Google Play link",
"google-play-link-required": "Google Play link is required",
"app-store-link": "App Store link", "app-store-link": "App Store link",
"app-store-link-required": "App Store link is required",
"appearance": "Appearance", "appearance": "Appearance",
"appearance-on-home-page": "Appearance on Home page", "appearance-on-home-page": "Appearance on Home page",
"enabled": "Enabled", "enabled": "Enabled",
@ -5567,7 +5569,9 @@
}, },
"widgets": { "widgets": {
"mobile-app-qr-code": { "mobile-app-qr-code": {
"configuration-hint": "The configuration depends on the Mobile app QR code widget in platform main settings" "configuration-hint": "The configuration depends on the Mobile app QR code widget in platform main settings",
"get-it-on-google-play": "Get it on Google Play",
"download-on-the-app-store": "Download on the App Store"
}, },
"action-button": { "action-button": {
"behavior": "Behavior", "behavior": "Behavior",