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