/// /// 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 { HasTenantId } from '@shared/models/entity.models'; import { BaseData } from '@shared/models/base-data'; import { MobileAppId } from '@shared/models/id/mobile-app-id'; import { OAuth2ClientInfo, PlatformType } from '@shared/models/oauth2.models'; import { MobileAppBundleId } from '@shared/models/id/mobile-app-bundle-id'; import { deepClone, isNotEmptyStr } from '@core/utils'; export interface QrCodeSettings extends HasTenantId { useDefaultApp: boolean; mobileAppBundleId: MobileAppBundleId androidConfig: AndroidConfig; //TODO: need remove iosConfig: IosConfig; //TODO: need remove qrCodeConfig: QRCodeConfig; defaultGooglePlayLink: string; defaultAppStoreLink: string; id: { id: string; } } export interface AndroidConfig { enabled: boolean; appPackage: string; sha256CertFingerprints: string; storeLink: string; } export interface IosConfig { enabled: boolean; appId: string; storeLink: string; } export interface QRCodeConfig { showOnHomePage: boolean; badgeEnabled: boolean; badgePosition: BadgePosition; qrCodeLabelEnabled: boolean; qrCodeLabel: string; } export interface MobileOSBadgeURL { iOS: string; android: string; } export enum BadgePosition { RIGHT = 'RIGHT', LEFT = 'LEFT' } export const badgePositionTranslationsMap = new Map([ [BadgePosition.RIGHT, 'admin.mobile-app.right'], [BadgePosition.LEFT, 'admin.mobile-app.left'] ]); export type QrCodeConfig = AndroidConfig & IosConfig; export enum MobileAppStatus { DRAFT = 'DRAFT', PUBLISHED = 'PUBLISHED', DEPRECATED = 'DEPRECATED', SUSPENDED = 'SUSPENDED' } export const mobileAppStatusTranslations = new Map( [ [MobileAppStatus.DRAFT, 'mobile.status-type.draft'], [MobileAppStatus.PUBLISHED, 'mobile.status-type.published'], [MobileAppStatus.DEPRECATED, 'mobile.status-type.deprecated'], [MobileAppStatus.SUSPENDED, 'mobile.status-type.suspended'], ] ); export interface VersionInfo { minVersion: string; minVersionReleaseNotes?: string; latestVersion: string; latestVersionReleaseNotes?: string; } export interface StoreInfo { sha256CertFingerprints?: string; storeLink: string; appId?: string; } export interface MobileApp extends BaseData, HasTenantId { pkgName: string; appSecret: string; platformType: PlatformType; status: MobileAppStatus; versionInfo: VersionInfo; storeInfo: StoreInfo; } enum MobileMenuPath { HOME = 'HOME', ASSETS = 'ASSETS', DEVICES = 'DEVICES', DEVICE_LIST = 'DEVICE_LIST', ALARMS = 'ALARMS', DASHBOARDS = 'DASHBOARDS', DASHBOARD = 'DASHBOARD', AUDIT_LOGS = 'AUDIT_LOGS', CUSTOMERS = 'CUSTOMERS', NOTIFICATIONS = 'NOTIFICATIONS' } export enum MobilePageType { DEFAULT = 'DEFAULT', CUSTOM = 'CUSTOM', DASHBOARD = 'DASHBOARD', WEB_VIEW = 'WEB_VIEW', } export const mobilePageTypeTranslations = new Map( [ [MobilePageType.CUSTOM, 'mobile.pages-types.custom'], [MobilePageType.DASHBOARD, 'mobile.pages-types.dashboard'], [MobilePageType.WEB_VIEW, 'mobile.pages-types.web-view'], ] ); export interface MobilePage { label?: string; icon?: string; type: MobilePageType; visible: boolean; } export interface DefaultMobilePage extends MobilePage { id: MobileMenuPath; } export interface CustomMobilePage extends MobilePage { dashboardId?: string; url?: string; path?: string; } export interface MobileLayoutConfig { pages: MobilePage[]; } export interface MobileAppBundle extends Omit, 'label'>, HasTenantId { title?: string; description?: string; androidAppId?: MobileAppId; iosAppId?: MobileAppId; layoutConfig?: MobileLayoutConfig; oauth2Enabled: boolean; } export interface MobileAppBundleInfo extends MobileAppBundle { androidPkgName: string; iosPkgName: string; androidPkg?: { name: string; id: MobileAppId }; iosPkg?: { name: string; id: MobileAppId } oauth2ClientInfos?: Array; qrCodeEnabled: boolean; } const defaultMobileMenu = [ MobileMenuPath.HOME, MobileMenuPath.ALARMS, MobileMenuPath.DEVICES, MobileMenuPath.CUSTOMERS, MobileMenuPath.ASSETS, MobileMenuPath.AUDIT_LOGS, MobileMenuPath.NOTIFICATIONS, MobileMenuPath.DEVICE_LIST, MobileMenuPath.DASHBOARDS ]; export const hideDefaultMenuItems = [ MobileMenuPath.DEVICE_LIST, MobileMenuPath.DASHBOARDS ]; export const getDefaultMobileMenuItem = (): DefaultMobilePage[] => { return deepClone(defaultMobileMenu).map(item => ({ visible: !hideDefaultMenuItems.includes(item), type: MobilePageType.DEFAULT, id: item })) } export const isDefaultMobileMenuItem = (item: MobilePage): item is DefaultMobilePage => { const path = (item as DefaultMobilePage).id; return isNotEmptyStr(path) && defaultMobilePageMap.has(path); }; const mobilePageEqualToDefault = (item: MobilePage, defaultMobilePage: DefaultMobilePage): boolean => { if (isDefaultMobileMenuItem(item) && (hideDefaultMenuItems.includes(item.id) ? !item.visible : item.visible)) { return !(item.id !== defaultMobilePage.id || !!item.label || !!item.icon); } else { return false; } }; export const isDefaultMobilePagesConfig = (items: MobilePage[]): boolean => { const defaultMenus = getDefaultMobileMenuItem(); if (!items?.length && !defaultMenus?.length) { return true; } else if (items.length !== defaultMenus.length) { return false; } else { for (let i = 0; i < items.length; i++) { const item = items[i]; const defaultMenuItem = defaultMenus[i]; if (!mobilePageEqualToDefault(item, defaultMenuItem)) { return false; } } return true; } }; export const mobileMenuDividers = new Map([ [2, 'mobile.mobile-599'], [4, 'mobile.tablet-959'], [6, 'mobile.max-element-number'], ]); export const defaultMobilePageMap = new Map>([ [ MobileMenuPath.HOME, { id: MobileMenuPath.HOME, icon: 'home', label: 'Home' } ], [ MobileMenuPath.ALARMS, { id: MobileMenuPath.ALARMS, icon: 'notifications', label: 'Alarms' } ], [ MobileMenuPath.DEVICES, { id: MobileMenuPath.DEVICES, icon: 'devices_other', label: 'Devices' } ], [ MobileMenuPath.CUSTOMERS, { id: MobileMenuPath.CUSTOMERS, icon: 'supervisor_account', label: 'Customers' } ], [ MobileMenuPath.ASSETS, { id: MobileMenuPath.ASSETS, icon: 'domain', label: 'Assets' } ], [ MobileMenuPath.DEVICE_LIST, { id: MobileMenuPath.DEVICE_LIST, icon: 'devices', label: 'Device list' } ], [ MobileMenuPath.DASHBOARDS, { id: MobileMenuPath.DASHBOARDS, icon: 'dashboard', label: 'Dashboards' } ], [ MobileMenuPath.AUDIT_LOGS, { id: MobileMenuPath.AUDIT_LOGS, icon: 'track_changes', label: 'Audit logs' } ], [ MobileMenuPath.NOTIFICATIONS, { id: MobileMenuPath.NOTIFICATIONS, icon: 'notifications_active', label: 'Notification' } ] ])