Commit 868234f13df958000e7d72a294f6ab6c613c9b5c

Authored by Igor Kulikov
1 parent fce3bdce

Tenant, device profiles UI

... ... @@ -20,7 +20,7 @@ import { Observable } from 'rxjs';
20 20 import { HttpClient } from '@angular/common/http';
21 21 import { PageLink } from '@shared/models/page/page-link';
22 22 import { PageData } from '@shared/models/page/page-data';
23   -import { Tenant } from '@shared/models/tenant.model';
  23 +import { Tenant, TenantInfo } from '@shared/models/tenant.model';
24 24
25 25 @Injectable({
26 26 providedIn: 'root'
... ... @@ -35,10 +35,18 @@ export class TenantService {
35 35 return this.http.get<PageData<Tenant>>(`/api/tenants${pageLink.toQuery()}`, defaultHttpOptionsFromConfig(config));
36 36 }
37 37
  38 + public getTenantInfos(pageLink: PageLink, config?: RequestConfig): Observable<PageData<TenantInfo>> {
  39 + return this.http.get<PageData<TenantInfo>>(`/api/tenantInfos${pageLink.toQuery()}`, defaultHttpOptionsFromConfig(config));
  40 + }
  41 +
38 42 public getTenant(tenantId: string, config?: RequestConfig): Observable<Tenant> {
39 43 return this.http.get<Tenant>(`/api/tenant/${tenantId}`, defaultHttpOptionsFromConfig(config));
40 44 }
41 45
  46 + public getTenantInfo(tenantId: string, config?: RequestConfig): Observable<TenantInfo> {
  47 + return this.http.get<TenantInfo>(`/api/tenant/info/${tenantId}`, defaultHttpOptionsFromConfig(config));
  48 + }
  49 +
42 50 public saveTenant(tenant: Tenant, config?: RequestConfig): Observable<Tenant> {
43 51 return this.http.post<Tenant>('/api/tenant', tenant, defaultHttpOptionsFromConfig(config));
44 52 }
... ...
... ... @@ -70,8 +70,10 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
70 70 return this.fb.group(
71 71 {
72 72 name: [entity ? entity.name : '', [Validators.required]],
  73 + deviceProfileId: [entity ? entity.deviceProfileId : null, [Validators.required]],
73 74 type: [entity ? entity.type : null, [Validators.required]],
74 75 label: [entity ? entity.label : ''],
  76 + deviceData: [entity ? entity.deviceData : null, [Validators.required]],
75 77 additionalInfo: this.fb.group(
76 78 {
77 79 gateway: [entity && entity.additionalInfo ? entity.additionalInfo.gateway : false],
... ... @@ -84,8 +86,10 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
84 86
85 87 updateForm(entity: DeviceInfo) {
86 88 this.entityForm.patchValue({name: entity.name});
  89 + this.entityForm.patchValue({deviceProfileId: entity.deviceProfileId});
87 90 this.entityForm.patchValue({type: entity.type});
88 91 this.entityForm.patchValue({label: entity.label});
  92 + this.entityForm.patchValue({deviceData: entity.deviceData});
89 93 this.entityForm.patchValue({additionalInfo:
90 94 {gateway: entity.additionalInfo ? entity.additionalInfo.gateway : false}});
91 95 this.entityForm.patchValue({additionalInfo: {description: entity.additionalInfo ? entity.additionalInfo.description : ''}});
... ...
... ... @@ -150,13 +150,14 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
150 150 configureColumns(deviceScope: string): Array<EntityTableColumn<DeviceInfo>> {
151 151 const columns: Array<EntityTableColumn<DeviceInfo>> = [
152 152 new DateEntityTableColumn<DeviceInfo>('createdTime', 'common.created-time', this.datePipe, '150px'),
153   - new EntityTableColumn<DeviceInfo>('name', 'device.name', '25%'),
154   - new EntityTableColumn<DeviceInfo>('type', 'device.device-type', '25%'),
155   - new EntityTableColumn<DeviceInfo>('label', 'device.label', '25%')
  153 + new EntityTableColumn<DeviceInfo>('name', 'device.name', '20%'),
  154 + new EntityTableColumn<DeviceInfo>('deviceProfileName', 'device-profile.device-profile', '20%'),
  155 + new EntityTableColumn<DeviceInfo>('type', 'device.device-type', '20%'),
  156 + new EntityTableColumn<DeviceInfo>('label', 'device.label', '20%')
156 157 ];
157 158 if (deviceScope === 'tenant') {
158 159 columns.push(
159   - new EntityTableColumn<DeviceInfo>('customerTitle', 'customer.customer', '25%'),
  160 + new EntityTableColumn<DeviceInfo>('customerTitle', 'customer.customer', '20%'),
160 161 new EntityTableColumn<DeviceInfo>('customerIsPublic', 'device.public', '60px',
161 162 entity => {
162 163 return checkBoxCell(entity.customerIsPublic);
... ...
... ... @@ -18,14 +18,14 @@ import { Component } from '@angular/core';
18 18 import { Store } from '@ngrx/store';
19 19 import { AppState } from '@core/core.state';
20 20 import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
21   -import { Tenant } from '@shared/models/tenant.model';
  21 +import { TenantInfo } from '@shared/models/tenant.model';
22 22
23 23 @Component({
24 24 selector: 'tb-tenant-tabs',
25 25 templateUrl: './tenant-tabs.component.html',
26 26 styleUrls: []
27 27 })
28   -export class TenantTabsComponent extends EntityTabsComponent<Tenant> {
  28 +export class TenantTabsComponent extends EntityTabsComponent<TenantInfo> {
29 29
30 30 constructor(protected store: Store<AppState>) {
31 31 super(store);
... ...
... ... @@ -18,7 +18,7 @@ import { Component, Inject } from '@angular/core';
18 18 import { Store } from '@ngrx/store';
19 19 import { AppState } from '@core/core.state';
20 20 import { FormBuilder, FormGroup, Validators } from '@angular/forms';
21   -import { Tenant } from '@app/shared/models/tenant.model';
  21 +import { Tenant, TenantInfo } from '@app/shared/models/tenant.model';
22 22 import { ActionNotificationShow } from '@app/core/notification/notification.actions';
23 23 import { TranslateService } from '@ngx-translate/core';
24 24 import { ContactBasedComponent } from '../../components/entity/contact-based.component';
... ... @@ -29,12 +29,12 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod
29 29 templateUrl: './tenant.component.html',
30 30 styleUrls: ['./tenant.component.scss']
31 31 })
32   -export class TenantComponent extends ContactBasedComponent<Tenant> {
  32 +export class TenantComponent extends ContactBasedComponent<TenantInfo> {
33 33
34 34 constructor(protected store: Store<AppState>,
35 35 protected translate: TranslateService,
36   - @Inject('entity') protected entityValue: Tenant,
37   - @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<Tenant>,
  36 + @Inject('entity') protected entityValue: TenantInfo,
  37 + @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<TenantInfo>,
38 38 protected fb: FormBuilder) {
39 39 super(store, fb, entityValue, entitiesTableConfigValue);
40 40 }
... ... @@ -47,12 +47,13 @@ export class TenantComponent extends ContactBasedComponent<Tenant> {
47 47 }
48 48 }
49 49
50   - buildEntityForm(entity: Tenant): FormGroup {
  50 + buildEntityForm(entity: TenantInfo): FormGroup {
51 51 return this.fb.group(
52 52 {
53 53 title: [entity ? entity.title : '', [Validators.required]],
54   - isolatedTbCore: [entity ? entity.isolatedTbCore : false, []],
55   - isolatedTbRuleEngine: [entity ? entity.isolatedTbRuleEngine : false, []],
  54 + tenantProfileId: [entity ? entity.tenantProfileId : null, [Validators.required]],
  55 + // isolatedTbCore: [entity ? entity.isolatedTbCore : false, []],
  56 + // isolatedTbRuleEngine: [entity ? entity.isolatedTbRuleEngine : false, []],
56 57 additionalInfo: this.fb.group(
57 58 {
58 59 description: [entity && entity.additionalInfo ? entity.additionalInfo.description : '']
... ... @@ -64,8 +65,9 @@ export class TenantComponent extends ContactBasedComponent<Tenant> {
64 65
65 66 updateEntityForm(entity: Tenant) {
66 67 this.entityForm.patchValue({title: entity.title});
67   - this.entityForm.patchValue({isolatedTbCore: entity.isolatedTbCore});
68   - this.entityForm.patchValue({isolatedTbRuleEngine: entity.isolatedTbRuleEngine});
  68 + this.entityForm.patchValue({tenantProfileId: entity.tenantProfileId});
  69 + // this.entityForm.patchValue({isolatedTbCore: entity.isolatedTbCore});
  70 + // this.entityForm.patchValue({isolatedTbRuleEngine: entity.isolatedTbRuleEngine});
69 71 this.entityForm.patchValue({additionalInfo: {description: entity.additionalInfo ? entity.additionalInfo.description : ''}});
70 72 }
71 73
... ... @@ -73,10 +75,10 @@ export class TenantComponent extends ContactBasedComponent<Tenant> {
73 75 if (this.entityForm) {
74 76 if (this.isEditValue) {
75 77 this.entityForm.enable({emitEvent: false});
76   - if (!this.isAdd) {
  78 + /* if (!this.isAdd) {
77 79 this.entityForm.get('isolatedTbCore').disable({emitEvent: false});
78 80 this.entityForm.get('isolatedTbRuleEngine').disable({emitEvent: false});
79   - }
  81 + } */
80 82 } else {
81 83 this.entityForm.disable({emitEvent: false});
82 84 }
... ...
... ... @@ -18,7 +18,7 @@ import { Injectable } from '@angular/core';
18 18
19 19 import { Resolve, Router } from '@angular/router';
20 20
21   -import { Tenant } from '@shared/models/tenant.model';
  21 +import { TenantInfo } from '@shared/models/tenant.model';
22 22 import {
23 23 DateEntityTableColumn,
24 24 EntityTableColumn,
... ... @@ -31,11 +31,12 @@ import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared
31 31 import { TenantComponent } from '@modules/home/pages/tenant/tenant.component';
32 32 import { EntityAction } from '@home/models/entity/entity-component.models';
33 33 import { TenantTabsComponent } from '@home/pages/tenant/tenant-tabs.component';
  34 +import { mergeMap } from 'rxjs/operators';
34 35
35 36 @Injectable()
36   -export class TenantsTableConfigResolver implements Resolve<EntityTableConfig<Tenant>> {
  37 +export class TenantsTableConfigResolver implements Resolve<EntityTableConfig<TenantInfo>> {
37 38
38   - private readonly config: EntityTableConfig<Tenant> = new EntityTableConfig<Tenant>();
  39 + private readonly config: EntityTableConfig<TenantInfo> = new EntityTableConfig<TenantInfo>();
39 40
40 41 constructor(private tenantService: TenantService,
41 42 private translate: TranslateService,
... ... @@ -49,11 +50,12 @@ export class TenantsTableConfigResolver implements Resolve<EntityTableConfig<Ten
49 50 this.config.entityResources = entityTypeResources.get(EntityType.TENANT);
50 51
51 52 this.config.columns.push(
52   - new DateEntityTableColumn<Tenant>('createdTime', 'common.created-time', this.datePipe, '150px'),
53   - new EntityTableColumn<Tenant>('title', 'tenant.title', '25%'),
54   - new EntityTableColumn<Tenant>('email', 'contact.email', '25%'),
55   - new EntityTableColumn<Tenant>('country', 'contact.country', '25%'),
56   - new EntityTableColumn<Tenant>('city', 'contact.city', '25%')
  53 + new DateEntityTableColumn<TenantInfo>('createdTime', 'common.created-time', this.datePipe, '150px'),
  54 + new EntityTableColumn<TenantInfo>('title', 'tenant-profile.tenant-profile', '20%'),
  55 + new EntityTableColumn<TenantInfo>('tenantProfileName', 'tenant.title', '20%'),
  56 + new EntityTableColumn<TenantInfo>('email', 'contact.email', '20%'),
  57 + new EntityTableColumn<TenantInfo>('country', 'contact.country', '20%'),
  58 + new EntityTableColumn<TenantInfo>('city', 'contact.city', '20%')
57 59 );
58 60
59 61 this.config.cellActionDescriptors.push(
... ... @@ -70,27 +72,29 @@ export class TenantsTableConfigResolver implements Resolve<EntityTableConfig<Ten
70 72 this.config.deleteEntitiesTitle = count => this.translate.instant('tenant.delete-tenants-title', {count});
71 73 this.config.deleteEntitiesContent = () => this.translate.instant('tenant.delete-tenants-text');
72 74
73   - this.config.entitiesFetchFunction = pageLink => this.tenantService.getTenants(pageLink);
74   - this.config.loadEntity = id => this.tenantService.getTenant(id.id);
75   - this.config.saveEntity = tenant => this.tenantService.saveTenant(tenant);
  75 + this.config.entitiesFetchFunction = pageLink => this.tenantService.getTenantInfos(pageLink);
  76 + this.config.loadEntity = id => this.tenantService.getTenantInfo(id.id);
  77 + this.config.saveEntity = tenant => this.tenantService.saveTenant(tenant).pipe(
  78 + mergeMap((savedTenant) => this.tenantService.getTenantInfo(savedTenant.id.id))
  79 + );
76 80 this.config.deleteEntity = id => this.tenantService.deleteTenant(id.id);
77 81 this.config.onEntityAction = action => this.onTenantAction(action);
78 82 }
79 83
80   - resolve(): EntityTableConfig<Tenant> {
  84 + resolve(): EntityTableConfig<TenantInfo> {
81 85 this.config.tableTitle = this.translate.instant('tenant.tenants');
82 86
83 87 return this.config;
84 88 }
85 89
86   - manageTenantAdmins($event: Event, tenant: Tenant) {
  90 + manageTenantAdmins($event: Event, tenant: TenantInfo) {
87 91 if ($event) {
88 92 $event.stopPropagation();
89 93 }
90 94 this.router.navigateByUrl(`tenants/${tenant.id.id}/users`);
91 95 }
92 96
93   - onTenantAction(action: EntityAction<Tenant>): boolean {
  97 + onTenantAction(action: EntityAction<TenantInfo>): boolean {
94 98 switch (action.action) {
95 99 case 'manageTenantAdmins':
96 100 this.manageTenantAdmins(action.event, action.entity);
... ...
... ... @@ -107,9 +107,11 @@ export const HelpLinks = {
107 107 ruleNodeRestApiCall: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/external-nodes/#rest-api-call-node',
108 108 ruleNodeSendEmail: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/external-nodes/#send-email-node',
109 109 tenants: helpBaseUrl + '/docs/user-guide/ui/tenants',
  110 + tenantProfiles: helpBaseUrl + '/docs/user-guide/ui/tenant-profiles',
110 111 customers: helpBaseUrl + '/docs/user-guide/ui/customers',
111 112 users: helpBaseUrl + '/docs/user-guide/ui/users',
112 113 devices: helpBaseUrl + '/docs/user-guide/ui/devices',
  114 + deviceProfiles: helpBaseUrl + '/docs/user-guide/ui/device-profiles',
113 115 assets: helpBaseUrl + '/docs/user-guide/ui/assets',
114 116 entityViews: helpBaseUrl + '/docs/user-guide/ui/entity-views',
115 117 entitiesImport: helpBaseUrl + '/docs/user-guide/bulk-provisioning',
... ...
... ... @@ -20,6 +20,62 @@ import { TenantId } from '@shared/models/id/tenant-id';
20 20 import { CustomerId } from '@shared/models/id/customer-id';
21 21 import { DeviceCredentialsId } from '@shared/models/id/device-credentials-id';
22 22 import { EntitySearchQuery } from '@shared/models/relation.models';
  23 +import { DeviceProfileId } from '@shared/models/id/device-profile-id';
  24 +import { RuleChainId } from '@shared/models/id/rule-chain-id';
  25 +import { EntityInfoData } from '@shared/models/entity.models';
  26 +
  27 +export enum DeviceProfileType {
  28 + DEFAULT = 'DEFAULT',
  29 + LWM2M = 'LWM2M'
  30 +}
  31 +
  32 +export interface DefaultDeviceProfileConfiguration {
  33 + [key: string]: any;
  34 +}
  35 +export interface Lwm2mDeviceProfileConfiguration {
  36 + [key: string]: any;
  37 +}
  38 +
  39 +export type DeviceProfileConfigurations = DefaultDeviceProfileConfiguration & Lwm2mDeviceProfileConfiguration;
  40 +
  41 +export interface DeviceProfileConfiguration extends DeviceProfileConfigurations {
  42 + type: DeviceProfileType;
  43 +}
  44 +
  45 +export interface DeviceProfileData {
  46 + configuration: DeviceProfileConfiguration;
  47 +}
  48 +
  49 +export interface DeviceProfile extends BaseData<DeviceProfileId> {
  50 + tenantId?: TenantId;
  51 + name: string;
  52 + description?: string;
  53 + isDefault: boolean;
  54 + type: DeviceProfileType;
  55 + defaultRuleChainId?: RuleChainId;
  56 + profileData: DeviceProfileData;
  57 +}
  58 +
  59 +export interface DeviceProfileInfo extends EntityInfoData {
  60 + type: DeviceProfileType;
  61 +}
  62 +
  63 +export interface DefaultDeviceConfiguration {
  64 + [key: string]: any;
  65 +}
  66 +export interface Lwm2mDeviceConfiguration {
  67 + [key: string]: any;
  68 +}
  69 +
  70 +export type DeviceConfigurations = DefaultDeviceConfiguration & Lwm2mDeviceConfiguration;
  71 +
  72 +export interface DeviceConfiguration extends DeviceConfigurations {
  73 + type: DeviceProfileType;
  74 +}
  75 +
  76 +export interface DeviceData {
  77 + configuration: DeviceConfiguration;
  78 +}
23 79
24 80 export interface Device extends BaseData<DeviceId> {
25 81 tenantId?: TenantId;
... ... @@ -27,12 +83,15 @@ export interface Device extends BaseData<DeviceId> {
27 83 name: string;
28 84 type: string;
29 85 label: string;
  86 + deviceProfileId: DeviceProfileId;
  87 + deviceData: DeviceData;
30 88 additionalInfo?: any;
31 89 }
32 90
33 91 export interface DeviceInfo extends Device {
34 92 customerTitle: string;
35 93 customerIsPublic: boolean;
  94 + deviceProfileName: string;
36 95 }
37 96
38 97 export enum DeviceCredentialsType {
... ... @@ -69,6 +128,6 @@ export enum ClaimResponse {
69 128 }
70 129
71 130 export interface ClaimResult {
72   - device: Device,
73   - response: ClaimResponse
  131 + device: Device;
  132 + response: ClaimResponse;
74 133 }
... ...
... ... @@ -35,11 +35,13 @@ import { BaseData, HasId } from '@shared/models/base-data';
35 35
36 36 export enum EntityType {
37 37 TENANT = 'TENANT',
  38 + TENANT_PROFILE = 'TENANT_PROFILE',
38 39 CUSTOMER = 'CUSTOMER',
39 40 USER = 'USER',
40 41 DASHBOARD = 'DASHBOARD',
41 42 ASSET = 'ASSET',
42 43 DEVICE = 'DEVICE',
  44 + DEVICE_PROFILE = 'DEVICE_PROFILE',
43 45 ALARM = 'ALARM',
44 46 RULE_CHAIN = 'RULE_CHAIN',
45 47 RULE_NODE = 'RULE_NODE',
... ... @@ -89,6 +91,20 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
89 91 }
90 92 ],
91 93 [
  94 + EntityType.TENANT_PROFILE,
  95 + {
  96 + type: 'entity.type-tenant-profile',
  97 + typePlural: 'entity.type-tenant-profiles',
  98 + list: 'entity.list-of-tenant-profiles',
  99 + nameStartsWith: 'entity.tenant-profile-name-starts-with',
  100 + details: 'tenant-profile.tenant-profile-details',
  101 + add: 'tenant-profile.add',
  102 + noEntities: 'tenant-profile.no-tenant-profiles-text',
  103 + search: 'tenant-profile.search',
  104 + selectedEntities: 'tenant-profile.selected-tenant-profiles'
  105 + }
  106 + ],
  107 + [
92 108 EntityType.CUSTOMER,
93 109 {
94 110 type: 'entity.type-customer',
... ... @@ -131,6 +147,20 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
131 147 }
132 148 ],
133 149 [
  150 + EntityType.DEVICE_PROFILE,
  151 + {
  152 + type: 'entity.type-device-profile',
  153 + typePlural: 'entity.type-device-profiles',
  154 + list: 'entity.list-of-device-profiles',
  155 + nameStartsWith: 'entity.device-profile-name-starts-with',
  156 + details: 'device-profile.device-profile-details',
  157 + add: 'device-profile.add',
  158 + noEntities: 'device-profile.no-device-profiles-text',
  159 + search: 'device-profile.search',
  160 + selectedEntities: 'device-profile.selected-device-profiles'
  161 + }
  162 + ],
  163 + [
134 164 EntityType.ASSET,
135 165 {
136 166 type: 'entity.type-asset',
... ... @@ -258,6 +288,12 @@ export const entityTypeResources = new Map<EntityType, EntityTypeResource<BaseDa
258 288 }
259 289 ],
260 290 [
  291 + EntityType.TENANT_PROFILE,
  292 + {
  293 + helpLinkId: 'tenantProfiles'
  294 + }
  295 + ],
  296 + [
261 297 EntityType.CUSTOMER,
262 298 {
263 299 helpLinkId: 'customers'
... ... @@ -276,6 +312,12 @@ export const entityTypeResources = new Map<EntityType, EntityTypeResource<BaseDa
276 312 }
277 313 ],
278 314 [
  315 + EntityType.DEVICE_PROFILE,
  316 + {
  317 + helpLinkId: 'deviceProfiles'
  318 + }
  319 + ],
  320 + [
279 321 EntityType.ASSET,
280 322 {
281 323 helpLinkId: 'assets'
... ...
... ... @@ -16,6 +16,7 @@
16 16
17 17 import { EntityType } from '@shared/models/entity-type.models';
18 18 import { AttributeData } from './telemetry/telemetry.models';
  19 +import { EntityId } from '@shared/models/id/entity-id';
19 20
20 21 export interface EntityInfo {
21 22 name?: string;
... ... @@ -25,6 +26,11 @@ export interface EntityInfo {
25 26 entityDescription?: string;
26 27 }
27 28
  29 +export interface EntityInfoData {
  30 + id: EntityId;
  31 + name: string;
  32 +}
  33 +
28 34 export interface ImportEntityData {
29 35 name: string;
30 36 type: string;
... ...
  1 +///
  2 +/// Copyright © 2016-2020 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { EntityId } from './entity-id';
  18 +import { EntityType } from '@shared/models/entity-type.models';
  19 +
  20 +export class DeviceProfileId implements EntityId {
  21 + entityType = EntityType.DEVICE_PROFILE;
  22 + id: string;
  23 + constructor(id: string) {
  24 + this.id = id;
  25 + }
  26 +}
... ...
... ... @@ -21,6 +21,7 @@ export * from './customer-id';
21 21 export * from './dashboard-id';
22 22 export * from './device-credentials-id';
23 23 export * from './device-id';
  24 +export * from './device-profile-id';
24 25 export * from './entity-id';
25 26 export * from './entity-view-id';
26 27 export * from './event-id';
... ... @@ -28,6 +29,7 @@ export * from './has-uuid';
28 29 export * from './rule-chain-id';
29 30 export * from './rule-node-id';
30 31 export * from './tenant-id';
  32 +export * from './tenant-profile-id';
31 33 export * from './user-id';
32 34 export * from './widget-type-id';
33 35 export * from './widgets-bundle-id';
... ...
  1 +///
  2 +/// Copyright © 2016-2020 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { EntityId } from './entity-id';
  18 +import { EntityType } from '@shared/models/entity-type.models';
  19 +
  20 +export class TenantProfileId implements EntityId {
  21 + entityType = EntityType.TENANT_PROFILE;
  22 + id: string;
  23 + constructor(id: string) {
  24 + this.id = id;
  25 + }
  26 +}
... ...
... ... @@ -50,7 +50,7 @@ export function entityKeyTypeToDataKeyType(entityKeyType: EntityKeyType): DataKe
50 50 case EntityKeyType.CLIENT_ATTRIBUTE:
51 51 case EntityKeyType.SHARED_ATTRIBUTE:
52 52 case EntityKeyType.SERVER_ATTRIBUTE:
53   - return DataKeyType.attribute
  53 + return DataKeyType.attribute;
54 54 case EntityKeyType.TIME_SERIES:
55 55 return DataKeyType.timeseries;
56 56 case EntityKeyType.ENTITY_FIELD:
... ... @@ -81,11 +81,10 @@ export interface EntityKey {
81 81 }
82 82
83 83 export function dataKeyToEntityKey(dataKey: DataKey): EntityKey {
84   - const entityKey: EntityKey = {
  84 + return {
85 85 key: dataKey.name,
86 86 type: dataKeyTypeToEntityKeyType(dataKey.type)
87 87 };
88   - return entityKey;
89 88 }
90 89
91 90 export enum EntityKeyValueType {
... ... @@ -287,26 +286,26 @@ export interface FilterPredicateValue<T> {
287 286 }
288 287
289 288 export interface StringFilterPredicate {
290   - type: FilterPredicateType.STRING,
  289 + type: FilterPredicateType.STRING;
291 290 operation: StringOperation;
292 291 value: FilterPredicateValue<string>;
293 292 ignoreCase: boolean;
294 293 }
295 294
296 295 export interface NumericFilterPredicate {
297   - type: FilterPredicateType.NUMERIC,
  296 + type: FilterPredicateType.NUMERIC;
298 297 operation: NumericOperation;
299 298 value: FilterPredicateValue<number>;
300 299 }
301 300
302 301 export interface BooleanFilterPredicate {
303   - type: FilterPredicateType.BOOLEAN,
  302 + type: FilterPredicateType.BOOLEAN;
304 303 operation: BooleanOperation;
305 304 value: FilterPredicateValue<boolean>;
306 305 }
307 306
308 307 export interface BaseComplexFilterPredicate<T extends KeyFilterPredicate | KeyFilterPredicateInfo> {
309   - type: FilterPredicateType.COMPLEX,
  308 + type: FilterPredicateType.COMPLEX;
310 309 operation: ComplexOperation;
311 310 predicates: Array<T>;
312 311 }
... ... @@ -481,7 +480,7 @@ export interface Filter extends FilterInfo {
481 480 }
482 481
483 482 export interface Filters {
484   - [id: string]: Filter
  483 + [id: string]: Filter;
485 484 }
486 485
487 486 export interface EntityFilter extends EntityFilters {
... ... @@ -535,7 +534,7 @@ export function createDefaultEntityDataPageLink(pageSize: number): EntityDataPag
535 534 },
536 535 direction: Direction.DESC
537 536 }
538   - }
  537 + };
539 538 }
540 539
541 540 export const singleEntityDataPageLink: EntityDataPageLink = createDefaultEntityDataPageLink(1);
... ...
... ... @@ -16,11 +16,29 @@
16 16
17 17 import { ContactBased } from '@shared/models/contact-based.model';
18 18 import { TenantId } from './id/tenant-id';
  19 +import { TenantProfileId } from '@shared/models/id/tenant-profile-id';
  20 +import { BaseData } from '@shared/models/base-data';
  21 +
  22 +export interface TenantProfileData {
  23 + [key: string]: string;
  24 +}
  25 +
  26 +export interface TenantProfile extends BaseData<TenantProfileId> {
  27 + name: string;
  28 + description: string;
  29 + isDefault: boolean;
  30 + isolatedTbCore: boolean;
  31 + isolatedTbRuleEngine: boolean;
  32 + profileData: TenantProfileData;
  33 +}
19 34
20 35 export interface Tenant extends ContactBased<TenantId> {
21 36 title: string;
22 37 region: string;
23   - isolatedTbCore: boolean;
24   - isolatedTbRuleEngine: boolean;
  38 + tenantProfileId: TenantProfileId;
25 39 additionalInfo?: any;
26 40 }
  41 +
  42 +export interface TenantInfo extends Tenant {
  43 + tenantProfileName: string;
  44 +}
... ...
... ... @@ -750,6 +750,15 @@
750 750 "search": "Search devices",
751 751 "selected-devices": "{ count, plural, 1 {1 device} other {# devices} } selected"
752 752 },
  753 + "device-profile": {
  754 + "device-profile": "Device profile",
  755 + "device-profiles": "Device profiles",
  756 + "add": "Add device profile",
  757 + "device-profile-details": "Device profile details",
  758 + "no-device-profiles-text": "No device profiles found",
  759 + "search": "Search device profiles",
  760 + "selected-device-profiles": "{ count, plural, 1 {1 device profile} other {# device profiles} } selected"
  761 + },
753 762 "dialog": {
754 763 "close": "Close dialog"
755 764 },
... ... @@ -806,6 +815,10 @@
806 815 "type-devices": "Devices",
807 816 "list-of-devices": "{ count, plural, 1 {One device} other {List of # devices} }",
808 817 "device-name-starts-with": "Devices whose names start with '{{prefix}}'",
  818 + "type-device-profile": "Device profile",
  819 + "type-device-profiles": "Device profiles",
  820 + "list-of-device-profiles": "{ count, plural, 1 {One device profile} other {List of # device profiles} }",
  821 + "device-profile-name-starts-with": "Device profiles whose names start with '{{prefix}}'",
809 822 "type-asset": "Asset",
810 823 "type-assets": "Assets",
811 824 "list-of-assets": "{ count, plural, 1 {One asset} other {List of # assets} }",
... ... @@ -826,6 +839,10 @@
826 839 "type-tenants": "Tenants",
827 840 "list-of-tenants": "{ count, plural, 1 {One tenant} other {List of # tenants} }",
828 841 "tenant-name-starts-with": "Tenants whose names start with '{{prefix}}'",
  842 + "type-tenant-profile": "Tenant profile",
  843 + "type-tenant-profiles": "Tenant profiles",
  844 + "list-of-tenant-profiles": "{ count, plural, 1 {One tenant profile} other {List of # tenant profiles} }",
  845 + "tenant-profile-name-starts-with": "Tenant profiles whose names start with '{{prefix}}'",
829 846 "type-customer": "Customer",
830 847 "type-customers": "Customers",
831 848 "list-of-customers": "{ count, plural, 1 {One customer} other {List of # customers} }",
... ... @@ -1659,6 +1676,15 @@
1659 1676 "isolated-tb-core-details": "Requires separate microservice(s) per isolated Tenant",
1660 1677 "isolated-tb-rule-engine-details": "Requires separate microservice(s) per isolated Tenant"
1661 1678 },
  1679 + "tenant-profile": {
  1680 + "tenant-profile": "Tenant profile",
  1681 + "tenant-profiles": "Tenant profiles",
  1682 + "add": "Add tenant profile",
  1683 + "tenant-profile-details": "Tenant profile details",
  1684 + "no-tenant-profiles-text": "No tenant profiles found",
  1685 + "search": "Search tenant profiles",
  1686 + "selected-tenant-profiles": "{ count, plural, 1 {1 tenant profile} other {# tenant profiles} } selected"
  1687 + },
1662 1688 "timeinterval": {
1663 1689 "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }",
1664 1690 "minutes-interval": "{ minutes, plural, 1 {1 minute} other {# minutes} }",
... ... @@ -2059,4 +2085,4 @@
2059 2085 "ka_GE": "ქართული"
2060 2086 }
2061 2087 }
2062   -}
  2088 +},
... ...