Merge pull request #10918 from rusikv/enhancement/mobile-qr-home
Mobile app qr code improvements
This commit is contained in:
commit
af35d6a678
@ -11,13 +11,13 @@
|
|||||||
"resources": [],
|
"resources": [],
|
||||||
"templateHtml": "<tb-mobile-app-qrcode-widget\n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-mobile-app-qrcode-widget>",
|
"templateHtml": "<tb-mobile-app-qrcode-widget\n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-mobile-app-qrcode-widget>",
|
||||||
"templateCss": "",
|
"templateCss": "",
|
||||||
"controllerScript": "self.onInit = function() {\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '250px',\n previewHeight: '250px',\n embedTitlePanel: true\n };\n};",
|
"controllerScript": "self.onInit = function() {\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '250px',\n embedTitlePanel: true\n };\n};",
|
||||||
"settingsSchema": "",
|
"settingsSchema": "",
|
||||||
"dataKeySettingsSchema": "",
|
"dataKeySettingsSchema": "",
|
||||||
"settingsDirective": "tb-mobile-app-qr-code-widget-settings",
|
"settingsDirective": "tb-mobile-app-qr-code-widget-settings",
|
||||||
"hasBasicMode": true,
|
"hasBasicMode": true,
|
||||||
"basicModeDirective": "tb-mobile-app-qr-code-basic-config",
|
"basicModeDirective": "tb-mobile-app-qr-code-basic-config",
|
||||||
"defaultConfig": "{\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"useSystemSettings\":true,\"qrCodeConfig\":{\"badgeEnabled\":true,\"badgePosition\":\"RIGHT\",\"qrCodeLabelEnabled\":true,\"qrCodeLabel\":\"Scan to connect or download mobile app\"},\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Mobile app QR code\",\"dropShadow\":true,\"showTitleIcon\":false,\"titleTooltip\":\"\",\"enableFullscreen\":false,\"margin\":\"0px\",\"borderRadius\":\"0px\",\"widgetStyle\":{},\"widgetCss\":\"\",\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"pageSize\":1024,\"noDataDisplayMessage\":\"\",\"configMode\":\"basic\"}"
|
"defaultConfig": "{\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"useSystemSettings\":true,\"qrCodeConfig\":{\"badgeEnabled\":true,\"badgePosition\":\"RIGHT\",\"qrCodeLabelEnabled\":true,\"qrCodeLabel\":\"Scan to connect or download mobile app\"},\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"padding\":\"12px\"},\"title\":\"Download mobile app\",\"dropShadow\":true,\"showTitleIcon\":false,\"titleTooltip\":\"\",\"enableFullscreen\":false,\"margin\":\"0px\",\"borderRadius\":\"0px\",\"widgetStyle\":{},\"widgetCss\":\"\",\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"pageSize\":1024,\"noDataDisplayMessage\":\"\",\"configMode\":\"basic\",\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"1.5\"},\"titleColor\":\"#000000\",\"iconSize\":\"26px\",\"titleIcon\":\"qr_code\",\"iconColor\":\"#000000\",\"actions\":{}}"
|
||||||
},
|
},
|
||||||
"tags": [
|
"tags": [
|
||||||
"ios",
|
"ios",
|
||||||
|
|||||||
@ -58,6 +58,8 @@ public class MobileApplicationController extends BaseController {
|
|||||||
|
|
||||||
@Value("${cache.specs.mobileSecretKey.timeToLiveInMinutes:2}")
|
@Value("${cache.specs.mobileSecretKey.timeToLiveInMinutes:2}")
|
||||||
private int mobileSecretKeyTtl;
|
private int mobileSecretKeyTtl;
|
||||||
|
@Value("${mobileApp.domain:demo.thingsboard.io}")
|
||||||
|
private String defaultAppDomain;
|
||||||
|
|
||||||
public static final String ASSET_LINKS_PATTERN = "[{\n" +
|
public static final String ASSET_LINKS_PATTERN = "[{\n" +
|
||||||
" \"relation\": [\"delegate_permission/common.handle_all_urls\"],\n" +
|
" \"relation\": [\"delegate_permission/common.handle_all_urls\"],\n" +
|
||||||
@ -81,11 +83,8 @@ public class MobileApplicationController extends BaseController {
|
|||||||
" }\n" +
|
" }\n" +
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
public static final String ANDROID_APPLICATION_STORE_LINK = "https://play.google.com/store/apps/details?id=org.thingsboard.demo.app";
|
|
||||||
public static final String APPLE_APPLICATION_STORE_LINK = "https://apps.apple.com/us/app/thingsboard-live/id1594355695";
|
|
||||||
public static final String SECRET = "secret";
|
public static final String SECRET = "secret";
|
||||||
public static final String SECRET_PARAM_DESCRIPTION = "A string value representing short-lived secret key";
|
public static final String SECRET_PARAM_DESCRIPTION = "A string value representing short-lived secret key";
|
||||||
public static final String DEFAULT_APP_DOMAIN = "demo.thingsboard.io";
|
|
||||||
public static final String DEEP_LINK_PATTERN = "https://%s/api/noauth/qr?secret=%s&ttl=%s";
|
public static final String DEEP_LINK_PATTERN = "https://%s/api/noauth/qr?secret=%s&ttl=%s";
|
||||||
|
|
||||||
private final SystemSecurityService systemSecurityService;
|
private final SystemSecurityService systemSecurityService;
|
||||||
@ -151,7 +150,7 @@ public class MobileApplicationController extends BaseController {
|
|||||||
if (!mobileAppSettings.isUseDefaultApp()) {
|
if (!mobileAppSettings.isUseDefaultApp()) {
|
||||||
appDomain = platformDomain;
|
appDomain = platformDomain;
|
||||||
} else {
|
} else {
|
||||||
appDomain = DEFAULT_APP_DOMAIN;
|
appDomain = defaultAppDomain;
|
||||||
}
|
}
|
||||||
String deepLink = String.format(DEEP_LINK_PATTERN, appDomain, secret, mobileSecretKeyTtl);
|
String deepLink = String.format(DEEP_LINK_PATTERN, appDomain, secret, mobileSecretKeyTtl);
|
||||||
if (!appDomain.equals(platformDomain)) {
|
if (!appDomain.equals(platformDomain)) {
|
||||||
@ -171,13 +170,17 @@ public class MobileApplicationController extends BaseController {
|
|||||||
|
|
||||||
@GetMapping(value = "/api/noauth/qr")
|
@GetMapping(value = "/api/noauth/qr")
|
||||||
public ResponseEntity<?> getApplicationRedirect(@RequestHeader(value = "User-Agent") String userAgent) {
|
public ResponseEntity<?> getApplicationRedirect(@RequestHeader(value = "User-Agent") String userAgent) {
|
||||||
|
MobileAppSettings mobileAppSettings = mobileAppSettingsService.getMobileAppSettings(TenantId.SYS_TENANT_ID);
|
||||||
|
boolean useDefaultApp = mobileAppSettings.isUseDefaultApp();
|
||||||
|
String googlePlayLink = useDefaultApp ? mobileAppSettings.getDefaultGooglePlayLink() : mobileAppSettings.getAndroidConfig().getStoreLink();
|
||||||
|
String appStoreLink = useDefaultApp ? mobileAppSettings.getDefaultAppStoreLink() : mobileAppSettings.getIosConfig().getStoreLink();
|
||||||
if (userAgent.contains("Android")) {
|
if (userAgent.contains("Android")) {
|
||||||
return ResponseEntity.status(HttpStatus.FOUND)
|
return ResponseEntity.status(HttpStatus.FOUND)
|
||||||
.header("Location", ANDROID_APPLICATION_STORE_LINK)
|
.header("Location", googlePlayLink)
|
||||||
.build();
|
.build();
|
||||||
} else if (userAgent.contains("iPhone") || userAgent.contains("iPad")) {
|
} else if (userAgent.contains("iPhone") || userAgent.contains("iPad")) {
|
||||||
return ResponseEntity.status(HttpStatus.FOUND)
|
return ResponseEntity.status(HttpStatus.FOUND)
|
||||||
.header("Location", APPLE_APPLICATION_STORE_LINK)
|
.header("Location", appStoreLink)
|
||||||
.build();
|
.build();
|
||||||
} else {
|
} else {
|
||||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||||
|
|||||||
@ -1794,3 +1794,12 @@ management:
|
|||||||
elasticsearch:
|
elasticsearch:
|
||||||
# Enable the org.springframework.boot.actuate.elasticsearch.ElasticsearchRestClientHealthIndicator.doHealthCheck
|
# Enable the org.springframework.boot.actuate.elasticsearch.ElasticsearchRestClientHealthIndicator.doHealthCheck
|
||||||
enabled: "false"
|
enabled: "false"
|
||||||
|
|
||||||
|
# Mobile application settings for Thingsboard mobile application
|
||||||
|
mobileApp:
|
||||||
|
# Server domain name for Thingsboard Live mobile application
|
||||||
|
domain: "${TB_MOBILE_APP_DOMAIN:demo.thingsboard.io}"
|
||||||
|
# Link to Google Play store for Thingsboard Live mobile application
|
||||||
|
googlePlayLink: "${TB_MOBILE_APP_GOOGLE_PLAY_LINK:https://play.google.com/store/apps/details?id=org.thingsboard.demo.app}"
|
||||||
|
# Link to App Store for Thingsboard Live mobile application
|
||||||
|
appStoreLink: "${TB_MOBILE_APP_APP_STORE_LINK:https://apps.apple.com/us/app/thingsboard-live/id1594355695}"
|
||||||
|
|||||||
@ -34,5 +34,7 @@ public class AndroidConfig {
|
|||||||
private String appPackage;
|
private String appPackage;
|
||||||
@NoXss
|
@NoXss
|
||||||
private String sha256CertFingerprints;
|
private String sha256CertFingerprints;
|
||||||
|
@NoXss
|
||||||
|
private String storeLink;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,5 +32,7 @@ public class IosConfig {
|
|||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
@NoXss
|
@NoXss
|
||||||
private String appId;
|
private String appId;
|
||||||
|
@NoXss
|
||||||
|
private String storeLink;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,29 +15,46 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.common.data.mobile;
|
package org.thingsboard.server.common.data.mobile;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
import org.thingsboard.server.common.data.BaseData;
|
import org.thingsboard.server.common.data.BaseData;
|
||||||
import org.thingsboard.server.common.data.HasTenantId;
|
import org.thingsboard.server.common.data.HasTenantId;
|
||||||
import org.thingsboard.server.common.data.id.MobileAppSettingsId;
|
import org.thingsboard.server.common.data.id.MobileAppSettingsId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
|
||||||
|
@Schema
|
||||||
@Data
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class MobileAppSettings extends BaseData<MobileAppSettingsId> implements HasTenantId {
|
public class MobileAppSettings extends BaseData<MobileAppSettingsId> implements HasTenantId {
|
||||||
|
|
||||||
private static final long serialVersionUID = 2628323657987010348L;
|
private static final long serialVersionUID = 2628323657987010348L;
|
||||||
|
|
||||||
|
@Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY)
|
||||||
private TenantId tenantId;
|
private TenantId tenantId;
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Type of application: true means use default Thingsboard app", example = "true")
|
||||||
private boolean useDefaultApp;
|
private boolean useDefaultApp;
|
||||||
@Valid
|
@Valid
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Android mobile app configuration.")
|
||||||
private AndroidConfig androidConfig;
|
private AndroidConfig androidConfig;
|
||||||
@Valid
|
@Valid
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Ios mobile app configuration.")
|
||||||
private IosConfig iosConfig;
|
private IosConfig iosConfig;
|
||||||
@Valid
|
@Valid
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "QR code config configuration.")
|
||||||
private QRCodeConfig qrCodeConfig;
|
private QRCodeConfig qrCodeConfig;
|
||||||
|
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
private String defaultGooglePlayLink;
|
||||||
|
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
private String defaultAppStoreLink;
|
||||||
|
|
||||||
public MobileAppSettings() {
|
public MobileAppSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MobileAppSettings(MobileAppSettingsId id) {
|
public MobileAppSettings(MobileAppSettingsId id) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ package org.thingsboard.server.dao.mobile;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.event.TransactionalEventListener;
|
import org.springframework.transaction.event.TransactionalEventListener;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
@ -40,6 +41,11 @@ public class BaseMobileAppSettingsService extends AbstractCachedEntityService<Te
|
|||||||
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
|
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
|
||||||
private static final String DEFAULT_QR_CODE_LABEL = "Scan to connect or download mobile app";
|
private static final String DEFAULT_QR_CODE_LABEL = "Scan to connect or download mobile app";
|
||||||
|
|
||||||
|
@Value("${mobileApp.googlePlayLink:https://play.google.com/store/apps/details?id=org.thingsboard.demo.app}")
|
||||||
|
private String googlePlayLink;
|
||||||
|
@Value("${mobileApp.appStoreLink:https://apps.apple.com/us/app/thingsboard-live/id1594355695}")
|
||||||
|
private String appStoreLink;
|
||||||
|
|
||||||
private final MobileAppSettingsDao mobileAppSettingsDao;
|
private final MobileAppSettingsDao mobileAppSettingsDao;
|
||||||
private final DataValidator<MobileAppSettings> mobileAppSettingsDataValidator;
|
private final DataValidator<MobileAppSettings> mobileAppSettingsDataValidator;
|
||||||
|
|
||||||
@ -49,7 +55,7 @@ public class BaseMobileAppSettingsService extends AbstractCachedEntityService<Te
|
|||||||
try {
|
try {
|
||||||
MobileAppSettings savedMobileAppSettings = mobileAppSettingsDao.save(tenantId, mobileAppSettings);
|
MobileAppSettings savedMobileAppSettings = mobileAppSettingsDao.save(tenantId, mobileAppSettings);
|
||||||
publishEvictEvent(new MobileAppSettingsEvictEvent(tenantId));
|
publishEvictEvent(new MobileAppSettingsEvictEvent(tenantId));
|
||||||
return savedMobileAppSettings;
|
return constructMobileAppSettings(savedMobileAppSettings);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleEvictEvent(new MobileAppSettingsEvictEvent(tenantId));
|
handleEvictEvent(new MobileAppSettingsEvictEvent(tenantId));
|
||||||
checkConstraintViolation(e, Map.of(
|
checkConstraintViolation(e, Map.of(
|
||||||
@ -104,6 +110,10 @@ public class BaseMobileAppSettingsService extends AbstractCachedEntityService<Te
|
|||||||
mobileAppSettings.setAndroidConfig(androidConfig);
|
mobileAppSettings.setAndroidConfig(androidConfig);
|
||||||
mobileAppSettings.setIosConfig(iosConfig);
|
mobileAppSettings.setIosConfig(iosConfig);
|
||||||
}
|
}
|
||||||
|
if (mobileAppSettings.isUseDefaultApp()) {
|
||||||
|
mobileAppSettings.setDefaultGooglePlayLink(googlePlayLink);
|
||||||
|
mobileAppSettings.setDefaultAppStoreLink(appStoreLink);
|
||||||
|
}
|
||||||
return mobileAppSettings;
|
return mobileAppSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,16 +45,7 @@
|
|||||||
{{ '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">
|
||||||
<input matInput formControlName="qrCodeLabel" maxlength="50" placeholder="{{'admin.mobile-app.set' | translate}}">
|
<input matInput formControlName="qrCodeLabel" placeholder="{{'admin.mobile-app.set' | translate}}">
|
||||||
<mat-icon matSuffix
|
|
||||||
matTooltipPosition="above"
|
|
||||||
matTooltipClass="tb-error-tooltip"
|
|
||||||
[matTooltip]="'admin.mobile-app.label-required' | translate"
|
|
||||||
*ngIf="mobileAppQrCodeWidgetConfigForm.get('qrCodeLabel').hasError('required')
|
|
||||||
&& mobileAppQrCodeWidgetConfigForm.get('qrCodeLabel').touched"
|
|
||||||
class="tb-error">
|
|
||||||
warning
|
|
||||||
</mat-icon>
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="tb-form-row column-xs">
|
<div class="tb-form-row column-xs">
|
||||||
@ -110,6 +101,12 @@
|
|||||||
<input matInput formControlName="borderRadius" placeholder="{{ 'widget-config.set' | translate }}">
|
<input matInput formControlName="borderRadius" placeholder="{{ 'widget-config.set' | translate }}">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tb-form-row space-between">
|
||||||
|
<div>{{ 'widget-config.card-padding' | translate }}</div>
|
||||||
|
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<tb-widget-actions-panel
|
<tb-widget-actions-panel
|
||||||
formControlName="actions">
|
formControlName="actions">
|
||||||
|
|||||||
@ -82,6 +82,7 @@ export class MobileAppQrCodeBasicConfigComponent extends BasicWidgetConfigCompon
|
|||||||
|
|
||||||
cardButtons: [this.getCardButtons(configData.config), []],
|
cardButtons: [this.getCardButtons(configData.config), []],
|
||||||
borderRadius: [configData.config.borderRadius, []],
|
borderRadius: [configData.config.borderRadius, []],
|
||||||
|
padding: [settings.padding, []],
|
||||||
|
|
||||||
actions: [configData.config.actions || {}, []]
|
actions: [configData.config.actions || {}, []]
|
||||||
});
|
});
|
||||||
@ -110,6 +111,7 @@ export class MobileAppQrCodeBasicConfigComponent extends BasicWidgetConfigCompon
|
|||||||
this.widgetConfig.config.settings.background = config.background;
|
this.widgetConfig.config.settings.background = config.background;
|
||||||
this.setCardButtons(config.cardButtons, this.widgetConfig.config);
|
this.setCardButtons(config.cardButtons, this.widgetConfig.config);
|
||||||
this.widgetConfig.config.borderRadius = config.borderRadius;
|
this.widgetConfig.config.borderRadius = config.borderRadius;
|
||||||
|
this.widgetConfig.config.settings.padding = config.padding;
|
||||||
|
|
||||||
this.widgetConfig.config.actions = config.actions;
|
this.widgetConfig.config.actions = config.actions;
|
||||||
return this.widgetConfig;
|
return this.widgetConfig;
|
||||||
|
|||||||
@ -50,5 +50,6 @@ export const mobileAppQrCodeWidgetDefaultSettings: MobileAppQrCodeWidgetSettings
|
|||||||
color: 'rgba(255,255,255,0.72)',
|
color: 'rgba(255,255,255,0.72)',
|
||||||
blur: 3
|
blur: 3
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
padding: '12px'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
<div class="tb-mobile-app-qrcode-panel"
|
<div class="tb-mobile-app-qrcode-panel"
|
||||||
|
[style.padding]="padding"
|
||||||
[class.preview]="previewMode"
|
[class.preview]="previewMode"
|
||||||
[style]="backgroundStyle$ | async">
|
[style]="backgroundStyle$ | async">
|
||||||
<div class="tb-mobile-app-qrcode-overlay" [style]="overlayStyle"></div>
|
<div class="tb-mobile-app-qrcode-overlay" [style]="overlayStyle"></div>
|
||||||
@ -24,11 +25,18 @@
|
|||||||
<div class="tb-flex row center align-center shrink"
|
<div class="tb-flex row center 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">
|
||||||
<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"
|
||||||
|
*ngIf="(mobileAppSettings?.iosConfig.enabled || mobileAppSettings?.androidConfig.enabled) &&
|
||||||
mobileAppSettings?.qrCodeConfig.badgeEnabled && showBadgeContainer">
|
mobileAppSettings?.qrCodeConfig.badgeEnabled && showBadgeContainer">
|
||||||
<img *ngIf="mobileAppSettings?.iosConfig.enabled" src="assets/android-ios-stores-badges/ios_store_en_black_badge.svg">
|
<a *ngIf="mobileAppSettings?.iosConfig.enabled" [href]="appStoreLink" target="_blank">
|
||||||
<img *ngIf="mobileAppSettings?.androidConfig.enabled" src="assets/android-ios-stores-badges/android_store_en_black_badge.svg">
|
<img alt="{{ 'widgets.mobile-app-qr-code.download-on-the-app-store' | translate }}"
|
||||||
|
src="assets/android-ios-stores-badges/ios_store_en_black_badge.svg">
|
||||||
|
</a>
|
||||||
|
<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">
|
||||||
|
|||||||
@ -47,10 +47,6 @@
|
|||||||
right: 12px;
|
right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.tb-widget-title {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-qrcode-label {
|
.tb-qrcode-label {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -60,7 +56,7 @@
|
|||||||
|
|
||||||
.tb-qrcode {
|
.tb-qrcode {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 0.3;
|
flex: 0.33;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@ -70,8 +66,30 @@
|
|||||||
.tb-badges {
|
.tb-badges {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 0.4;
|
flex: 0.44;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
&.tb-no-interaction {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
display: contents;
|
||||||
|
border-bottom: none;
|
||||||
|
&:hover {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep {
|
||||||
|
.tb-mobile-app-qrcode-panel {
|
||||||
|
.tb-widget-title {
|
||||||
|
padding: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.tb-qrcode svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -45,6 +45,9 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
|
|||||||
private deepLinkTTL: number;
|
private deepLinkTTL: number;
|
||||||
private deepLinkTTLTimeoutID: NodeJS.Timeout;
|
private deepLinkTTLTimeoutID: NodeJS.Timeout;
|
||||||
|
|
||||||
|
googlePlayLink: string;
|
||||||
|
appStoreLink: string;
|
||||||
|
|
||||||
previewMode = false;
|
previewMode = false;
|
||||||
|
|
||||||
badgePosition = BadgePosition;
|
badgePosition = BadgePosition;
|
||||||
@ -52,6 +55,7 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
|
|||||||
|
|
||||||
backgroundStyle$: Observable<ComponentStyle>;
|
backgroundStyle$: Observable<ComponentStyle>;
|
||||||
overlayStyle: ComponentStyle = {};
|
overlayStyle: ComponentStyle = {};
|
||||||
|
padding: string;
|
||||||
|
|
||||||
qrCodeSVG = '';
|
qrCodeSVG = '';
|
||||||
|
|
||||||
@ -86,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);
|
||||||
}
|
}
|
||||||
@ -101,6 +112,7 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
|
|||||||
this.widgetResize$.observe(this.elementRef.nativeElement);
|
this.widgetResize$.observe(this.elementRef.nativeElement);
|
||||||
this.backgroundStyle$ = backgroundStyle(this.ctx.settings.background, this.imagePipe, this.sanitizer);
|
this.backgroundStyle$ = backgroundStyle(this.ctx.settings.background, this.imagePipe, this.sanitizer);
|
||||||
this.overlayStyle = overlayStyle(this.ctx.settings.background.overlay);
|
this.overlayStyle = overlayStyle(this.ctx.settings.background.overlay);
|
||||||
|
this.padding = this.ctx.settings.background.overlay.enabled ? undefined : this.ctx.settings.padding;
|
||||||
this.cd.markForCheck();
|
this.cd.markForCheck();
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -48,16 +48,7 @@
|
|||||||
{{ '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">
|
||||||
<input matInput formControlName="qrCodeLabel" maxlength="50" placeholder="{{'admin.mobile-app.set' | translate}}">
|
<input matInput formControlName="qrCodeLabel" placeholder="{{'admin.mobile-app.set' | translate}}">
|
||||||
<mat-icon matSuffix
|
|
||||||
matTooltipPosition="above"
|
|
||||||
matTooltipClass="tb-error-tooltip"
|
|
||||||
[matTooltip]="'admin.mobile-app.label-required' | translate"
|
|
||||||
*ngIf="mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabel').hasError('required')
|
|
||||||
&& mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabel').touched"
|
|
||||||
class="tb-error">
|
|
||||||
warning
|
|
||||||
</mat-icon>
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -69,5 +60,11 @@
|
|||||||
</tb-background-settings>
|
</tb-background-settings>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tb-form-row space-between">
|
||||||
|
<div>{{ 'widget-config.card-padding' | translate }}</div>
|
||||||
|
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -55,7 +55,8 @@ export class MobileAppQrCodeWidgetSettingsComponent extends WidgetSettingsCompon
|
|||||||
qrCodeLabelEnabled: [settings.qrCodeConfig.qrCodeLabelEnabled],
|
qrCodeLabelEnabled: [settings.qrCodeConfig.qrCodeLabelEnabled],
|
||||||
qrCodeLabel: [settings.qrCodeConfig.qrCodeLabel]
|
qrCodeLabel: [settings.qrCodeConfig.qrCodeLabel]
|
||||||
}),
|
}),
|
||||||
background: [settings.background]
|
background: [settings.background],
|
||||||
|
padding: [settings.padding, []]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -76,6 +76,24 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tb-form-panel no-border no-padding-top"
|
||||||
|
*ngIf="!mobileAppSettingsForm.get('useDefaultApp').value && mobileAppSettingsForm.get('androidConfig.enabled').value">
|
||||||
|
<div class="tb-form-row column-xs">
|
||||||
|
<div class="fixed-title-width-230">{{ 'admin.mobile-app.google-play-link' | translate }}</div>
|
||||||
|
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<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>
|
||||||
|
</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">
|
||||||
@ -101,6 +119,24 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tb-form-panel no-border no-padding-top"
|
||||||
|
*ngIf="!mobileAppSettingsForm.get('useDefaultApp').value && mobileAppSettingsForm.get('iosConfig.enabled').value">
|
||||||
|
<div class="tb-form-row column-xs">
|
||||||
|
<div class="fixed-title-width-230">{{ 'admin.mobile-app.app-store-link' | translate }}</div>
|
||||||
|
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tb-form-panel" formGroupName="qrCodeConfig">
|
<div class="tb-form-panel" formGroupName="qrCodeConfig">
|
||||||
|
|||||||
@ -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});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -128,11 +132,13 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf
|
|||||||
androidConfig: this.fb.group({
|
androidConfig: this.fb.group({
|
||||||
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: ['', [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: ['', [Validators.required]]
|
||||||
}),
|
}),
|
||||||
qrCodeConfig: this.fb.group({
|
qrCodeConfig: this.fb.group({
|
||||||
showOnHomePage: [true],
|
showOnHomePage: [true],
|
||||||
@ -154,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});
|
||||||
}
|
}
|
||||||
@ -166,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});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,17 +21,21 @@ 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 {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
appPackage: string;
|
appPackage: string;
|
||||||
sha256CertFingerprints: string
|
sha256CertFingerprints: string;
|
||||||
|
storeLink: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IosConfig {
|
export interface IosConfig {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
appId: string;
|
appId: string;
|
||||||
|
storeLink: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QRCodeConfig {
|
export interface QRCodeConfig {
|
||||||
|
|||||||
@ -2665,7 +2665,7 @@
|
|||||||
"dropShadow": false,
|
"dropShadow": false,
|
||||||
"enableFullscreen": false,
|
"enableFullscreen": false,
|
||||||
"widgetStyle": {},
|
"widgetStyle": {},
|
||||||
"widgetCss": " .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title > .title-row > .title {\n padding: 0;\n}\n\n .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title > .title-row > .title {\n padding-bottom: 8px;\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.tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel {\n padding: 0;\n}\n\n@media screen and (min-width: 960px) and (max-height: 900px) {\n .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title {\n display: none;\n }\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n .tb-widget-container > .tb-widget > .tb-widget-content .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\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode-label {\n display: none;\n }\n}\n\n@media screen and (min-width: 960px) and (max-width: 1190px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel {\n gap: 0;\n }\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n min-width: 150px;\n }\n}\n\n@media screen and (max-width: 960px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n max-width: 110px;\n }\n \n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-badges {\n max-width: 140px;\n }\n}\n\n@media screen and (min-width: 1819px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n max-width: 125px;\n }\n \n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-badges {\n max-width: 160px;\n }\n}",
|
"widgetCss": " .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title > .title-row > .title {\n padding: 0;\n}\n\n .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title > .title-row > .title {\n padding-bottom: 8px;\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.tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel {\n padding: 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n .tb-widget-container > .tb-widget > .tb-widget-content .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\n@media screen and (min-width: 960px) and (max-width: 1190px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel {\n gap: 0;\n }\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n min-width: 150px;\n }\n}\n\n@media screen and (max-width: 960px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n max-width: 110px;\n }\n \n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-badges {\n max-width: 140px;\n }\n}\n\n@media screen and (min-width: 1819px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n max-width: 125px;\n }\n \n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-badges {\n max-width: 160px;\n }\n}\n\n@media screen and (min-width: 960px) and (max-height: 960px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode-label {\n display: none;\n }\n}",
|
||||||
"showTitleIcon": false,
|
"showTitleIcon": false,
|
||||||
"titleTooltip": "",
|
"titleTooltip": "",
|
||||||
"titleStyle": null,
|
"titleStyle": null,
|
||||||
|
|||||||
@ -1208,7 +1208,7 @@
|
|||||||
"dropShadow": false,
|
"dropShadow": false,
|
||||||
"enableFullscreen": false,
|
"enableFullscreen": false,
|
||||||
"widgetStyle": {},
|
"widgetStyle": {},
|
||||||
"widgetCss": " .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title > .title-row > .title {\n padding: 0;\n}\n\n .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title > .title-row > .title {\n padding-bottom: 8px;\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.tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel {\n padding: 0;\n}\n\n@media screen and (min-width: 960px) and (max-height: 900px) {\n .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title {\n display: none;\n }\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n .tb-widget-container > .tb-widget > .tb-widget-content .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\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode-label {\n display: none;\n }\n}\n\n@media screen and (min-width: 960px) and (max-width: 1182px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel {\n gap: 0;\n }\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n min-width: 150px;\n }\n}\n\n@media screen and (max-width: 960px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n max-width: 120px;\n }\n \n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-badges {\n max-width: 160px;\n }\n}\n\n@media screen and (min-width: 1819px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n max-width: 125px;\n }\n \n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-badges {\n max-width: 160px;\n }\n}",
|
"widgetCss": " .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title > .title-row > .title {\n padding: 0;\n}\n\n .tb-widget-container > .tb-widget > .tb-widget-content .tb-widget-title > .title-row > .title {\n padding-bottom: 8px;\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.tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel {\n padding: 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n .tb-widget-container > .tb-widget > .tb-widget-content .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\n@media screen and (min-width: 960px) and (max-width: 1182px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel {\n gap: 0;\n }\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n min-width: 150px;\n }\n}\n\n@media screen and (max-width: 960px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n max-width: 120px;\n }\n \n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-badges {\n max-width: 160px;\n }\n}\n\n@media screen and (min-width: 1819px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode {\n max-width: 125px;\n }\n \n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-badges {\n max-width: 160px;\n }\n}\n\n@media screen and (min-width: 960px) and (max-height: 960px) {\n .tb-widget-container > .tb-widget > .tb-widget-content > .tb-widget .tb-mobile-app-qrcode-panel .tb-qrcode-label {\n display: none;\n }\n}",
|
||||||
"showTitleIcon": false,
|
"showTitleIcon": false,
|
||||||
"titleTooltip": "",
|
"titleTooltip": "",
|
||||||
"titleStyle": null,
|
"titleStyle": null,
|
||||||
|
|||||||
@ -437,6 +437,10 @@
|
|||||||
"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",
|
||||||
|
"google-play-link": "Google Play link",
|
||||||
|
"google-play-link-required": "Google Play link is required",
|
||||||
|
"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",
|
||||||
@ -5576,7 +5580,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",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user