33 changed files with 1551 additions and 42 deletions
@ -0,0 +1,263 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 {Injectable} from '@angular/core'; |
|||
import {Observable, throwError, of, empty, EMPTY} from 'rxjs/index'; |
|||
import {HttpClient} from '@angular/common/http'; |
|||
import {PageLink} from '@shared/models/page/page-link'; |
|||
import {EntityType} from '@shared/models/entity-type.models'; |
|||
import {BaseData} from '@shared/models/base-data'; |
|||
import {EntityId} from '@shared/models/id/entity-id'; |
|||
import {DeviceService} from '@core/http/device.service'; |
|||
import {TenantService} from '@core/http/tenant.service'; |
|||
import {CustomerService} from '@core/http/customer.service'; |
|||
import {UserService} from './user.service'; |
|||
import {DashboardService} from '@core/http/dashboard.service'; |
|||
import {Direction} from '@shared/models/page/sort-order'; |
|||
import {PageData} from '@shared/models/page/page-data'; |
|||
import {getCurrentAuthUser} from '../auth/auth.selectors'; |
|||
import {Store} from '@ngrx/store'; |
|||
import {AppState} from '@core/core.state'; |
|||
import {Authority} from '@shared/models/authority.enum'; |
|||
import {Tenant} from '@shared/models/tenant.model'; |
|||
import {concatMap, expand, map, toArray} from 'rxjs/operators'; |
|||
import {Customer} from '@app/shared/models/customer.model'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root' |
|||
}) |
|||
export class EntityService { |
|||
|
|||
constructor( |
|||
private http: HttpClient, |
|||
private store: Store<AppState>, |
|||
private deviceService: DeviceService, |
|||
private tenantService: TenantService, |
|||
private customerService: CustomerService, |
|||
private userService: UserService, |
|||
private dashboardService: DashboardService |
|||
) { } |
|||
|
|||
private getEntityObservable(entityType: EntityType, entityId: string, |
|||
ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<BaseData<EntityId>> { |
|||
|
|||
let observable: Observable<BaseData<EntityId>>; |
|||
switch (entityType) { |
|||
case EntityType.DEVICE: |
|||
observable = this.deviceService.getDevice(entityId, ignoreErrors, ignoreLoading); |
|||
break; |
|||
case EntityType.ASSET: |
|||
// TODO:
|
|||
break; |
|||
case EntityType.ENTITY_VIEW: |
|||
// TODO:
|
|||
break; |
|||
case EntityType.TENANT: |
|||
observable = this.tenantService.getTenant(entityId, ignoreErrors, ignoreLoading); |
|||
break; |
|||
case EntityType.CUSTOMER: |
|||
observable = this.customerService.getCustomer(entityId, ignoreErrors, ignoreLoading); |
|||
break; |
|||
case EntityType.DASHBOARD: |
|||
observable = this.dashboardService.getDashboardInfo(entityId, ignoreErrors, ignoreLoading); |
|||
break; |
|||
case EntityType.USER: |
|||
observable = this.userService.getUser(entityId, ignoreErrors, ignoreLoading); |
|||
break; |
|||
case EntityType.RULE_CHAIN: |
|||
// TODO:
|
|||
break; |
|||
case EntityType.ALARM: |
|||
console.error('Get Alarm Entity is not implemented!'); |
|||
break; |
|||
} |
|||
return observable; |
|||
} |
|||
|
|||
public getEntity(entityType: EntityType, entityId: string, |
|||
ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<BaseData<EntityId>> { |
|||
const entityObservable = this.getEntityObservable(entityType, entityId, ignoreErrors, ignoreLoading); |
|||
if (entityObservable) { |
|||
return entityObservable; |
|||
} else { |
|||
return throwError(null); |
|||
} |
|||
} |
|||
|
|||
private getSingleTenantByPageLinkObservable(pageLink: PageLink, |
|||
ignoreErrors: boolean = false, |
|||
ignoreLoading: boolean = false): Observable<PageData<Tenant>> { |
|||
const authUser = getCurrentAuthUser(this.store); |
|||
const tenantId = authUser.tenantId; |
|||
return this.tenantService.getTenant(tenantId, ignoreErrors, ignoreLoading).pipe( |
|||
map((tenant) => { |
|||
const result = { |
|||
data: [], |
|||
totalPages: 0, |
|||
totalElements: 0, |
|||
hasNext: false |
|||
} as PageData<Tenant>; |
|||
if (tenant.title.toLowerCase().startsWith(pageLink.textSearch.toLowerCase())) { |
|||
result.data.push(tenant); |
|||
result.totalPages = 1; |
|||
result.totalElements = 1; |
|||
} |
|||
return result; |
|||
}) |
|||
); |
|||
} |
|||
|
|||
private getSingleCustomerByPageLinkObservable(pageLink: PageLink, |
|||
ignoreErrors: boolean = false, |
|||
ignoreLoading: boolean = false): Observable<PageData<Customer>> { |
|||
const authUser = getCurrentAuthUser(this.store); |
|||
const customerId = authUser.customerId; |
|||
return this.customerService.getCustomer(customerId, ignoreErrors, ignoreLoading).pipe( |
|||
map((customer) => { |
|||
const result = { |
|||
data: [], |
|||
totalPages: 0, |
|||
totalElements: 0, |
|||
hasNext: false |
|||
} as PageData<Customer>; |
|||
if (customer.title.toLowerCase().startsWith(pageLink.textSearch.toLowerCase())) { |
|||
result.data.push(customer); |
|||
result.totalPages = 1; |
|||
result.totalElements = 1; |
|||
} |
|||
return result; |
|||
}) |
|||
); |
|||
} |
|||
|
|||
private getEntitiesByPageLinkObservable(entityType: EntityType, pageLink: PageLink, subType: string = '', |
|||
ignoreErrors: boolean = false, |
|||
ignoreLoading: boolean = false): Observable<PageData<BaseData<EntityId>>> { |
|||
let entitiesObservable: Observable<PageData<BaseData<EntityId>>>; |
|||
const authUser = getCurrentAuthUser(this.store); |
|||
const customerId = authUser.customerId; |
|||
switch (entityType) { |
|||
case EntityType.DEVICE: |
|||
pageLink.sortOrder.property = 'name'; |
|||
if (authUser.authority === Authority.CUSTOMER_USER) { |
|||
entitiesObservable = this.deviceService.getCustomerDeviceInfos(customerId, pageLink, subType, ignoreErrors, ignoreLoading); |
|||
} else { |
|||
entitiesObservable = this.deviceService.getTenantDeviceInfos(pageLink, subType, ignoreErrors, ignoreLoading); |
|||
} |
|||
break; |
|||
case EntityType.ASSET: |
|||
pageLink.sortOrder.property = 'name'; |
|||
if (authUser.authority === Authority.CUSTOMER_USER) { |
|||
// TODO:
|
|||
} else { |
|||
// TODO:
|
|||
} |
|||
break; |
|||
case EntityType.ENTITY_VIEW: |
|||
pageLink.sortOrder.property = 'name'; |
|||
if (authUser.authority === Authority.CUSTOMER_USER) { |
|||
// TODO:
|
|||
} else { |
|||
// TODO:
|
|||
} |
|||
break; |
|||
case EntityType.TENANT: |
|||
pageLink.sortOrder.property = 'title'; |
|||
if (authUser.authority === Authority.TENANT_ADMIN) { |
|||
entitiesObservable = this.getSingleTenantByPageLinkObservable(pageLink, ignoreErrors, ignoreLoading); |
|||
} else { |
|||
entitiesObservable = this.tenantService.getTenants(pageLink, ignoreErrors, ignoreLoading); |
|||
} |
|||
break; |
|||
case EntityType.CUSTOMER: |
|||
pageLink.sortOrder.property = 'title'; |
|||
if (authUser.authority === Authority.CUSTOMER_USER) { |
|||
entitiesObservable = this.getSingleCustomerByPageLinkObservable(pageLink, ignoreErrors, ignoreLoading); |
|||
} else { |
|||
entitiesObservable = this.customerService.getCustomers(pageLink, ignoreErrors, ignoreLoading); |
|||
} |
|||
break; |
|||
case EntityType.RULE_CHAIN: |
|||
pageLink.sortOrder.property = 'name'; |
|||
// TODO:
|
|||
break; |
|||
case EntityType.DASHBOARD: |
|||
pageLink.sortOrder.property = 'title'; |
|||
if (authUser.authority === Authority.CUSTOMER_USER) { |
|||
entitiesObservable = this.dashboardService.getCustomerDashboards(customerId, pageLink, ignoreErrors, ignoreLoading); |
|||
} else { |
|||
entitiesObservable = this.dashboardService.getTenantDashboards(pageLink, ignoreErrors, ignoreLoading); |
|||
} |
|||
break; |
|||
case EntityType.USER: |
|||
console.error('Get User Entities is not implemented!'); |
|||
break; |
|||
case EntityType.ALARM: |
|||
console.error('Get Alarm Entities is not implemented!'); |
|||
break; |
|||
} |
|||
return entitiesObservable; |
|||
} |
|||
|
|||
private getEntitiesByPageLink(entityType: EntityType, pageLink: PageLink, subType: string = '', |
|||
ignoreErrors: boolean = false, |
|||
ignoreLoading: boolean = false): Observable<Array<BaseData<EntityId>>> { |
|||
const entitiesObservable: Observable<PageData<BaseData<EntityId>>> = |
|||
this.getEntitiesByPageLinkObservable(entityType, pageLink, subType, ignoreErrors, ignoreLoading); |
|||
if (entitiesObservable) { |
|||
return entitiesObservable.pipe( |
|||
expand((data) => { |
|||
if (data.hasNext) { |
|||
pageLink.page += 1; |
|||
return this.getEntitiesByPageLinkObservable(entityType, pageLink, subType, ignoreErrors, ignoreLoading); |
|||
} else { |
|||
return EMPTY; |
|||
} |
|||
}), |
|||
map((data) => data.data), |
|||
concatMap((data) => data), |
|||
toArray() |
|||
); |
|||
} else { |
|||
return of(null); |
|||
} |
|||
} |
|||
|
|||
public getEntitiesByNameFilter(entityType: EntityType, entityNameFilter: string, |
|||
pageSize: number, subType: string = '', |
|||
ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<Array<BaseData<EntityId>>> { |
|||
const pageLink = new PageLink(pageSize, 0, entityNameFilter, { |
|||
property: 'name', |
|||
direction: Direction.ASC |
|||
}); |
|||
if (pageSize === -1) { // all
|
|||
pageLink.pageSize = 100; |
|||
return this.getEntitiesByPageLink(entityType, pageLink, subType, ignoreErrors, ignoreLoading).pipe( |
|||
map((data) => data && data.length ? data : null) |
|||
); |
|||
} else { |
|||
const entitiesObservable: Observable<PageData<BaseData<EntityId>>> = |
|||
this.getEntitiesByPageLinkObservable(entityType, pageLink, subType, ignoreErrors, ignoreLoading); |
|||
if (entitiesObservable) { |
|||
return entitiesObservable.pipe( |
|||
map((data) => data && data.data.length ? data.data : null) |
|||
); |
|||
} else { |
|||
return of(null); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2019 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. |
|||
|
|||
--> |
|||
<form #deviceCredentialsForm="ngForm" [formGroup]="deviceCredentialsFormGroup" (ngSubmit)="save()"> |
|||
<mat-toolbar fxLayout="row" color="primary"> |
|||
<h2 translate>device.device-credentials</h2> |
|||
<span fxFlex></span> |
|||
<button mat-button mat-icon-button |
|||
(click)="cancel()" |
|||
type="button"> |
|||
<mat-icon class="material-icons">close</mat-icon> |
|||
</button> |
|||
</mat-toolbar> |
|||
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> |
|||
</mat-progress-bar> |
|||
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> |
|||
<div mat-dialog-content> |
|||
<fieldset [disabled]="(isLoading$ | async) || isReadOnly"> |
|||
<mat-form-field class="mat-block"> |
|||
<mat-label translate>device.credentials-type</mat-label> |
|||
<mat-select matInput formControlName="credentialsType" |
|||
(ngModelChange)="credentialsTypeChanged()"> |
|||
<mat-option *ngFor="let credentialsType of credentialsTypes" [value]="credentialsType"> |
|||
{{ credentialTypeNamesMap.get(credentialsType) }} |
|||
</mat-option> |
|||
</mat-select> |
|||
</mat-form-field> |
|||
<mat-form-field *ngIf="deviceCredentialsFormGroup.get('credentialsType').value === deviceCredentialsType.ACCESS_TOKEN" |
|||
class="mat-block"> |
|||
<mat-label translate>device.access-token</mat-label> |
|||
<input matInput formControlName="credentialsId" required> |
|||
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsId').hasError('required')"> |
|||
{{ 'device.access-token-required' | translate }} |
|||
</mat-error> |
|||
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsId').hasError('pattern')"> |
|||
{{ 'device.access-token-invalid' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
<mat-form-field *ngIf="deviceCredentialsFormGroup.get('credentialsType').value === deviceCredentialsType.X509_CERTIFICATE" |
|||
class="mat-block"> |
|||
<mat-label translate>device.rsa-key</mat-label> |
|||
<textarea matInput formControlName="credentialsValue" cols="15" rows="5" required></textarea> |
|||
<mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsValue').hasError('required')"> |
|||
{{ 'device.rsa-key-required' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
</fieldset> |
|||
</div> |
|||
<div mat-dialog-actions fxLayout="row"> |
|||
<span fxFlex></span> |
|||
<button *ngIf="!isReadOnly" mat-button mat-raised-button color="primary" |
|||
type="submit" |
|||
[disabled]="(isLoading$ | async) || deviceCredentialsForm.invalid |
|||
|| !deviceCredentialsForm.dirty"> |
|||
{{ 'action.save' | translate }} |
|||
</button> |
|||
<button mat-button color="primary" |
|||
style="margin-right: 20px;" |
|||
type="button" |
|||
[disabled]="(isLoading$ | async)" |
|||
(click)="cancel()" cdkFocusInitial> |
|||
{{ (isReadOnly ? 'action.close' : 'action.cancel') | translate }} |
|||
</button> |
|||
</div> |
|||
</form> |
|||
@ -0,0 +1,138 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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, OnInit, SkipSelf, Inject} from '@angular/core'; |
|||
import {ErrorStateMatcher, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material'; |
|||
import { PageComponent } from '@shared/components/page.component'; |
|||
import { Store } from '@ngrx/store'; |
|||
import { AppState } from '@core/core.state'; |
|||
import {FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators} from '@angular/forms'; |
|||
import { ActionNotificationShow } from '@core/notification/notification.actions'; |
|||
import { TranslateService } from '@ngx-translate/core'; |
|||
import { AuthService } from '@core/auth/auth.service'; |
|||
import {DeviceService} from '@core/http/device.service'; |
|||
import {DeviceCredentials, DeviceCredentialsType, credentialTypeNames} from '@shared/models/device.models'; |
|||
|
|||
export interface DeviceCredentialsDialogData { |
|||
isReadOnly: boolean; |
|||
deviceId: string; |
|||
} |
|||
|
|||
@Component({ |
|||
selector: 'tb-device-credentials-dialog', |
|||
templateUrl: './device-credentials-dialog.component.html', |
|||
providers: [{provide: ErrorStateMatcher, useExisting: DeviceCredentialsDialogComponent}], |
|||
styleUrls: [] |
|||
}) |
|||
export class DeviceCredentialsDialogComponent extends PageComponent implements OnInit, ErrorStateMatcher { |
|||
|
|||
deviceCredentialsFormGroup: FormGroup; |
|||
|
|||
isReadOnly: boolean; |
|||
|
|||
deviceCredentials: DeviceCredentials; |
|||
|
|||
submitted = false; |
|||
|
|||
deviceCredentialsType = DeviceCredentialsType; |
|||
|
|||
credentialsTypes = Object.keys(DeviceCredentialsType); |
|||
|
|||
credentialTypeNamesMap = credentialTypeNames; |
|||
|
|||
constructor(protected store: Store<AppState>, |
|||
@Inject(MAT_DIALOG_DATA) public data: DeviceCredentialsDialogData, |
|||
private deviceService: DeviceService, |
|||
@SkipSelf() private errorStateMatcher: ErrorStateMatcher, |
|||
public dialogRef: MatDialogRef<DeviceCredentialsDialogComponent, DeviceCredentials>, |
|||
public fb: FormBuilder) { |
|||
super(store); |
|||
|
|||
this.isReadOnly = data.isReadOnly; |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
this.deviceCredentialsFormGroup = this.fb.group({ |
|||
credentialsType: [DeviceCredentialsType.ACCESS_TOKEN], |
|||
credentialsId: [''], |
|||
credentialsValue: [''] |
|||
}); |
|||
if (this.isReadOnly) { |
|||
this.deviceCredentialsFormGroup.disable({emitEvent: false}); |
|||
} else { |
|||
this.registerDisableOnLoadFormControl(this.deviceCredentialsFormGroup.get('credentialsType')); |
|||
} |
|||
this.loadDeviceCredentials(); |
|||
} |
|||
|
|||
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { |
|||
const originalErrorState = this.errorStateMatcher.isErrorState(control, form); |
|||
const customErrorState = !!(control && control.invalid && this.submitted); |
|||
return originalErrorState || customErrorState; |
|||
} |
|||
|
|||
loadDeviceCredentials() { |
|||
this.deviceService.getDeviceCredentials(this.data.deviceId).subscribe( |
|||
(deviceCredentials) => { |
|||
this.deviceCredentials = deviceCredentials; |
|||
this.deviceCredentialsFormGroup.patchValue({ |
|||
credentialsType: deviceCredentials.credentialsType, |
|||
credentialsId: deviceCredentials.credentialsId, |
|||
credentialsValue: deviceCredentials.credentialsValue |
|||
}); |
|||
this.updateValidators(); |
|||
} |
|||
); |
|||
} |
|||
|
|||
credentialsTypeChanged(): void { |
|||
this.deviceCredentialsFormGroup.patchValue( |
|||
{credentialsId: null, credentialsValue: null}, {emitEvent: true}); |
|||
this.updateValidators(); |
|||
} |
|||
|
|||
updateValidators(): void { |
|||
const crendetialsType = this.deviceCredentialsFormGroup.get('credentialsType').value as DeviceCredentialsType; |
|||
switch (crendetialsType) { |
|||
case DeviceCredentialsType.ACCESS_TOKEN: |
|||
this.deviceCredentialsFormGroup.get('credentialsId').setValidators([Validators.max(20), Validators.pattern(/^.{1,20}$/)]); |
|||
this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity(); |
|||
this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([]); |
|||
this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity(); |
|||
break; |
|||
case DeviceCredentialsType.X509_CERTIFICATE: |
|||
this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([Validators.required]); |
|||
this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity(); |
|||
this.deviceCredentialsFormGroup.get('credentialsId').setValidators([]); |
|||
this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity(); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
cancel(): void { |
|||
this.dialogRef.close(null); |
|||
} |
|||
|
|||
save(): void { |
|||
this.submitted = true; |
|||
this.deviceCredentials = {...this.deviceCredentials, ...this.deviceCredentialsFormGroup.value}; |
|||
this.deviceService.saveDeviceCredentials(this.deviceCredentials).subscribe( |
|||
(deviceCredentials) => { |
|||
this.dialogRef.close(deviceCredentials); |
|||
} |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2019 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. |
|||
|
|||
--> |
|||
<mat-form-field [formGroup]="selectEntityFormGroup" class="mat-block"> |
|||
<input matInput type="text" placeholder="{{ entityText | translate }}" |
|||
#entityInput |
|||
formControlName="entity" |
|||
[required]="required" |
|||
[matAutocomplete]="entityAutocomplete"> |
|||
<button *ngIf="selectEntityFormGroup.get('entity').value && !disabled" |
|||
type="button" |
|||
matSuffix mat-button mat-icon-button aria-label="Clear" |
|||
(click)="clear()"> |
|||
<mat-icon class="material-icons">close</mat-icon> |
|||
</button> |
|||
<mat-autocomplete #entityAutocomplete="matAutocomplete" [displayWith]="displayEntityFn"> |
|||
<mat-option *ngFor="let entity of filteredEntities | async" [value]="entity"> |
|||
<span [innerHTML]="entity.name | highlight:searchText"></span> |
|||
</mat-option> |
|||
<mat-option *ngIf="!(filteredEntities | async)?.length" [value]="null"> |
|||
<span> |
|||
{{ translate.get(noEntitiesMatchingText, {entity: searchText}) | async }} |
|||
</span> |
|||
</mat-option> |
|||
</mat-autocomplete> |
|||
<mat-error *ngIf="selectEntityFormGroup.get('entity').hasError('required')"> |
|||
{{ entityRequiredText | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
@ -0,0 +1,274 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 {AfterViewInit, Component, ElementRef, forwardRef, Input, OnInit, ViewChild} from '@angular/core'; |
|||
import {ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR} from '@angular/forms'; |
|||
import {Observable} from 'rxjs'; |
|||
import {map, mergeMap, startWith, tap} from 'rxjs/operators'; |
|||
import {Store} from '@ngrx/store'; |
|||
import {AppState} from '@app/core/core.state'; |
|||
import {TranslateService} from '@ngx-translate/core'; |
|||
import {AliasEntityType, EntityType} from '@shared/models/entity-type.models'; |
|||
import {BaseData} from '@shared/models/base-data'; |
|||
import {EntityId} from '@shared/models/id/entity-id'; |
|||
import {EntityService} from '@core/http/entity.service'; |
|||
|
|||
@Component({ |
|||
selector: 'tb-entity-autocomplete', |
|||
templateUrl: './entity-autocomplete.component.html', |
|||
styleUrls: [], |
|||
providers: [{ |
|||
provide: NG_VALUE_ACCESSOR, |
|||
useExisting: forwardRef(() => EntityAutocompleteComponent), |
|||
multi: true |
|||
}] |
|||
}) |
|||
export class EntityAutocompleteComponent implements ControlValueAccessor, OnInit, AfterViewInit { |
|||
|
|||
selectEntityFormGroup: FormGroup; |
|||
|
|||
modelValue: string | null; |
|||
|
|||
entityTypeValue: EntityType | AliasEntityType; |
|||
|
|||
entitySubtypeValue: string; |
|||
|
|||
@Input() |
|||
set entityType(entityType: EntityType) { |
|||
if (this.entityTypeValue !== entityType) { |
|||
this.entityTypeValue = entityType; |
|||
this.load(); |
|||
} |
|||
} |
|||
|
|||
@Input() |
|||
set entitySubtype(entitySubtype: string) { |
|||
if (this.entitySubtypeValue !== entitySubtype) { |
|||
this.entitySubtypeValue = entitySubtype; |
|||
const currentEntity = this.getCurrentEntity(); |
|||
if (currentEntity) { |
|||
if ((currentEntity as any).type !== this.entitySubtypeValue) { |
|||
this.reset(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Input() |
|||
excludeEntityIds: Array<string>; |
|||
|
|||
@Input() |
|||
required: boolean; |
|||
|
|||
@Input() |
|||
disabled: boolean; |
|||
|
|||
@ViewChild('entityInput', {static: true}) entityInput: ElementRef; |
|||
|
|||
entityText: string; |
|||
noEntitiesMatchingText: string; |
|||
entityRequiredText: string; |
|||
|
|||
filteredEntities: Observable<Array<BaseData<EntityId>>>; |
|||
|
|||
private searchText = ''; |
|||
|
|||
private propagateChange = (v: any) => { }; |
|||
|
|||
constructor(private store: Store<AppState>, |
|||
public translate: TranslateService, |
|||
private entityService: EntityService, |
|||
private fb: FormBuilder) { |
|||
this.selectEntityFormGroup = this.fb.group({ |
|||
entity: [null] |
|||
}); |
|||
} |
|||
|
|||
registerOnChange(fn: any): void { |
|||
this.propagateChange = fn; |
|||
} |
|||
|
|||
registerOnTouched(fn: any): void { |
|||
} |
|||
|
|||
ngOnInit() { |
|||
this.filteredEntities = this.selectEntityFormGroup.get('dashboard').valueChanges |
|||
.pipe( |
|||
tap(value => { |
|||
let modelValue; |
|||
if (typeof value === 'string' || !value) { |
|||
modelValue = null; |
|||
} else { |
|||
modelValue = value.id.id; |
|||
} |
|||
this.updateView(modelValue); |
|||
}), |
|||
startWith<string | BaseData<EntityId>>(''), |
|||
map(value => value ? (typeof value === 'string' ? value : value.name) : ''), |
|||
mergeMap(name => this.fetchEntities(name) ) |
|||
); |
|||
} |
|||
|
|||
ngAfterViewInit(): void {} |
|||
|
|||
load(): void { |
|||
if (this.entityTypeValue) { |
|||
switch (this.entityTypeValue) { |
|||
case EntityType.ASSET: |
|||
this.entityText = 'asset.asset'; |
|||
this.noEntitiesMatchingText = 'asset.no-assets-matching'; |
|||
this.entityRequiredText = 'asset.asset-required'; |
|||
break; |
|||
case EntityType.DEVICE: |
|||
this.entityText = 'device.device'; |
|||
this.noEntitiesMatchingText = 'device.no-devices-matching'; |
|||
this.entityRequiredText = 'device.device-required'; |
|||
break; |
|||
case EntityType.ENTITY_VIEW: |
|||
this.entityText = 'entity-view.entity-view'; |
|||
this.noEntitiesMatchingText = 'entity-view.no-entity-views-matching'; |
|||
this.entityRequiredText = 'entity-view.entity-view-required'; |
|||
break; |
|||
case EntityType.RULE_CHAIN: |
|||
this.entityText = 'rulechain.rulechain'; |
|||
this.noEntitiesMatchingText = 'rulechain.no-rulechains-matching'; |
|||
this.entityRequiredText = 'rulechain.rulechain-required'; |
|||
break; |
|||
case EntityType.TENANT: |
|||
this.entityText = 'tenant.tenant'; |
|||
this.noEntitiesMatchingText = 'tenant.no-tenants-matching'; |
|||
this.entityRequiredText = 'tenant.tenant-required'; |
|||
break; |
|||
case EntityType.CUSTOMER: |
|||
this.entityText = 'customer.customer'; |
|||
this.noEntitiesMatchingText = 'customer.no-customers-matching'; |
|||
this.entityRequiredText = 'customer.customer-required'; |
|||
break; |
|||
case EntityType.USER: |
|||
this.entityText = 'user.user'; |
|||
this.noEntitiesMatchingText = 'user.no-users-matching'; |
|||
this.entityRequiredText = 'user.user-required'; |
|||
break; |
|||
case EntityType.DASHBOARD: |
|||
this.entityText = 'dashboard.dashboard'; |
|||
this.noEntitiesMatchingText = 'dashboard.no-dashboards-matching'; |
|||
this.entityRequiredText = 'dashboard.dashboard-required'; |
|||
break; |
|||
case EntityType.ALARM: |
|||
this.entityText = 'alarm.alarm'; |
|||
this.noEntitiesMatchingText = 'alarm.no-alarms-matching'; |
|||
this.entityRequiredText = 'alarm.alarm-required'; |
|||
break; |
|||
case AliasEntityType.CURRENT_CUSTOMER: |
|||
this.entityText = 'customer.default-customer'; |
|||
this.noEntitiesMatchingText = 'customer.no-customers-matching'; |
|||
this.entityRequiredText = 'customer.default-customer-required'; |
|||
break; |
|||
} |
|||
} |
|||
const currentEntity = this.getCurrentEntity(); |
|||
if (currentEntity) { |
|||
const currentEntityType = currentEntity.id.entityType; |
|||
if (this.entityTypeValue && currentEntityType !== this.entityTypeValue) { |
|||
this.reset(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
getCurrentEntity(): BaseData<EntityId> | null { |
|||
const currentEntity = this.selectEntityFormGroup.get('entity').value; |
|||
if (currentEntity && typeof currentEntity !== 'string') { |
|||
return currentEntity as BaseData<EntityId>; |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
setDisabledState(isDisabled: boolean): void { |
|||
this.disabled = isDisabled; |
|||
} |
|||
|
|||
writeValue(value: string | null): void { |
|||
this.searchText = ''; |
|||
if (value != null) { |
|||
let targetEntityType = this.entityTypeValue; |
|||
if (targetEntityType === AliasEntityType.CURRENT_CUSTOMER) { |
|||
targetEntityType = EntityType.CUSTOMER; |
|||
} |
|||
this.entityService.getEntity(targetEntityType, value).subscribe( |
|||
(entity) => { |
|||
this.modelValue = entity.id.id; |
|||
this.selectEntityFormGroup.get('entity').patchValue(entity, {emitEvent: true}); |
|||
} |
|||
); |
|||
} else { |
|||
this.modelValue = null; |
|||
this.selectEntityFormGroup.get('entity').patchValue(null, {emitEvent: true}); |
|||
} |
|||
} |
|||
|
|||
reset() { |
|||
this.selectEntityFormGroup.get('entity').patchValue(null, {emitEvent: true}); |
|||
} |
|||
|
|||
updateView(value: string | null) { |
|||
if (this.modelValue !== value) { |
|||
this.modelValue = value; |
|||
this.propagateChange(this.modelValue); |
|||
} |
|||
} |
|||
|
|||
displayEntityFn(entity?: BaseData<EntityId>): string | undefined { |
|||
return entity ? entity.name : undefined; |
|||
} |
|||
|
|||
fetchEntities(searchText?: string): Observable<Array<BaseData<EntityId>>> { |
|||
this.searchText = searchText; |
|||
let targetEntityType = this.entityTypeValue; |
|||
if (targetEntityType === AliasEntityType.CURRENT_CUSTOMER) { |
|||
targetEntityType = EntityType.CUSTOMER; |
|||
} |
|||
return this.entityService.getEntitiesByNameFilter(targetEntityType, searchText, |
|||
50, this.entitySubtypeValue, false, true).pipe( |
|||
map((data) => { |
|||
if (data) { |
|||
if (this.excludeEntityIds && this.excludeEntityIds.length) { |
|||
const entities: Array<BaseData<EntityId>> = []; |
|||
data.forEach((entity) => { |
|||
if (this.excludeEntityIds.indexOf(entity.id.id) === -1) { |
|||
entities.push(entity); |
|||
} |
|||
}); |
|||
return entities; |
|||
} else { |
|||
return data; |
|||
} |
|||
} else { |
|||
return []; |
|||
} |
|||
} |
|||
)); |
|||
} |
|||
|
|||
clear() { |
|||
this.selectEntityFormGroup.get('entity').patchValue(null, {emitEvent: true}); |
|||
setTimeout(() => { |
|||
this.entityInput.nativeElement.blur(); |
|||
this.entityInput.nativeElement.focus(); |
|||
}, 0); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 {BaseData} from '@shared/models/base-data'; |
|||
import {AssetId} from '@shared/models/id/asset-id'; |
|||
import {TenantId} from '@shared/models/id/tenant-id'; |
|||
import {CustomerId} from '@shared/models/id/customer-id'; |
|||
import {AlarmId} from '@shared/models/id/alarm-id'; |
|||
import {EntityId} from '@shared/models/id/entity-id'; |
|||
|
|||
export enum AlarmSeverity { |
|||
CRITICAL = 'CRITICAL', |
|||
MAJOR = 'MAJOR', |
|||
MINOR = 'MINOR', |
|||
WARNING = 'WARNING', |
|||
INDETERMINATE = 'INDETERMINATE' |
|||
} |
|||
|
|||
export enum AlarmStatus { |
|||
ACTIVE_UNACK = 'ACTIVE_UNACK', |
|||
ACTIVE_ACK = 'ACTIVE_ACK', |
|||
CLEARED_UNACK = 'CLEARED_UNACK', |
|||
CLEARED_ACK = 'CLEARED_ACK' |
|||
} |
|||
|
|||
export interface Alarm extends BaseData<AlarmId> { |
|||
tenantId: TenantId; |
|||
type: string; |
|||
originator: EntityId; |
|||
severity: AlarmSeverity; |
|||
status: AlarmStatus; |
|||
startTs: number; |
|||
endTs: number; |
|||
ackTs: number; |
|||
clearTs: number; |
|||
propagate: boolean; |
|||
details?: any; |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 {BaseData} from '@shared/models/base-data'; |
|||
import {AssetId} from './id/asset-id'; |
|||
import {TenantId} from '@shared/models/id/tenant-id'; |
|||
import {CustomerId} from '@shared/models/id/customer-id'; |
|||
import {DeviceCredentialsId} from '@shared/models/id/device-credentials-id'; |
|||
|
|||
export interface Asset extends BaseData<AssetId> { |
|||
tenantId: TenantId; |
|||
customerId: CustomerId; |
|||
name: string; |
|||
type: string; |
|||
additionalInfo?: any; |
|||
} |
|||
|
|||
export interface AssetInfo extends Asset { |
|||
customerTitle: string; |
|||
customerIsPublic: boolean; |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 {BaseData} from '@shared/models/base-data'; |
|||
import {AssetId} from './id/asset-id'; |
|||
import {TenantId} from '@shared/models/id/tenant-id'; |
|||
import {CustomerId} from '@shared/models/id/customer-id'; |
|||
import {EntityViewId} from '@shared/models/id/entity-view-id'; |
|||
import {EntityId} from '@shared/models/id/entity-id'; |
|||
|
|||
export interface AttributesEntityView { |
|||
cs: Array<string>; |
|||
ss: Array<string>; |
|||
sh: Array<string>; |
|||
} |
|||
|
|||
export interface TelemetryEntityView { |
|||
timeseries: Array<string>; |
|||
attributes: AttributesEntityView; |
|||
} |
|||
|
|||
export interface EntityView extends BaseData<EntityViewId> { |
|||
tenantId: TenantId; |
|||
customerId: CustomerId; |
|||
entityId: EntityId; |
|||
name: string; |
|||
type: string; |
|||
keys: TelemetryEntityView; |
|||
startTimeMs: number; |
|||
endTimeMs: number; |
|||
additionalInfo?: any; |
|||
} |
|||
|
|||
export interface EntityViewInfo extends EntityView { |
|||
customerTitle: string; |
|||
customerIsPublic: boolean; |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 { EntityId } from './entity-id'; |
|||
import { EntityType } from '@shared/models/entity-type.models'; |
|||
|
|||
export class AlarmId implements EntityId { |
|||
entityType = EntityType.ALARM; |
|||
id: string; |
|||
constructor(id: string) { |
|||
this.id = id; |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 { EntityId } from './entity-id'; |
|||
import { EntityType } from '@shared/models/entity-type.models'; |
|||
|
|||
export class AssetId implements EntityId { |
|||
entityType = EntityType.ASSET; |
|||
id: string; |
|||
constructor(id: string) { |
|||
this.id = id; |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 { HasUUID } from '@shared/models/id/has-uuid'; |
|||
|
|||
export class DeviceCredentialsId implements HasUUID { |
|||
id: string; |
|||
constructor(id: string) { |
|||
this.id = id; |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 { EntityId } from './entity-id'; |
|||
import { EntityType } from '@shared/models/entity-type.models'; |
|||
|
|||
export class EntityViewId implements EntityId { |
|||
entityType = EntityType.ENTITY_VIEW; |
|||
id: string; |
|||
constructor(id: string) { |
|||
this.id = id; |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 { EntityId } from './entity-id'; |
|||
import { EntityType } from '@shared/models/entity-type.models'; |
|||
|
|||
export class RuleChainId implements EntityId { |
|||
entityType = EntityType.RULE_CHAIN; |
|||
id: string; |
|||
constructor(id: string) { |
|||
this.id = id; |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 { EntityId } from './entity-id'; |
|||
import { EntityType } from '@shared/models/entity-type.models'; |
|||
|
|||
export class RuleNodeId implements EntityId { |
|||
entityType = EntityType.RULE_NODE; |
|||
id: string; |
|||
constructor(id: string) { |
|||
this.id = id; |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 { EntityId } from './entity-id'; |
|||
import { EntityType } from '@shared/models/entity-type.models'; |
|||
|
|||
export class WidgetTypeId implements EntityId { |
|||
entityType = EntityType.WIDGET_TYPE; |
|||
id: string; |
|||
constructor(id: string) { |
|||
this.id = id; |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 { EntityId } from './entity-id'; |
|||
import { EntityType } from '@shared/models/entity-type.models'; |
|||
|
|||
export class WidgetsBundleId implements EntityId { |
|||
entityType = EntityType.WIDGETS_BUNDLE; |
|||
id: string; |
|||
constructor(id: string) { |
|||
this.id = id; |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 {BaseData} from '@shared/models/base-data'; |
|||
import {AssetId} from '@shared/models/id/asset-id'; |
|||
import {TenantId} from '@shared/models/id/tenant-id'; |
|||
import {CustomerId} from '@shared/models/id/customer-id'; |
|||
import {RuleChainId} from '@shared/models/id/rule-chain-id'; |
|||
import {RuleNodeId} from '@shared/models/id/rule-node-id'; |
|||
|
|||
export interface RuleChainConfiguration { |
|||
todo: Array<any>; |
|||
// TODO:
|
|||
} |
|||
|
|||
export interface RuleChain extends BaseData<RuleChainId> { |
|||
tenantId: TenantId; |
|||
name: string; |
|||
firstRuleNodeId: RuleNodeId; |
|||
root: boolean; |
|||
debugMode: boolean; |
|||
configuration: RuleChainConfiguration; |
|||
additionalInfo?: any; |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 {BaseData} from '@shared/models/base-data'; |
|||
import {AssetId} from '@shared/models/id/asset-id'; |
|||
import {TenantId} from '@shared/models/id/tenant-id'; |
|||
import {CustomerId} from '@shared/models/id/customer-id'; |
|||
import {RuleChainId} from '@shared/models/id/rule-chain-id'; |
|||
import {RuleNodeId} from '@shared/models/id/rule-node-id'; |
|||
|
|||
export interface RuleNodeConfiguration { |
|||
todo: Array<any>; |
|||
// TODO:
|
|||
} |
|||
|
|||
export interface RuleNode extends BaseData<RuleNodeId> { |
|||
ruleChainId: RuleChainId; |
|||
type: string; |
|||
name: string; |
|||
debugMode: boolean; |
|||
configuration: RuleNodeConfiguration; |
|||
additionalInfo?: any; |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 {BaseData} from '@shared/models/base-data'; |
|||
import {TenantId} from '@shared/models/id/tenant-id'; |
|||
import {WidgetsBundleId} from '@shared/models/id/widgets-bundle-id'; |
|||
import {WidgetTypeId} from '@shared/models/id/widget-type-id'; |
|||
|
|||
export interface WidgetTypeDescriptor { |
|||
todo: Array<any>; |
|||
// TODO:
|
|||
} |
|||
|
|||
export interface WidgetType extends BaseData<WidgetTypeId> { |
|||
tenantId: TenantId; |
|||
bundleAlias: string; |
|||
alias: string; |
|||
name: string; |
|||
descriptor: WidgetTypeDescriptor; |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 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 {BaseData} from '@shared/models/base-data'; |
|||
import {TenantId} from '@shared/models/id/tenant-id'; |
|||
import {WidgetsBundleId} from '@shared/models/id/widgets-bundle-id'; |
|||
|
|||
export interface WidgetsBundle extends BaseData<WidgetsBundleId> { |
|||
tenantId: TenantId; |
|||
alias: string; |
|||
title: string; |
|||
image: string; |
|||
} |
|||
Loading…
Reference in new issue