diff --git a/application/src/main/data/json/system/widget_bundles/cards.json b/application/src/main/data/json/system/widget_bundles/cards.json index 39996839f1..5a839d4c82 100644 --- a/application/src/main/data/json/system/widget_bundles/cards.json +++ b/application/src/main/data/json/system/widget_bundles/cards.json @@ -17,6 +17,7 @@ "cards.label_widget", "cards.dashboard_state_widget", "cards.qr_code", + "cards.mobile_app_qr_code", "cards.attributes_card", "cards.html_card", "cards.html_value_card", diff --git a/application/src/main/data/json/system/widget_bundles/home_page_widgets.json b/application/src/main/data/json/system/widget_bundles/home_page_widgets.json index 5465f750e5..0af30e4df2 100644 --- a/application/src/main/data/json/system/widget_bundles/home_page_widgets.json +++ b/application/src/main/data/json/system/widget_bundles/home_page_widgets.json @@ -14,6 +14,6 @@ "home_page_widgets.documentation_links", "home_page_widgets.dashboards", "home_page_widgets.usage_info", - "home_page_widgets.mobile_app_qr_code" + "home_page_widgets.home_mobile_app_qr_code" ] } \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/home_mobile_app_qr_code.json b/application/src/main/data/json/system/widget_types/home_mobile_app_qr_code.json new file mode 100644 index 0000000000..88109fc902 --- /dev/null +++ b/application/src/main/data/json/system/widget_types/home_mobile_app_qr_code.json @@ -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": "\n", + "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\":\"
HTML code here
\",\"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 +} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/mobile_app_qr_code.json b/application/src/main/data/json/system/widget_types/mobile_app_qr_code.json index 2e3600d05b..82ce9025ed 100644 --- a/application/src/main/data/json/system/widget_types/mobile_app_qr_code.json +++ b/application/src/main/data/json/system/widget_types/mobile_app_qr_code.json @@ -1,21 +1,21 @@ { - "fqn": "home_page_widgets.mobile_app_qr_code", + "fqn": "cards.mobile_app_qr_code", "name": "Mobile app QR code", "deprecated": false, "image": null, "description": null, "descriptor": { "type": "static", - "sizeX": 6, + "sizeX": 7.5, "sizeY": 3, "resources": [], "templateHtml": "\n", "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": "", "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\":\"
HTML code here
\",\"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}" + "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\":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 } \ No newline at end of file diff --git a/ui-ngx/src/app/core/http/mobile-app.service.ts b/ui-ngx/src/app/core/http/mobile-app.service.ts index 75d5f337bc..bb4dc6c863 100644 --- a/ui-ngx/src/app/core/http/mobile-app.service.ts +++ b/ui-ngx/src/app/core/http/mobile-app.service.ts @@ -18,7 +18,7 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils'; import { Observable } from 'rxjs'; -import { MobileAppSettings } from '@shared/models/mobile-app.models'; +import { MobileAppQRCodeSettings } from '@shared/models/mobile-app.models'; @Injectable({ providedIn: 'root' @@ -30,12 +30,12 @@ export class MobileAppService { ) { } - public getMobileAppSettings(config?: RequestConfig): Observable { - return this.http.get(`/api/mobile/app/settings`, defaultHttpOptionsFromConfig(config)); + public getMobileAppSettings(config?: RequestConfig): Observable { + return this.http.get(`/api/mobile/app/settings`, defaultHttpOptionsFromConfig(config)); } - public saveMobileAppSettings(mobileAppSettings: MobileAppSettings, config?: RequestConfig): Observable { - return this.http.post(`/api/mobile/app/settings`, mobileAppSettings, defaultHttpOptionsFromConfig(config)); + public saveMobileAppSettings(mobileAppSettings: MobileAppQRCodeSettings, config?: RequestConfig): Observable { + return this.http.post(`/api/mobile/app/settings`, mobileAppSettings, defaultHttpOptionsFromConfig(config)); } public getMobileAppDeepLink( config?: RequestConfig): Observable { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/mobile-app-qr-code-widge.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/mobile-app-qr-code-widge.models.ts new file mode 100644 index 0000000000..4027e0445b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/mobile-app-qr-code-widge.models.ts @@ -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; +} + +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' + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.html index 53f95cb57e..e3f9ca11c3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.html @@ -15,15 +15,15 @@ limitations under the License. --> -
admin.mobile-app.connect-mobile-app
+
admin.mobile-app.connect-mobile-app
-
+ [class.tb-badge-container]="!previewMode && !ctx"> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.scss index 1d088ec482..5dafcc7521 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.scss @@ -17,7 +17,6 @@ @import '../../../../../../scss/constants'; :host { - width: 100%; height: 100%; display: flex; flex-direction: column; @@ -25,12 +24,14 @@ } .tb-title { + padding-bottom: 12px; align-self: start; font-weight: 600; font-size: 20px; line-height: 24px; letter-spacing: 0.1px; color: rgba(0, 0, 0, 0.76); + @media #{$mat-md-lg} { font-weight: 500; font-size: 14px; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts index c9c8541613..7296b47f80 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts @@ -18,13 +18,14 @@ import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, Input, OnDestr import { PageComponent } from '@shared/components/page.component'; import { AppState } from '@core/core.state'; 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 { WidgetContext } from '@home/models/widget-component.models'; import { UtilsService } from '@core/services/utils.service'; import { interval, mergeMap, Observable, Subject, takeUntil } from 'rxjs'; import { MINUTE } from '@shared/models/time/time.models'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { MobileAppQrCodeWidgetSettings } from '@home/components/widget/lib/cards/mobile-app-qr-code-widge.models'; @Component({ selector: 'tb-mobile-app-qrcode-widget', @@ -41,7 +42,7 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI previewMode: boolean; @Input() - set mobileAppSettings(settings: MobileAppSettings) { + set mobileAppSettings(settings: MobileAppQRCodeSettings | MobileAppQrCodeWidgetSettings) { if (settings) { this.mobileAppSettingsValue = settings; } @@ -59,7 +60,7 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI badgePosition = BadgePosition; badgeStyleURLMap = badgeStyleURLMap; - private mobileAppSettingsValue: MobileAppSettings; + private mobileAppSettingsValue: MobileAppQRCodeSettings | MobileAppQrCodeWidgetSettings; private deepLinkTTL: number; constructor(protected store: Store, @@ -71,9 +72,8 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI ngOnInit(): void { if (this.ctx) { - this.ctx.$scope.mobileAppQrcodeWidget = this; - } - if (!this.mobileAppSettings) { + this.mobileAppSettings = this.ctx.settings; + } else { this.mobileAppService.getMobileAppSettings().subscribe((settings => { this.mobileAppSettings = settings; this.cd.detectChanges(); @@ -104,7 +104,7 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI updateQRCode(link: string) { import('qrcode').then((QRCode) => { - QRCode.toCanvas(this.canvasRef.nativeElement, link, { width: 125}); + QRCode.toCanvas(this.canvasRef.nativeElement, link, { width: 90 }); }); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.html new file mode 100644 index 0000000000..cdef956141 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.html @@ -0,0 +1,130 @@ + +
+
+
+
admin.mobile-app.applications
+ + {{ 'admin.mobile-app.default' | translate }} + {{ 'admin.mobile-app.custom' | translate }} + +
+
+
+ + {{ 'admin.mobile-app.android' | translate }} + +
+
+
+
{{ 'admin.mobile-app.app-package-name' | translate }}
+ + + + warning + + +
+
+
+
+
{{ 'admin.mobile-app.sha256-certificate-fingerprints' | translate }}
+ + + + warning + + +
+
+
+
+
+ + {{ 'admin.mobile-app.ios' | translate }} + +
+
+
+
{{ 'admin.mobile-app.app-id' | translate }}
+ + + + warning + + +
+
+
+
+
+
+
+ + {{ 'admin.mobile-app.badges' | translate }} + + + + + {{ badgeStyle.value | translate }} + + + + + + + {{ badgePosition.value | translate }} + + + +
+
+
+
+ + {{ 'admin.mobile-app.label' | translate }} + + + + +
+
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.scss new file mode 100644 index 0000000000..d0a2c9ac16 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.scss @@ -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; +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.ts new file mode 100644 index 0000000000..61999d7d41 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/mobile-app-qr-code-widget-settings.component.ts @@ -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, + 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}); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts index c71f0fd658..f093c4c568 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts @@ -354,10 +354,14 @@ import { import { RadarChartWidgetSettingsComponent } 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({ declarations: [ QrCodeWidgetSettingsComponent, + MobileAppQrCodeWidgetSettingsComponent, TimeseriesTableWidgetSettingsComponent, TimeseriesTableKeySettingsComponent, TimeseriesTableLatestKeySettingsComponent, @@ -490,6 +494,7 @@ import { ], exports: [ QrCodeWidgetSettingsComponent, + MobileAppQrCodeWidgetSettingsComponent, TimeseriesTableWidgetSettingsComponent, TimeseriesTableKeySettingsComponent, TimeseriesTableLatestKeySettingsComponent, @@ -620,6 +625,7 @@ export class WidgetSettingsModule { export const widgetSettingsComponentsMap: {[key: string]: Type} = { 'tb-qrcode-widget-settings': QrCodeWidgetSettingsComponent, + 'tb-mobile-app-qr-code-widget-settings': MobileAppQrCodeWidgetSettingsComponent, 'tb-timeseries-table-widget-settings': TimeseriesTableWidgetSettingsComponent, 'tb-timeseries-table-key-settings': TimeseriesTableKeySettingsComponent, 'tb-timeseries-table-latest-key-settings': TimeseriesTableLatestKeySettingsComponent, diff --git a/ui-ngx/src/app/modules/home/pages/admin/mobile-app-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/mobile-app-settings.component.ts index c342b68d1f..aa2aca3cb9 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/mobile-app-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/mobile-app-settings.component.ts @@ -27,7 +27,7 @@ import { badgePositionTranslationsMap, BadgeStyle, badgeStyleTranslationsMap, - MobileAppSettings + MobileAppQRCodeSettings } from '@shared/models/mobile-app.models'; @Component({ @@ -39,7 +39,7 @@ export class MobileAppSettingsComponent extends PageComponent implements HasConf mobileAppSettingsForm: FormGroup; - mobileAppSettings: MobileAppSettings; + mobileAppSettings: MobileAppQRCodeSettings; private readonly destroy$ = new Subject(); @@ -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.mobileAppSettingsForm.reset(this.mobileAppSettings); } diff --git a/ui-ngx/src/app/shared/models/mobile-app.models.ts b/ui-ngx/src/app/shared/models/mobile-app.models.ts index 0787f17747..02139bd913 100644 --- a/ui-ngx/src/app/shared/models/mobile-app.models.ts +++ b/ui-ngx/src/app/shared/models/mobile-app.models.ts @@ -16,7 +16,7 @@ import { TenantId } from '@shared/models/id/tenant-id'; -export interface MobileAppSettings { +export interface MobileAppQRCodeSettings { tenantId: TenantId; useDefaultApp: boolean; androidConfig: AndroidConfig; diff --git a/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json b/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json index d850e640b7..e69b43b1fe 100644 --- a/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json +++ b/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json @@ -1145,7 +1145,7 @@ "id": "8e71a398-caf5-540d-cec5-6e5dc264343e" }, "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", "sizeX": 6, "sizeY": 3, @@ -1176,12 +1176,10 @@ "backgroundColor": "rgb(255, 255, 255)", "color": "rgba(0, 0, 0, 0.87)", "padding": "8px", - "settings": { - "cardHtml": "
HTML code here
", - "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": false + "settings": {}, + "title": "Mobile app QR code", + "dropShadow": false, + "enableFullscreen": false }, "row": 0, "col": 0, diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index a692994144..fa1eab0ece 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -290,9 +290,6 @@ &.shrink { flex: 0; } - &.no-gap { - gap: 0; - } } .tb-form-panel, .tb-form-row {