UI: added separate mobile qrcode widget to cards bundle
This commit is contained in:
parent
4ee969fa1e
commit
953c215002
@ -17,6 +17,7 @@
|
|||||||
"cards.label_widget",
|
"cards.label_widget",
|
||||||
"cards.dashboard_state_widget",
|
"cards.dashboard_state_widget",
|
||||||
"cards.qr_code",
|
"cards.qr_code",
|
||||||
|
"cards.mobile_app_qr_code",
|
||||||
"cards.attributes_card",
|
"cards.attributes_card",
|
||||||
"cards.html_card",
|
"cards.html_card",
|
||||||
"cards.html_value_card",
|
"cards.html_value_card",
|
||||||
|
|||||||
@ -14,6 +14,6 @@
|
|||||||
"home_page_widgets.documentation_links",
|
"home_page_widgets.documentation_links",
|
||||||
"home_page_widgets.dashboards",
|
"home_page_widgets.dashboards",
|
||||||
"home_page_widgets.usage_info",
|
"home_page_widgets.usage_info",
|
||||||
"home_page_widgets.mobile_app_qr_code"
|
"home_page_widgets.home_mobile_app_qr_code"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"fqn": "home_page_widgets.home_mobile_app_qr_code",
|
||||||
|
"name": "Mobile app QR code",
|
||||||
|
"deprecated": false,
|
||||||
|
"image": null,
|
||||||
|
"description": null,
|
||||||
|
"descriptor": {
|
||||||
|
"type": "static",
|
||||||
|
"sizeX": 6,
|
||||||
|
"sizeY": 3,
|
||||||
|
"resources": [],
|
||||||
|
"templateHtml": "<tb-mobile-app-qrcode-widget>\n</tb-mobile-app-qrcode-widget>",
|
||||||
|
"templateCss": "",
|
||||||
|
"controllerScript": "self.onInit = function() {\n}",
|
||||||
|
"settingsSchema": "",
|
||||||
|
"dataKeySettingsSchema": "",
|
||||||
|
"settingsDirective": "",
|
||||||
|
"defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"cardHtml\":\"<div class='card'>HTML code here</div>\",\"cardCss\":\".card {\\n font-weight: bold;\\n font-size: 32px;\\n color: #999;\\n width: 100%;\\n height: 100%;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n}\"},\"title\":\"Mobile app QR code\",\"dropShadow\":true}"
|
||||||
|
},
|
||||||
|
"tags": null
|
||||||
|
}
|
||||||
@ -1,21 +1,21 @@
|
|||||||
{
|
{
|
||||||
"fqn": "home_page_widgets.mobile_app_qr_code",
|
"fqn": "cards.mobile_app_qr_code",
|
||||||
"name": "Mobile app QR code",
|
"name": "Mobile app QR code",
|
||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"image": null,
|
"image": null,
|
||||||
"description": null,
|
"description": null,
|
||||||
"descriptor": {
|
"descriptor": {
|
||||||
"type": "static",
|
"type": "static",
|
||||||
"sizeX": 6,
|
"sizeX": 7.5,
|
||||||
"sizeY": 3,
|
"sizeY": 3,
|
||||||
"resources": [],
|
"resources": [],
|
||||||
"templateHtml": "<tb-mobile-app-qrcode-widget\n [ctx]=\"ctx\">\n</tb-mobile-app-qrcode-widget>",
|
"templateHtml": "<tb-mobile-app-qrcode-widget\n [ctx]=\"ctx\">\n</tb-mobile-app-qrcode-widget>",
|
||||||
"templateCss": "",
|
"templateCss": "",
|
||||||
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mobileAppQrcodeWidget.ngOnInit();\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.mobileAppQrcodeWidget.ngOnDestroy();\n}",
|
"controllerScript": "self.onInit = function() {\n}\n",
|
||||||
"settingsSchema": "",
|
"settingsSchema": "",
|
||||||
"dataKeySettingsSchema": "",
|
"dataKeySettingsSchema": "",
|
||||||
"settingsDirective": "",
|
"settingsDirective": "tb-mobile-app-qr-code-widget-settings",
|
||||||
"defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"cardHtml\":\"<div class='card'>HTML code here</div>\",\"cardCss\":\".card {\\n font-weight: bold;\\n font-size: 32px;\\n color: #999;\\n width: 100%;\\n height: 100%;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n}\"},\"title\":\"HTML Card\",\"dropShadow\":true}"
|
"defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"useDefaultApp\":true,\"androidConfig\":{\"enabled\":true,\"appPackage\":\"\",\"sha256CertFingerprints\":\"\"},\"iosConfig\":{\"enabled\":true,\"appId\":\"\"},\"qrCodeConfig\":{\"badgeEnabled\":true,\"badgeStyle\":\"ORIGINAL\",\"badgePosition\":\"RIGHT\",\"qrCodeLabelEnabled\":true,\"qrCodeLabel\":\"Scan to connect or download mobile app\"}},\"title\":\"Mobile app QR code\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"noDataDisplayMessage\":\"\",\"showTitleIcon\":false,\"titleTooltip\":\"\",\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
|
||||||
},
|
},
|
||||||
"tags": null
|
"tags": null
|
||||||
}
|
}
|
||||||
@ -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 } from '@shared/models/mobile-app.models';
|
import { MobileAppQRCodeSettings } from '@shared/models/mobile-app.models';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -30,12 +30,12 @@ export class MobileAppService {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMobileAppSettings(config?: RequestConfig): Observable<MobileAppSettings> {
|
public getMobileAppSettings(config?: RequestConfig): Observable<MobileAppQRCodeSettings> {
|
||||||
return this.http.get<MobileAppSettings>(`/api/mobile/app/settings`, defaultHttpOptionsFromConfig(config));
|
return this.http.get<MobileAppQRCodeSettings>(`/api/mobile/app/settings`, defaultHttpOptionsFromConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
public saveMobileAppSettings(mobileAppSettings: MobileAppSettings, config?: RequestConfig): Observable<MobileAppSettings> {
|
public saveMobileAppSettings(mobileAppSettings: MobileAppQRCodeSettings, config?: RequestConfig): Observable<MobileAppQRCodeSettings> {
|
||||||
return this.http.post<MobileAppSettings>(`/api/mobile/app/settings`, mobileAppSettings, defaultHttpOptionsFromConfig(config));
|
return this.http.post<MobileAppQRCodeSettings>(`/api/mobile/app/settings`, mobileAppSettings, defaultHttpOptionsFromConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMobileAppDeepLink( config?: RequestConfig): Observable<string> {
|
public getMobileAppDeepLink( config?: RequestConfig): Observable<string> {
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2024 The Thingsboard Authors
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
|
||||||
|
import {
|
||||||
|
AndroidConfig,
|
||||||
|
BadgePosition,
|
||||||
|
BadgeStyle,
|
||||||
|
IosConfig,
|
||||||
|
QRCodeConfig
|
||||||
|
} from '@shared/models/mobile-app.models';
|
||||||
|
|
||||||
|
export type MobileAppQrCodeWidgetSettings = {
|
||||||
|
useDefaultApp: boolean;
|
||||||
|
androidConfig: AndroidConfig;
|
||||||
|
iosConfig: IosConfig;
|
||||||
|
qrCodeConfig: Omit<QRCodeConfig, 'showOnHomePage'>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mobileAppQrCodeWidgetDefaultSettings: MobileAppQrCodeWidgetSettings = {
|
||||||
|
useDefaultApp: true,
|
||||||
|
androidConfig: {
|
||||||
|
enabled: true,
|
||||||
|
appPackage: '',
|
||||||
|
sha256CertFingerprints: ''
|
||||||
|
},
|
||||||
|
iosConfig: {
|
||||||
|
enabled: true,
|
||||||
|
appId: ''
|
||||||
|
},
|
||||||
|
qrCodeConfig: {
|
||||||
|
badgeEnabled: true,
|
||||||
|
badgeStyle: BadgeStyle.ORIGINAL,
|
||||||
|
badgePosition: BadgePosition.RIGHT,
|
||||||
|
qrCodeLabelEnabled: true,
|
||||||
|
qrCodeLabel: 'Scan to connect or download mobile app'
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,15 +15,15 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<div *ngIf="!previewMode" class="tb-title" translate>admin.mobile-app.connect-mobile-app</div>
|
<div *ngIf="!previewMode && !ctx" class="tb-title" translate>admin.mobile-app.connect-mobile-app</div>
|
||||||
<div class="tb-flex column center align-center">
|
<div class="tb-flex column center align-center">
|
||||||
<div class="tb-flex row align-center shrink" style="margin-bottom: 8px"
|
<div class="tb-flex row align-center shrink"
|
||||||
[class.row]="mobileAppSettings?.qrCodeConfig.badgePosition === badgePosition.RIGHT"
|
[class.row]="mobileAppSettings?.qrCodeConfig.badgePosition === badgePosition.RIGHT"
|
||||||
[class.row-reverse]="mobileAppSettings?.qrCodeConfig.badgePosition === badgePosition.LEFT">
|
[class.row-reverse]="mobileAppSettings?.qrCodeConfig.badgePosition === badgePosition.LEFT">
|
||||||
<canvas #canvas class="tb-qrcode"></canvas>
|
<canvas #canvas class="tb-qrcode"></canvas>
|
||||||
<div *ngIf="mobileAppSettings?.qrCodeConfig.badgeEnabled"
|
<div *ngIf="mobileAppSettings?.qrCodeConfig.badgeEnabled"
|
||||||
class="tb-flex column no-gap tb-badge-container"
|
class="tb-flex column no-gap tb-badge-container"
|
||||||
[class.tb-badge-container]="!previewMode">
|
[class.tb-badge-container]="!previewMode && !ctx">
|
||||||
<ng-container *ngIf="mobileAppSettings.qrCodeConfig.badgeStyle === badgeStyle.ORIGINAL;else white">
|
<ng-container *ngIf="mobileAppSettings.qrCodeConfig.badgeStyle === badgeStyle.ORIGINAL;else white">
|
||||||
<img *ngIf="mobileAppSettings.iosConfig.enabled" [src]="badgeStyleURLMap.get(badgeStyle.ORIGINAL).iOS">
|
<img *ngIf="mobileAppSettings.iosConfig.enabled" [src]="badgeStyleURLMap.get(badgeStyle.ORIGINAL).iOS">
|
||||||
<img *ngIf="mobileAppSettings.androidConfig.enabled" [src]="badgeStyleURLMap.get(badgeStyle.ORIGINAL).android">
|
<img *ngIf="mobileAppSettings.androidConfig.enabled" [src]="badgeStyleURLMap.get(badgeStyle.ORIGINAL).android">
|
||||||
|
|||||||
@ -17,7 +17,6 @@
|
|||||||
@import '../../../../../../scss/constants';
|
@import '../../../../../../scss/constants';
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -25,12 +24,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tb-title {
|
.tb-title {
|
||||||
|
padding-bottom: 12px;
|
||||||
align-self: start;
|
align-self: start;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
letter-spacing: 0.1px;
|
letter-spacing: 0.1px;
|
||||||
color: rgba(0, 0, 0, 0.76);
|
color: rgba(0, 0, 0, 0.76);
|
||||||
|
|
||||||
@media #{$mat-md-lg} {
|
@media #{$mat-md-lg} {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
@ -18,13 +18,14 @@ import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, Input, OnDestr
|
|||||||
import { PageComponent } from '@shared/components/page.component';
|
import { PageComponent } from '@shared/components/page.component';
|
||||||
import { AppState } from '@core/core.state';
|
import { AppState } from '@core/core.state';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { BadgePosition, BadgeStyle, badgeStyleURLMap, MobileAppSettings } from '@shared/models/mobile-app.models';
|
import { BadgePosition, BadgeStyle, badgeStyleURLMap, MobileAppQRCodeSettings } from '@shared/models/mobile-app.models';
|
||||||
import { MobileAppService } from '@core/http/mobile-app.service';
|
import { MobileAppService } from '@core/http/mobile-app.service';
|
||||||
import { WidgetContext } from '@home/models/widget-component.models';
|
import { WidgetContext } from '@home/models/widget-component.models';
|
||||||
import { UtilsService } from '@core/services/utils.service';
|
import { UtilsService } from '@core/services/utils.service';
|
||||||
import { interval, mergeMap, Observable, Subject, takeUntil } from 'rxjs';
|
import { interval, mergeMap, Observable, Subject, takeUntil } from 'rxjs';
|
||||||
import { MINUTE } from '@shared/models/time/time.models';
|
import { MINUTE } from '@shared/models/time/time.models';
|
||||||
import { coerceBoolean } from '@shared/decorators/coercion';
|
import { coerceBoolean } from '@shared/decorators/coercion';
|
||||||
|
import { MobileAppQrCodeWidgetSettings } from '@home/components/widget/lib/cards/mobile-app-qr-code-widge.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-mobile-app-qrcode-widget',
|
selector: 'tb-mobile-app-qrcode-widget',
|
||||||
@ -41,7 +42,7 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
|
|||||||
previewMode: boolean;
|
previewMode: boolean;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set mobileAppSettings(settings: MobileAppSettings) {
|
set mobileAppSettings(settings: MobileAppQRCodeSettings | MobileAppQrCodeWidgetSettings) {
|
||||||
if (settings) {
|
if (settings) {
|
||||||
this.mobileAppSettingsValue = settings;
|
this.mobileAppSettingsValue = settings;
|
||||||
}
|
}
|
||||||
@ -59,7 +60,7 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
|
|||||||
badgePosition = BadgePosition;
|
badgePosition = BadgePosition;
|
||||||
badgeStyleURLMap = badgeStyleURLMap;
|
badgeStyleURLMap = badgeStyleURLMap;
|
||||||
|
|
||||||
private mobileAppSettingsValue: MobileAppSettings;
|
private mobileAppSettingsValue: MobileAppQRCodeSettings | MobileAppQrCodeWidgetSettings;
|
||||||
private deepLinkTTL: number;
|
private deepLinkTTL: number;
|
||||||
|
|
||||||
constructor(protected store: Store<AppState>,
|
constructor(protected store: Store<AppState>,
|
||||||
@ -71,9 +72,8 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
if (this.ctx) {
|
if (this.ctx) {
|
||||||
this.ctx.$scope.mobileAppQrcodeWidget = this;
|
this.mobileAppSettings = this.ctx.settings;
|
||||||
}
|
} else {
|
||||||
if (!this.mobileAppSettings) {
|
|
||||||
this.mobileAppService.getMobileAppSettings().subscribe((settings => {
|
this.mobileAppService.getMobileAppSettings().subscribe((settings => {
|
||||||
this.mobileAppSettings = settings;
|
this.mobileAppSettings = settings;
|
||||||
this.cd.detectChanges();
|
this.cd.detectChanges();
|
||||||
@ -104,7 +104,7 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
|
|||||||
|
|
||||||
updateQRCode(link: string) {
|
updateQRCode(link: string) {
|
||||||
import('qrcode').then((QRCode) => {
|
import('qrcode').then((QRCode) => {
|
||||||
QRCode.toCanvas(this.canvasRef.nativeElement, link, { width: 125});
|
QRCode.toCanvas(this.canvasRef.nativeElement, link, { width: 90 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,130 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright © 2016-2024 The Thingsboard Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<section class="tb-widget-settings tb-form-panel no-border no-padding" [formGroup]="mobileAppQRCodeWidgetSettingsForm" fxLayout="column">
|
||||||
|
<div class="tb-form-panel">
|
||||||
|
<div fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
<div class="tb-form-panel-title" translate>admin.mobile-app.applications</div>
|
||||||
|
<tb-toggle-select formControlName="useDefaultApp">
|
||||||
|
<tb-toggle-option [value]="true">{{ 'admin.mobile-app.default' | translate }}</tb-toggle-option>
|
||||||
|
<tb-toggle-option [value]="false">{{ 'admin.mobile-app.custom' | translate }}</tb-toggle-option>
|
||||||
|
</tb-toggle-select>
|
||||||
|
</div>
|
||||||
|
<div class="tb-form-panel stroked no-padding no-gap" formGroupName="androidConfig">
|
||||||
|
<div class="tb-form-row no-border no-padding-bottom">
|
||||||
|
<mat-slide-toggle class="mat-slide" formControlName="enabled" (click)="$event.stopPropagation()">
|
||||||
|
{{ 'admin.mobile-app.android' | translate }}
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
<div class="tb-form-panel no-border no-padding-top"
|
||||||
|
*ngIf="!mobileAppQRCodeWidgetSettingsForm.get('useDefaultApp').value && mobileAppQRCodeWidgetSettingsForm.get('androidConfig.enabled').value">
|
||||||
|
<div class="tb-form-row column-xs">
|
||||||
|
<div class="tb-fixed-width">{{ 'admin.mobile-app.app-package-name' | translate }}</div>
|
||||||
|
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<input matInput formControlName="appPackage" placeholder="{{'admin.mobile-app.set' | translate}}">
|
||||||
|
<mat-icon matSuffix
|
||||||
|
matTooltipPosition="above"
|
||||||
|
matTooltipClass="tb-error-tooltip"
|
||||||
|
[matTooltip]="'admin.mobile-app.app-package-name-required' | translate"
|
||||||
|
*ngIf="mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').hasError('required')
|
||||||
|
&& mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').touched"
|
||||||
|
class="tb-error">
|
||||||
|
warning
|
||||||
|
</mat-icon>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tb-form-panel no-border no-padding-top"
|
||||||
|
*ngIf="!mobileAppQRCodeWidgetSettingsForm.get('useDefaultApp').value && mobileAppQRCodeWidgetSettingsForm.get('androidConfig.enabled').value">
|
||||||
|
<div class="tb-form-row column-xs">
|
||||||
|
<div class="tb-fixed-width">{{ 'admin.mobile-app.sha256-certificate-fingerprints' | translate }}</div>
|
||||||
|
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<input matInput formControlName="sha256CertFingerprints" placeholder="{{'admin.mobile-app.set' | translate}}">
|
||||||
|
<mat-icon matSuffix
|
||||||
|
matTooltipPosition="above"
|
||||||
|
matTooltipClass="tb-error-tooltip"
|
||||||
|
[matTooltip]="'admin.mobile-app.sha256-certificate-fingerprints-required' | translate"
|
||||||
|
*ngIf="mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').hasError('required')
|
||||||
|
&& mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').touched"
|
||||||
|
class="tb-error">
|
||||||
|
warning
|
||||||
|
</mat-icon>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tb-form-panel stroked no-padding no-gap" formGroupName="iosConfig">
|
||||||
|
<div class="tb-form-row no-border no-padding-bottom">
|
||||||
|
<mat-slide-toggle class="mat-slide" formControlName="enabled" (click)="$event.stopPropagation()">
|
||||||
|
{{ 'admin.mobile-app.ios' | translate }}
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
<div class="tb-form-panel no-border no-padding-top"
|
||||||
|
*ngIf="!mobileAppQRCodeWidgetSettingsForm.get('useDefaultApp').value && mobileAppQRCodeWidgetSettingsForm.get('iosConfig.enabled').value">
|
||||||
|
<div class="tb-form-row column-xs">
|
||||||
|
<div class="tb-fixed-width">{{ 'admin.mobile-app.app-id' | translate }}</div>
|
||||||
|
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<input matInput formControlName="appId" placeholder="{{'admin.mobile-app.set' | translate}}">
|
||||||
|
<mat-icon matSuffix
|
||||||
|
matTooltipPosition="above"
|
||||||
|
matTooltipClass="tb-error-tooltip"
|
||||||
|
[matTooltip]="'admin.mobile-app.app-id-required' | translate"
|
||||||
|
*ngIf="mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').hasError('required')
|
||||||
|
&& mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').touched"
|
||||||
|
class="tb-error">
|
||||||
|
warning
|
||||||
|
</mat-icon>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tb-form-panel" formGroupName="qrCodeConfig">
|
||||||
|
<div class="tb-form-panel stroked no-padding no-gap">
|
||||||
|
<div class="tb-form-row space-between no-border no-padding-bottom column-xs">
|
||||||
|
<mat-slide-toggle class="mat-slide tb-fixed-width" formControlName="badgeEnabled"
|
||||||
|
(click)="$event.stopPropagation()">
|
||||||
|
{{ 'admin.mobile-app.badges' | translate }}
|
||||||
|
</mat-slide-toggle>
|
||||||
|
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<mat-select formControlName="badgeStyle" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<mat-option *ngFor="let badgeStyle of badgeStyleTranslationsMap | keyvalue" [value]="badgeStyle.key">
|
||||||
|
{{ badgeStyle.value | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<mat-select formControlName="badgePosition" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<mat-option *ngFor="let badgePosition of badgePositionTranslationsMap | keyvalue" [value]="badgePosition.key">
|
||||||
|
{{ badgePosition.value | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tb-form-panel stroked no-padding no-gap">
|
||||||
|
<div class="tb-form-row space-between no-border no-padding-bottom column-xs">
|
||||||
|
<mat-slide-toggle class="mat-slide tb-fixed-width" formControlName="qrCodeLabelEnabled" (click)="$event.stopPropagation()">
|
||||||
|
{{ 'admin.mobile-app.label' | translate }}
|
||||||
|
</mat-slide-toggle>
|
||||||
|
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<input matInput formControlName="qrCodeLabel" maxlength="50" placeholder="{{'admin.mobile-app.set' | translate}}">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2024 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.tb-fixed-width {
|
||||||
|
min-width: 230px;
|
||||||
|
}
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2024 The Thingsboard Authors
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
|
||||||
|
import { Component } from "@angular/core";
|
||||||
|
import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
|
||||||
|
import { WidgetSettings, WidgetSettingsComponent } from "@shared/models/widget.models";
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
import { Store } from "@ngrx/store";
|
||||||
|
import { badgePositionTranslationsMap, badgeStyleTranslationsMap } from '@shared/models/mobile-app.models';
|
||||||
|
import { mobileAppQrCodeWidgetDefaultSettings } from '@home/components/widget/lib/cards/mobile-app-qr-code-widge.models';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-mobile-app-qr-code-widget-settings',
|
||||||
|
templateUrl: './mobile-app-qr-code-widget-settings.component.html',
|
||||||
|
styleUrls: ['/mobile-app-qr-code-widget-settings.component.scss', './../widget-settings.scss']
|
||||||
|
})
|
||||||
|
export class MobileAppQrCodeWidgetSettingsComponent extends WidgetSettingsComponent {
|
||||||
|
|
||||||
|
mobileAppQRCodeWidgetSettingsForm: UntypedFormGroup;
|
||||||
|
|
||||||
|
badgePositionTranslationsMap = badgePositionTranslationsMap;
|
||||||
|
badgeStyleTranslationsMap = badgeStyleTranslationsMap;
|
||||||
|
|
||||||
|
constructor(protected store: Store<AppState>,
|
||||||
|
private fb: UntypedFormBuilder) {
|
||||||
|
super(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected settingsForm(): UntypedFormGroup {
|
||||||
|
return this.mobileAppQRCodeWidgetSettingsForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected defaultSettings(): WidgetSettings {
|
||||||
|
return {...mobileAppQrCodeWidgetDefaultSettings};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onSettingsSet(settings: WidgetSettings) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm = this.fb.group({
|
||||||
|
useDefaultApp: [settings.useDefaultApp, []],
|
||||||
|
androidConfig: this.fb.group({
|
||||||
|
enabled: [settings.androidConfig.enabled, []],
|
||||||
|
appPackage: [settings.androidConfig.appPackage, []],
|
||||||
|
sha256CertFingerprints: [settings.androidConfig.sha256CertFingerprints, []]
|
||||||
|
}),
|
||||||
|
iosConfig: this.fb.group({
|
||||||
|
enabled: [settings.iosConfig.enabled, []],
|
||||||
|
appId: [settings.iosConfig.appId, []]
|
||||||
|
}),
|
||||||
|
qrCodeConfig: this.fb.group({
|
||||||
|
badgeEnabled: [settings.qrCodeConfig.badgeEnabled, []],
|
||||||
|
badgeStyle: [{value: settings.qrCodeConfig.badgeStyle, disabled: true}, []],
|
||||||
|
badgePosition: [{value: settings.qrCodeConfig.badgePosition, disabled: true}, []],
|
||||||
|
qrCodeLabelEnabled: [settings.qrCodeConfig.qrCodeLabelEnabled, []],
|
||||||
|
qrCodeLabel: [settings.qrCodeConfig.qrCodeLabel, []]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected validatorTriggers(): string[] {
|
||||||
|
return ['useDefaultApp', 'androidConfig.enabled', 'iosConfig.enabled', 'qrCodeConfig.badgeEnabled', 'qrCodeConfig.qrCodeLabelEnabled'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updateValidators(emitEvent: boolean) {
|
||||||
|
const useDefaultApp = this.mobileAppQRCodeWidgetSettingsForm.get('useDefaultApp').value;
|
||||||
|
const androidEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.enabled').value;
|
||||||
|
const iosEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.enabled').value;
|
||||||
|
const badgeEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeEnabled').value;
|
||||||
|
const qrCodeLabelEnabled = this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabelEnabled').value;
|
||||||
|
|
||||||
|
if (useDefaultApp) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').clearValidators();
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').clearValidators();
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').clearValidators();
|
||||||
|
} else {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').setValidators([Validators.required]);
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').setValidators([Validators.required]);
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').setValidators([Validators.required]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (androidEnabled) {
|
||||||
|
if (!useDefaultApp) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').setValidators([Validators.required]);
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').setValidators([Validators.required]);
|
||||||
|
}
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeEnabled').enable({emitEvent: false});
|
||||||
|
if (badgeEnabled) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeStyle').enable();
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgePosition').enable();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!useDefaultApp) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').clearValidators();
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').clearValidators();
|
||||||
|
}
|
||||||
|
if (!iosEnabled) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeEnabled').disable({emitEvent: false});
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeStyle').disable();
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgePosition').disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iosEnabled) {
|
||||||
|
if (!useDefaultApp) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').setValidators([Validators.required]);
|
||||||
|
}
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeEnabled').enable({emitEvent: false});
|
||||||
|
if (badgeEnabled) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeStyle').enable();
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgePosition').enable();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!useDefaultApp) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').clearValidators();
|
||||||
|
}
|
||||||
|
if (!androidEnabled) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeEnabled').disable({emitEvent: false});
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeStyle').disable();
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgePosition').disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badgeEnabled) {
|
||||||
|
if (androidEnabled || iosEnabled) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeStyle').enable();
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgePosition').enable();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgeStyle').disable();
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.badgePosition').disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qrCodeLabelEnabled) {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabel').enable();
|
||||||
|
} else {
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('qrCodeConfig.qrCodeLabel').disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.appPackage').updateValueAndValidity({emitEvent});
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('androidConfig.sha256CertFingerprints').updateValueAndValidity({emitEvent});
|
||||||
|
this.mobileAppQRCodeWidgetSettingsForm.get('iosConfig.appId').updateValueAndValidity({emitEvent});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -354,10 +354,14 @@ import {
|
|||||||
import {
|
import {
|
||||||
RadarChartWidgetSettingsComponent
|
RadarChartWidgetSettingsComponent
|
||||||
} from '@home/components/widget/lib/settings/chart/radar-chart-widget-settings.component';
|
} from '@home/components/widget/lib/settings/chart/radar-chart-widget-settings.component';
|
||||||
|
import {
|
||||||
|
MobileAppQrCodeWidgetSettingsComponent
|
||||||
|
} from '@home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
QrCodeWidgetSettingsComponent,
|
QrCodeWidgetSettingsComponent,
|
||||||
|
MobileAppQrCodeWidgetSettingsComponent,
|
||||||
TimeseriesTableWidgetSettingsComponent,
|
TimeseriesTableWidgetSettingsComponent,
|
||||||
TimeseriesTableKeySettingsComponent,
|
TimeseriesTableKeySettingsComponent,
|
||||||
TimeseriesTableLatestKeySettingsComponent,
|
TimeseriesTableLatestKeySettingsComponent,
|
||||||
@ -490,6 +494,7 @@ import {
|
|||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
QrCodeWidgetSettingsComponent,
|
QrCodeWidgetSettingsComponent,
|
||||||
|
MobileAppQrCodeWidgetSettingsComponent,
|
||||||
TimeseriesTableWidgetSettingsComponent,
|
TimeseriesTableWidgetSettingsComponent,
|
||||||
TimeseriesTableKeySettingsComponent,
|
TimeseriesTableKeySettingsComponent,
|
||||||
TimeseriesTableLatestKeySettingsComponent,
|
TimeseriesTableLatestKeySettingsComponent,
|
||||||
@ -620,6 +625,7 @@ export class WidgetSettingsModule {
|
|||||||
|
|
||||||
export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsComponent>} = {
|
export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsComponent>} = {
|
||||||
'tb-qrcode-widget-settings': QrCodeWidgetSettingsComponent,
|
'tb-qrcode-widget-settings': QrCodeWidgetSettingsComponent,
|
||||||
|
'tb-mobile-app-qr-code-widget-settings': MobileAppQrCodeWidgetSettingsComponent,
|
||||||
'tb-timeseries-table-widget-settings': TimeseriesTableWidgetSettingsComponent,
|
'tb-timeseries-table-widget-settings': TimeseriesTableWidgetSettingsComponent,
|
||||||
'tb-timeseries-table-key-settings': TimeseriesTableKeySettingsComponent,
|
'tb-timeseries-table-key-settings': TimeseriesTableKeySettingsComponent,
|
||||||
'tb-timeseries-table-latest-key-settings': TimeseriesTableLatestKeySettingsComponent,
|
'tb-timeseries-table-latest-key-settings': TimeseriesTableLatestKeySettingsComponent,
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import {
|
|||||||
badgePositionTranslationsMap,
|
badgePositionTranslationsMap,
|
||||||
BadgeStyle,
|
BadgeStyle,
|
||||||
badgeStyleTranslationsMap,
|
badgeStyleTranslationsMap,
|
||||||
MobileAppSettings
|
MobileAppQRCodeSettings
|
||||||
} from '@shared/models/mobile-app.models';
|
} from '@shared/models/mobile-app.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -39,7 +39,7 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf
|
|||||||
|
|
||||||
mobileAppSettingsForm: FormGroup;
|
mobileAppSettingsForm: FormGroup;
|
||||||
|
|
||||||
mobileAppSettings: MobileAppSettings;
|
mobileAppSettings: MobileAppQRCodeSettings;
|
||||||
|
|
||||||
private readonly destroy$ = new Subject<void>();
|
private readonly destroy$ = new Subject<void>();
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private processMobileAppSettings(mobileAppSettings: MobileAppSettings): void {
|
private processMobileAppSettings(mobileAppSettings: MobileAppQRCodeSettings): void {
|
||||||
this.mobileAppSettings = {...mobileAppSettings};
|
this.mobileAppSettings = {...mobileAppSettings};
|
||||||
this.mobileAppSettingsForm.reset(this.mobileAppSettings);
|
this.mobileAppSettingsForm.reset(this.mobileAppSettings);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
import { TenantId } from '@shared/models/id/tenant-id';
|
import { TenantId } from '@shared/models/id/tenant-id';
|
||||||
|
|
||||||
export interface MobileAppSettings {
|
export interface MobileAppQRCodeSettings {
|
||||||
tenantId: TenantId;
|
tenantId: TenantId;
|
||||||
useDefaultApp: boolean;
|
useDefaultApp: boolean;
|
||||||
androidConfig: AndroidConfig;
|
androidConfig: AndroidConfig;
|
||||||
|
|||||||
@ -1145,7 +1145,7 @@
|
|||||||
"id": "8e71a398-caf5-540d-cec5-6e5dc264343e"
|
"id": "8e71a398-caf5-540d-cec5-6e5dc264343e"
|
||||||
},
|
},
|
||||||
"b9d704a2-f579-dbff-f123-f953d92081fd": {
|
"b9d704a2-f579-dbff-f123-f953d92081fd": {
|
||||||
"typeFullFqn": "system.home_page_widgets.mobile_app_qr_code",
|
"typeFullFqn": "system.home_page_widgets.home_mobile_app_qr_code",
|
||||||
"type": "static",
|
"type": "static",
|
||||||
"sizeX": 6,
|
"sizeX": 6,
|
||||||
"sizeY": 3,
|
"sizeY": 3,
|
||||||
@ -1176,12 +1176,10 @@
|
|||||||
"backgroundColor": "rgb(255, 255, 255)",
|
"backgroundColor": "rgb(255, 255, 255)",
|
||||||
"color": "rgba(0, 0, 0, 0.87)",
|
"color": "rgba(0, 0, 0, 0.87)",
|
||||||
"padding": "8px",
|
"padding": "8px",
|
||||||
"settings": {
|
"settings": {},
|
||||||
"cardHtml": "<div class='card'>HTML code here</div>",
|
"title": "Mobile app QR code",
|
||||||
"cardCss": ".card {\n font-weight: bold;\n font-size: 32px;\n color: #999;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}"
|
"dropShadow": false,
|
||||||
},
|
"enableFullscreen": false
|
||||||
"title": "HTML Card",
|
|
||||||
"dropShadow": false
|
|
||||||
},
|
},
|
||||||
"row": 0,
|
"row": 0,
|
||||||
"col": 0,
|
"col": 0,
|
||||||
|
|||||||
@ -290,9 +290,6 @@
|
|||||||
&.shrink {
|
&.shrink {
|
||||||
flex: 0;
|
flex: 0;
|
||||||
}
|
}
|
||||||
&.no-gap {
|
|
||||||
gap: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tb-form-panel, .tb-form-row {
|
.tb-form-panel, .tb-form-row {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user