21 changed files with 810 additions and 31 deletions
@ -0,0 +1,67 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2020 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 { HttpClient } from '@angular/common/http'; |
||||
|
import { PageLink } from '@shared/models/page/page-link'; |
||||
|
import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; |
||||
|
import { Observable } from 'rxjs'; |
||||
|
import { PageData } from '@shared/models/page/page-data'; |
||||
|
import { TenantProfile } from '@shared/models/tenant.model'; |
||||
|
import { EntityInfoData } from '@shared/models/entity.models'; |
||||
|
|
||||
|
@Injectable({ |
||||
|
providedIn: 'root' |
||||
|
}) |
||||
|
export class TenantProfileService { |
||||
|
|
||||
|
constructor( |
||||
|
private http: HttpClient |
||||
|
) { } |
||||
|
|
||||
|
public getTenantProfiles(pageLink: PageLink, config?: RequestConfig): Observable<PageData<TenantProfile>> { |
||||
|
return this.http.get<PageData<TenantProfile>>(`/api/tenantProfiles${pageLink.toQuery()}`, defaultHttpOptionsFromConfig(config)); |
||||
|
} |
||||
|
|
||||
|
public getTenantProfile(tenantProfileId: string, config?: RequestConfig): Observable<TenantProfile> { |
||||
|
return this.http.get<TenantProfile>(`/api/tenantProfile/${tenantProfileId}`, defaultHttpOptionsFromConfig(config)); |
||||
|
} |
||||
|
|
||||
|
public saveTenantProfile(tenantProfile: TenantProfile, config?: RequestConfig): Observable<TenantProfile> { |
||||
|
return this.http.post<TenantProfile>('/api/tenantProfile', tenantProfile, defaultHttpOptionsFromConfig(config)); |
||||
|
} |
||||
|
|
||||
|
public deleteTenantProfile(tenantProfileId: string, config?: RequestConfig) { |
||||
|
return this.http.delete(`/api/tenantProfile/${tenantProfileId}`, defaultHttpOptionsFromConfig(config)); |
||||
|
} |
||||
|
|
||||
|
public setDefaultTenantProfile(tenantProfileId: string, config?: RequestConfig): Observable<TenantProfile> { |
||||
|
return this.http.post<TenantProfile>(`/api/tenantProfile/${tenantProfileId}/default`, defaultHttpOptionsFromConfig(config)); |
||||
|
} |
||||
|
|
||||
|
public getDefaultTenantProfileInfo(config?: RequestConfig): Observable<EntityInfoData> { |
||||
|
return this.http.get<EntityInfoData>('/api/tenantProfileInfo/default', defaultHttpOptionsFromConfig(config)); |
||||
|
} |
||||
|
|
||||
|
public getTenantProfileInfo(tenantProfileId: string, config?: RequestConfig): Observable<EntityInfoData> { |
||||
|
return this.http.get<EntityInfoData>(`/api/tenantProfileInfo/${tenantProfileId}`, defaultHttpOptionsFromConfig(config)); |
||||
|
} |
||||
|
|
||||
|
public getTenantProfileInfos(pageLink: PageLink, config?: RequestConfig): Observable<PageData<EntityInfoData>> { |
||||
|
return this.http.get<PageData<EntityInfoData>>(`/api/tenantProfileInfos${pageLink.toQuery()}`, defaultHttpOptionsFromConfig(config)); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2020 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]="selectTenantProfileFormGroup" class="mat-block"> |
||||
|
<input matInput type="text" placeholder="{{ 'tenant-profile.tenant-profile' | translate }}" |
||||
|
#tenantProfileInput |
||||
|
formControlName="tenantProfile" |
||||
|
[required]="required" |
||||
|
[matAutocomplete]="tenantProfileAutocomplete"> |
||||
|
<button *ngIf="selectTenantProfileFormGroup.get('tenantProfile').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 |
||||
|
class="tb-autocomplete" |
||||
|
#tenantProfileAutocomplete="matAutocomplete" |
||||
|
[displayWith]="displayTenantProfileFn"> |
||||
|
<mat-option *ngFor="let tenantProfile of filteredTenantProfiles | async" [value]="tenantProfile"> |
||||
|
<span [innerHTML]="tenantProfile.name | highlight:searchText"></span> |
||||
|
</mat-option> |
||||
|
<mat-option *ngIf="!(filteredTenantProfiles | async)?.length" [value]="null"> |
||||
|
<span> |
||||
|
{{ translate.get('tenant-profile.no-tenant-profiles-matching', {entity: searchText}) | async }} |
||||
|
</span> |
||||
|
</mat-option> |
||||
|
</mat-autocomplete> |
||||
|
<mat-error *ngIf="selectTenantProfileFormGroup.get('tenantProfile').hasError('required')"> |
||||
|
{{ 'tenant-profile.tenant-profile-required' | translate }} |
||||
|
</mat-error> |
||||
|
</mat-form-field> |
||||
@ -0,0 +1,171 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2020 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, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; |
||||
|
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
||||
|
import { Observable } from 'rxjs'; |
||||
|
import { PageLink } from '@shared/models/page/page-link'; |
||||
|
import { Direction } from '@shared/models/page/sort-order'; |
||||
|
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 { coerceBooleanProperty } from '@angular/cdk/coercion'; |
||||
|
import { TenantProfileId } from '@shared/models/id/tenant-profile-id'; |
||||
|
import { EntityInfoData } from '@shared/models/entity.models'; |
||||
|
import { TenantProfileService } from '@core/http/tenant-profile.service'; |
||||
|
import { entityIdEquals } from '../../../../shared/models/id/entity-id'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-tenant-profile-autocomplete', |
||||
|
templateUrl: './tenant-profile-autocomplete.component.html', |
||||
|
styleUrls: [], |
||||
|
providers: [{ |
||||
|
provide: NG_VALUE_ACCESSOR, |
||||
|
useExisting: forwardRef(() => TenantProfileAutocompleteComponent), |
||||
|
multi: true |
||||
|
}] |
||||
|
}) |
||||
|
export class TenantProfileAutocompleteComponent implements ControlValueAccessor, OnInit { |
||||
|
|
||||
|
selectTenantProfileFormGroup: FormGroup; |
||||
|
|
||||
|
modelValue: TenantProfileId | null; |
||||
|
|
||||
|
@Input() |
||||
|
selectDefaultProfile = false; |
||||
|
|
||||
|
private requiredValue: boolean; |
||||
|
get required(): boolean { |
||||
|
return this.requiredValue; |
||||
|
} |
||||
|
@Input() |
||||
|
set required(value: boolean) { |
||||
|
this.requiredValue = coerceBooleanProperty(value); |
||||
|
} |
||||
|
|
||||
|
@Input() |
||||
|
disabled: boolean; |
||||
|
|
||||
|
@ViewChild('tenantProfileInput', {static: true}) tenantProfileInput: ElementRef; |
||||
|
|
||||
|
filteredTenantProfiles: Observable<Array<EntityInfoData>>; |
||||
|
|
||||
|
searchText = ''; |
||||
|
|
||||
|
private propagateChange = (v: any) => { }; |
||||
|
|
||||
|
constructor(private store: Store<AppState>, |
||||
|
public translate: TranslateService, |
||||
|
private tenantProfileService: TenantProfileService, |
||||
|
private fb: FormBuilder) { |
||||
|
this.selectTenantProfileFormGroup = this.fb.group({ |
||||
|
tenantProfile: [null] |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
registerOnChange(fn: any): void { |
||||
|
this.propagateChange = fn; |
||||
|
} |
||||
|
|
||||
|
registerOnTouched(fn: any): void { |
||||
|
} |
||||
|
|
||||
|
ngOnInit() { |
||||
|
this.filteredTenantProfiles = this.selectTenantProfileFormGroup.get('tenantProfile').valueChanges |
||||
|
.pipe( |
||||
|
tap((value: EntityInfoData | string) => { |
||||
|
let modelValue: TenantProfileId | null; |
||||
|
if (typeof value === 'string' || !value) { |
||||
|
modelValue = null; |
||||
|
} else { |
||||
|
modelValue = new TenantProfileId(value.id.id); |
||||
|
} |
||||
|
this.updateView(modelValue); |
||||
|
}), |
||||
|
startWith<string | EntityInfoData>(''), |
||||
|
map(value => value ? (typeof value === 'string' ? value : value.name) : ''), |
||||
|
mergeMap(name => this.fetchTenantProfiles(name) ) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
selectDefaultTenantProfileIfNeeded(): void { |
||||
|
if (this.selectDefaultProfile && !this.modelValue) { |
||||
|
this.tenantProfileService.getDefaultTenantProfileInfo().subscribe( |
||||
|
(profile) => { |
||||
|
if (profile) { |
||||
|
this.modelValue = new TenantProfileId(profile.id.id); |
||||
|
this.selectTenantProfileFormGroup.get('tenantProfile').patchValue(profile, {emitEvent: false}); |
||||
|
this.propagateChange(this.modelValue); |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
setDisabledState(isDisabled: boolean): void { |
||||
|
this.disabled = isDisabled; |
||||
|
} |
||||
|
|
||||
|
writeValue(value: TenantProfileId | null): void { |
||||
|
this.searchText = ''; |
||||
|
if (value != null) { |
||||
|
this.tenantProfileService.getTenantProfileInfo(value.id).subscribe( |
||||
|
(profile) => { |
||||
|
this.modelValue = new TenantProfileId(profile.id.id); |
||||
|
this.selectTenantProfileFormGroup.get('tenantProfile').patchValue(profile, {emitEvent: true}); |
||||
|
} |
||||
|
); |
||||
|
} else { |
||||
|
this.modelValue = null; |
||||
|
this.selectTenantProfileFormGroup.get('tenantProfile').patchValue(null, {emitEvent: true}); |
||||
|
this.selectDefaultTenantProfileIfNeeded(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
updateView(value: TenantProfileId | null) { |
||||
|
if (!entityIdEquals(this.modelValue, value)) { |
||||
|
this.modelValue = value; |
||||
|
this.propagateChange(this.modelValue); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
displayTenantProfileFn(profile?: EntityInfoData): string | undefined { |
||||
|
return profile ? profile.name : undefined; |
||||
|
} |
||||
|
|
||||
|
fetchTenantProfiles(searchText?: string): Observable<Array<EntityInfoData>> { |
||||
|
this.searchText = searchText; |
||||
|
const pageLink = new PageLink(10, 0, searchText, { |
||||
|
property: 'name', |
||||
|
direction: Direction.ASC |
||||
|
}); |
||||
|
return this.tenantProfileService.getTenantProfileInfos(pageLink, {ignoreLoading: true}).pipe( |
||||
|
map(pageData => { |
||||
|
return pageData.data; |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
clear() { |
||||
|
this.selectTenantProfileFormGroup.get('tenantProfile').patchValue(null, {emitEvent: true}); |
||||
|
setTimeout(() => { |
||||
|
this.tenantProfileInput.nativeElement.blur(); |
||||
|
this.tenantProfileInput.nativeElement.focus(); |
||||
|
}, 0); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2020 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. |
||||
|
|
||||
|
--> |
||||
|
<div class="tb-details-buttons" fxLayout.xs="column" *ngIf="!standalone"> |
||||
|
<button mat-raised-button color="primary" |
||||
|
[disabled]="(isLoading$ | async)" |
||||
|
(click)="onEntityAction($event, 'setDefault')" |
||||
|
[fxShow]="!isEdit && !entity?.default"> |
||||
|
{{'tenant-profile.set-default' | translate }} |
||||
|
</button> |
||||
|
<button mat-raised-button color="primary" |
||||
|
[disabled]="(isLoading$ | async)" |
||||
|
(click)="onEntityAction($event, 'delete')" |
||||
|
[fxShow]="!hideDelete() && !isEdit"> |
||||
|
{{'tenant-profile.delete' | translate }} |
||||
|
</button> |
||||
|
<div fxLayout="row" fxLayout.xs="column"> |
||||
|
<button mat-raised-button |
||||
|
ngxClipboard |
||||
|
(cbOnSuccess)="onTenantProfileIdCopied($event)" |
||||
|
[cbContent]="entity?.id?.id" |
||||
|
[fxShow]="!isEdit"> |
||||
|
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon> |
||||
|
<span translate>tenant-profile.copyId</span> |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="mat-padding" fxLayout="column"> |
||||
|
<form [formGroup]="entityForm"> |
||||
|
<fieldset [disabled]="(isLoading$ | async) || !isEdit"> |
||||
|
<mat-form-field class="mat-block"> |
||||
|
<mat-label translate>tenant-profile.name</mat-label> |
||||
|
<input matInput formControlName="name" required/> |
||||
|
<mat-error *ngIf="entityForm.get('name').hasError('required')"> |
||||
|
{{ 'tenant-profile.name-required' | translate }} |
||||
|
</mat-error> |
||||
|
</mat-form-field> |
||||
|
<div fxLayout="column"> |
||||
|
<mat-checkbox class="hinted-checkbox" formControlName="isolatedTbCore"> |
||||
|
<div>{{ 'tenant.isolated-tb-core' | translate }}</div> |
||||
|
<div class="tb-hint">{{'tenant.isolated-tb-core-details' | translate}}</div> |
||||
|
</mat-checkbox> |
||||
|
<mat-checkbox class="hinted-checkbox" formControlName="isolatedTbRuleEngine"> |
||||
|
<div>{{ 'tenant.isolated-tb-rule-engine' | translate }}</div> |
||||
|
<div class="tb-hint">{{'tenant.isolated-tb-rule-engine-details' | translate}}</div> |
||||
|
</mat-checkbox> |
||||
|
</div> |
||||
|
<mat-form-field class="mat-block"> |
||||
|
<mat-label translate>tenant-profile.description</mat-label> |
||||
|
<textarea matInput formControlName="description" rows="2"></textarea> |
||||
|
</mat-form-field> |
||||
|
</fieldset> |
||||
|
</form> |
||||
|
</div> |
||||
@ -0,0 +1,96 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2020 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, Inject, Input } from '@angular/core'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
|
import { TenantProfile } from '@app/shared/models/tenant.model'; |
||||
|
import { ActionNotificationShow } from '@app/core/notification/notification.actions'; |
||||
|
import { TranslateService } from '@ngx-translate/core'; |
||||
|
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; |
||||
|
import { EntityComponent } from '../entity/entity.component'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-tenant-profile', |
||||
|
templateUrl: './tenant-profile.component.html', |
||||
|
styleUrls: ['./tenant-profile.component.scss'] |
||||
|
}) |
||||
|
export class TenantProfileComponent extends EntityComponent<TenantProfile> { |
||||
|
|
||||
|
@Input() |
||||
|
standalone = false; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>, |
||||
|
protected translate: TranslateService, |
||||
|
@Inject('entity') protected entityValue: TenantProfile, |
||||
|
@Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<TenantProfile>, |
||||
|
protected fb: FormBuilder) { |
||||
|
super(store, fb, entityValue, entitiesTableConfigValue); |
||||
|
} |
||||
|
|
||||
|
hideDelete() { |
||||
|
if (this.entitiesTableConfig) { |
||||
|
return !this.entitiesTableConfig.deleteEnabled(this.entity); |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
buildForm(entity: TenantProfile): FormGroup { |
||||
|
return this.fb.group( |
||||
|
{ |
||||
|
name: [entity ? entity.name : '', [Validators.required]], |
||||
|
isolatedTbCore: [entity ? entity.isolatedTbCore : false, []], |
||||
|
isolatedTbRuleEngine: [entity ? entity.isolatedTbRuleEngine : false, []], |
||||
|
description: [entity ? entity.description : '', []], |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
updateForm(entity: TenantProfile) { |
||||
|
this.entityForm.patchValue({name: entity.name}); |
||||
|
this.entityForm.patchValue({isolatedTbCore: entity.isolatedTbCore}); |
||||
|
this.entityForm.patchValue({isolatedTbRuleEngine: entity.isolatedTbRuleEngine}); |
||||
|
this.entityForm.patchValue({description: entity.description}); |
||||
|
} |
||||
|
|
||||
|
updateFormState() { |
||||
|
if (this.entityForm) { |
||||
|
if (this.isEditValue) { |
||||
|
this.entityForm.enable({emitEvent: false}); |
||||
|
if (!this.isAdd) { |
||||
|
this.entityForm.get('isolatedTbCore').disable({emitEvent: false}); |
||||
|
this.entityForm.get('isolatedTbRuleEngine').disable({emitEvent: false}); |
||||
|
} |
||||
|
} else { |
||||
|
this.entityForm.disable({emitEvent: false}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
onTenantProfileIdCopied(event) { |
||||
|
this.store.dispatch(new ActionNotificationShow( |
||||
|
{ |
||||
|
message: this.translate.instant('tenant-profile.idCopiedMessage'), |
||||
|
type: 'success', |
||||
|
duration: 750, |
||||
|
verticalPosition: 'bottom', |
||||
|
horizontalPosition: 'right' |
||||
|
})); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2020 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 { NgModule } from '@angular/core'; |
||||
|
import { RouterModule, Routes } from '@angular/router'; |
||||
|
|
||||
|
import { EntitiesTableComponent } from '../../components/entity/entities-table.component'; |
||||
|
import { Authority } from '@shared/models/authority.enum'; |
||||
|
import { TenantProfilesTableConfigResolver } from './tenant-profiles-table-config.resolver'; |
||||
|
|
||||
|
const routes: Routes = [ |
||||
|
{ |
||||
|
path: 'tenantProfiles', |
||||
|
data: { |
||||
|
breadcrumb: { |
||||
|
label: 'tenant-profile.tenant-profiles', |
||||
|
icon: 'mdi:alpha-t-box' |
||||
|
} |
||||
|
}, |
||||
|
children: [ |
||||
|
{ |
||||
|
path: '', |
||||
|
component: EntitiesTableComponent, |
||||
|
data: { |
||||
|
auth: [Authority.SYS_ADMIN], |
||||
|
title: 'tenant-profile.tenant-profiles' |
||||
|
}, |
||||
|
resolve: { |
||||
|
entitiesTableConfig: TenantProfilesTableConfigResolver |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
]; |
||||
|
|
||||
|
@NgModule({ |
||||
|
imports: [RouterModule.forChild(routes)], |
||||
|
exports: [RouterModule], |
||||
|
providers: [ |
||||
|
TenantProfilesTableConfigResolver |
||||
|
] |
||||
|
}) |
||||
|
export class TenantProfileRoutingModule { } |
||||
@ -0,0 +1,43 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2020 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-tab *ngIf="entity" |
||||
|
label="{{ 'attribute.attributes' | translate }}" #attributesTab="matTab"> |
||||
|
<tb-attribute-table [defaultAttributeScope]="attributeScopes.SERVER_SCOPE" |
||||
|
[active]="attributesTab.isActive" |
||||
|
[entityId]="entity.id" |
||||
|
[entityName]="entity.name"> |
||||
|
</tb-attribute-table> |
||||
|
</mat-tab> |
||||
|
<mat-tab *ngIf="entity" |
||||
|
label="{{ 'attribute.latest-telemetry' | translate }}" #telemetryTab="matTab"> |
||||
|
<tb-attribute-table [defaultAttributeScope]="latestTelemetryTypes.LATEST_TELEMETRY" |
||||
|
disableAttributeScopeSelection |
||||
|
[active]="telemetryTab.isActive" |
||||
|
[entityId]="entity.id" |
||||
|
[entityName]="entity.name"> |
||||
|
</tb-attribute-table> |
||||
|
</mat-tab> |
||||
|
<mat-tab *ngIf="entity" |
||||
|
label="{{ 'alarm.alarms' | translate }}" #alarmsTab="matTab"> |
||||
|
<tb-alarm-table [active]="alarmsTab.isActive" [entityId]="entity.id"></tb-alarm-table> |
||||
|
</mat-tab> |
||||
|
<mat-tab *ngIf="entity" |
||||
|
label="{{ 'tenant.events' | translate }}" #eventsTab="matTab"> |
||||
|
<tb-event-table [defaultEventType]="eventTypes.ERROR" [active]="eventsTab.isActive" [tenantId]="nullUid" |
||||
|
[entityId]="entity.id"></tb-event-table> |
||||
|
</mat-tab> |
||||
@ -0,0 +1,38 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2020 The Thingsboard Authors
|
||||
|
///
|
||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
/// you may not use this file except in compliance with the License.
|
||||
|
/// You may obtain a copy of the License at
|
||||
|
///
|
||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
///
|
||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
/// See the License for the specific language governing permissions and
|
||||
|
/// limitations under the License.
|
||||
|
///
|
||||
|
|
||||
|
import { Component } from '@angular/core'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { EntityTabsComponent } from '../../components/entity/entity-tabs.component'; |
||||
|
import { TenantProfile } from '@shared/models/tenant.model'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-tenant-profile-tabs', |
||||
|
templateUrl: './tenant-profile-tabs.component.html', |
||||
|
styleUrls: [] |
||||
|
}) |
||||
|
export class TenantProfileTabsComponent extends EntityTabsComponent<TenantProfile> { |
||||
|
|
||||
|
constructor(protected store: Store<AppState>) { |
||||
|
super(store); |
||||
|
} |
||||
|
|
||||
|
ngOnInit() { |
||||
|
super.ngOnInit(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2020 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 { NgModule } from '@angular/core'; |
||||
|
import { CommonModule } from '@angular/common'; |
||||
|
import { SharedModule } from '@shared/shared.module'; |
||||
|
import { HomeComponentsModule } from '@modules/home/components/home-components.module'; |
||||
|
import { TenantProfileRoutingModule } from './tenant-profile-routing.module'; |
||||
|
import { TenantProfileTabsComponent } from './tenant-profile-tabs.component'; |
||||
|
|
||||
|
@NgModule({ |
||||
|
declarations: [ |
||||
|
TenantProfileTabsComponent |
||||
|
], |
||||
|
imports: [ |
||||
|
CommonModule, |
||||
|
SharedModule, |
||||
|
HomeComponentsModule, |
||||
|
TenantProfileRoutingModule |
||||
|
] |
||||
|
}) |
||||
|
export class TenantProfileModule { } |
||||
@ -0,0 +1,122 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2020 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 { Resolve } from '@angular/router'; |
||||
|
import { TenantProfile } from '@shared/models/tenant.model'; |
||||
|
import { |
||||
|
checkBoxCell, |
||||
|
DateEntityTableColumn, |
||||
|
EntityTableColumn, |
||||
|
EntityTableConfig |
||||
|
} from '@home/models/entity/entities-table-config.models'; |
||||
|
import { TranslateService } from '@ngx-translate/core'; |
||||
|
import { DatePipe } from '@angular/common'; |
||||
|
import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models'; |
||||
|
import { EntityAction } from '@home/models/entity/entity-component.models'; |
||||
|
import { TenantProfileService } from '@core/http/tenant-profile.service'; |
||||
|
import { TenantProfileComponent } from '../../components/profile/tenant-profile.component'; |
||||
|
import { TenantProfileTabsComponent } from './tenant-profile-tabs.component'; |
||||
|
import { DialogService } from '@core/services/dialog.service'; |
||||
|
|
||||
|
@Injectable() |
||||
|
export class TenantProfilesTableConfigResolver implements Resolve<EntityTableConfig<TenantProfile>> { |
||||
|
|
||||
|
private readonly config: EntityTableConfig<TenantProfile> = new EntityTableConfig<TenantProfile>(); |
||||
|
|
||||
|
constructor(private tenantProfileService: TenantProfileService, |
||||
|
private translate: TranslateService, |
||||
|
private datePipe: DatePipe, |
||||
|
private dialogService: DialogService) { |
||||
|
|
||||
|
this.config.entityType = EntityType.TENANT_PROFILE; |
||||
|
this.config.entityComponent = TenantProfileComponent; |
||||
|
this.config.entityTabsComponent = TenantProfileTabsComponent; |
||||
|
this.config.entityTranslations = entityTypeTranslations.get(EntityType.TENANT_PROFILE); |
||||
|
this.config.entityResources = entityTypeResources.get(EntityType.TENANT_PROFILE); |
||||
|
|
||||
|
this.config.columns.push( |
||||
|
new DateEntityTableColumn<TenantProfile>('createdTime', 'common.created-time', this.datePipe, '150px'), |
||||
|
new EntityTableColumn<TenantProfile>('name', 'tenant-profile.name', '40%'), |
||||
|
new EntityTableColumn<TenantProfile>('description', 'tenant-profile.description', '60%'), |
||||
|
new EntityTableColumn<TenantProfile>('isDefault', 'tenant-profile.default', '60px', |
||||
|
entity => { |
||||
|
return checkBoxCell(entity.default); |
||||
|
}) |
||||
|
); |
||||
|
|
||||
|
this.config.cellActionDescriptors.push( |
||||
|
{ |
||||
|
name: this.translate.instant('tenant-profile.set-default'), |
||||
|
icon: 'flag', |
||||
|
isEnabled: (tenantProfile) => !tenantProfile.default, |
||||
|
onAction: ($event, entity) => this.setDefaultTenantProfile($event, entity) |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
this.config.deleteEntityTitle = tenantProfile => this.translate.instant('tenant-profile.delete-tenant-profile-title', |
||||
|
{ tenantProfileName: tenantProfile.name }); |
||||
|
this.config.deleteEntityContent = () => this.translate.instant('tenant-profile.delete-tenant-profile-text'); |
||||
|
this.config.deleteEntitiesTitle = count => this.translate.instant('tenant-profile.delete-tenant-profiles-title', {count}); |
||||
|
this.config.deleteEntitiesContent = () => this.translate.instant('tenant-profile.delete-tenant-profiles-text'); |
||||
|
|
||||
|
this.config.entitiesFetchFunction = pageLink => this.tenantProfileService.getTenantProfiles(pageLink); |
||||
|
this.config.loadEntity = id => this.tenantProfileService.getTenantProfile(id.id); |
||||
|
this.config.saveEntity = tenantProfile => this.tenantProfileService.saveTenantProfile(tenantProfile); |
||||
|
this.config.deleteEntity = id => this.tenantProfileService.deleteTenantProfile(id.id); |
||||
|
this.config.onEntityAction = action => this.onTenantProfileAction(action); |
||||
|
this.config.deleteEnabled = (tenantProfile) => tenantProfile && !tenantProfile.default; |
||||
|
this.config.entitySelectionEnabled = (tenantProfile) => tenantProfile && !tenantProfile.default; |
||||
|
} |
||||
|
|
||||
|
resolve(): EntityTableConfig<TenantProfile> { |
||||
|
this.config.tableTitle = this.translate.instant('tenant-profile.tenant-profiles'); |
||||
|
|
||||
|
return this.config; |
||||
|
} |
||||
|
|
||||
|
setDefaultTenantProfile($event: Event, tenantProfile: TenantProfile) { |
||||
|
if ($event) { |
||||
|
$event.stopPropagation(); |
||||
|
} |
||||
|
this.dialogService.confirm( |
||||
|
this.translate.instant('tenant-profile.set-default-tenant-profile-title', {tenantProfileName: tenantProfile.name}), |
||||
|
this.translate.instant('tenant-profile.set-default-tenant-profile-text'), |
||||
|
this.translate.instant('action.no'), |
||||
|
this.translate.instant('action.yes'), |
||||
|
true |
||||
|
).subscribe((res) => { |
||||
|
if (res) { |
||||
|
this.tenantProfileService.setDefaultTenantProfile(tenantProfile.id.id).subscribe( |
||||
|
() => { |
||||
|
this.config.table.updateData(); |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
onTenantProfileAction(action: EntityAction<TenantProfile>): boolean { |
||||
|
switch (action.action) { |
||||
|
case 'setDefault': |
||||
|
this.setDefaultTenantProfile(action.event, action.entity); |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
} |
||||
Loading…
Reference in new issue