UI: Added new component copy-device-credentials
This commit is contained in:
parent
986cfe5cc1
commit
205be4e5ce
@ -0,0 +1,26 @@
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<button mat-raised-button
|
||||
ngxClipboard
|
||||
[cbContent]="credential"
|
||||
(cbOnSuccess)="onCopyCredential()"
|
||||
[fxHide]="hideButton"
|
||||
[disabled]="disabled || loading">
|
||||
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon>
|
||||
<span>{{ buttonLabel }}</span>
|
||||
</button>
|
||||
@ -0,0 +1,128 @@
|
||||
///
|
||||
/// 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, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { EntityId } from '@shared/models/id/entity-id';
|
||||
import { DeviceService } from '@core/http/device.service';
|
||||
import { DeviceCredentials, DeviceCredentialsType } from '@shared/models/device.models';
|
||||
import { isDefinedAndNotNull, isEqual } from '@core/utils';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, mergeMap, tap } from 'rxjs/operators';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { ActionNotificationShow } from '@core/notification/notification.actions';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '@core/core.state';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-copy-device-credentials',
|
||||
templateUrl: './copy-device-credentials.component.html',
|
||||
styleUrls: []
|
||||
})
|
||||
export class CopyDeviceCredentialsComponent implements OnDestroy {
|
||||
|
||||
private deviceId$ = new BehaviorSubject<EntityId>(null);
|
||||
|
||||
private credentials$ = new Subject<DeviceCredentials>();
|
||||
|
||||
private tooltipMessage: string;
|
||||
|
||||
public hideButton = true;
|
||||
|
||||
public credential: string;
|
||||
|
||||
public loading = false;
|
||||
|
||||
public buttonLabel: string;
|
||||
|
||||
@Input()
|
||||
set deviceId(deviceId: EntityId) {
|
||||
this.deviceId$.next(deviceId);
|
||||
}
|
||||
|
||||
@Input() disabled: boolean;
|
||||
|
||||
@Input()
|
||||
set credentials(credential: DeviceCredentials) {
|
||||
this.credentials$.next(credential);
|
||||
}
|
||||
|
||||
constructor(private store: Store<AppState>,
|
||||
private translate: TranslateService,
|
||||
private deviceService: DeviceService
|
||||
) {
|
||||
this.deviceId$.pipe(
|
||||
filter(device => isDefinedAndNotNull(device) && device.entityType === EntityType.DEVICE),
|
||||
distinctUntilChanged((prev, curr) => prev.id === curr.id),
|
||||
tap(() => this.loading = true),
|
||||
mergeMap(device => this.deviceService.getDeviceCredentials(device.id))
|
||||
).subscribe(deviceCredentials => {
|
||||
this.processingValue(deviceCredentials);
|
||||
this.loading = false;
|
||||
});
|
||||
|
||||
this.credentials$.pipe(
|
||||
filter(credential => isDefinedAndNotNull(credential)),
|
||||
distinctUntilChanged((prev, curr) => isEqual(prev, curr))
|
||||
).subscribe(deviceCredentials => {
|
||||
console.warn(deviceCredentials);
|
||||
this.processingValue(deviceCredentials);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.deviceId$.unsubscribe();
|
||||
this.credentials$.unsubscribe();
|
||||
}
|
||||
|
||||
private processingValue(credential: DeviceCredentials): void {
|
||||
switch (credential.credentialsType) {
|
||||
case DeviceCredentialsType.ACCESS_TOKEN:
|
||||
this.hideButton = false;
|
||||
this.credential = credential.credentialsId;
|
||||
this.buttonLabel = this.translate.instant('device.copyAccessToken');
|
||||
this.tooltipMessage = this.translate.instant('device.accessTokenCopiedMessage');
|
||||
break;
|
||||
case DeviceCredentialsType.MQTT_BASIC:
|
||||
this.hideButton = false;
|
||||
this.credential = this.convertObjectToString(JSON.parse(credential.credentialsValue));
|
||||
this.buttonLabel = this.translate.instant('device.copy-mqtt-authentication');
|
||||
this.tooltipMessage = this.translate.instant('device.mqtt-authentication-copied-message');
|
||||
break;
|
||||
default:
|
||||
this.hideButton = true;
|
||||
this.credential = null;
|
||||
this.buttonLabel = '';
|
||||
this.tooltipMessage = '';
|
||||
}
|
||||
}
|
||||
|
||||
private convertObjectToString(obj: object): string {
|
||||
Object.keys(obj).forEach(k => (!obj[k] && obj[k] !== undefined) && delete obj[k]);
|
||||
return JSON.stringify(obj).replace(/"([^"]+)":/g, '$1:');
|
||||
}
|
||||
|
||||
onCopyCredential() {
|
||||
this.store.dispatch(new ActionNotificationShow(
|
||||
{
|
||||
message: this.tooltipMessage,
|
||||
type: 'success',
|
||||
duration: 750,
|
||||
verticalPosition: 'bottom',
|
||||
horizontalPosition: 'right'
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -105,7 +105,7 @@ import { AlarmRuleConditionComponent } from './profile/alarm/alarm-rule-conditio
|
||||
import { FilterTextComponent } from './filter/filter-text.component';
|
||||
import { AddDeviceProfileDialogComponent } from './profile/add-device-profile-dialog.component';
|
||||
import { RuleChainAutocompleteComponent } from './rule-chain/rule-chain-autocomplete.component';
|
||||
import { DeviceProfileProvisionConfigurationComponent } from "./profile/device-profile-provision-configuration.component";
|
||||
import { DeviceProfileProvisionConfigurationComponent } from './profile/device-profile-provision-configuration.component';
|
||||
import { AlarmScheduleComponent } from './profile/alarm/alarm-schedule.component';
|
||||
import { DeviceWizardDialogComponent } from './wizard/device-wizard-dialog.component';
|
||||
import { DeviceCredentialsComponent } from './device/device-credentials.component';
|
||||
@ -115,6 +115,7 @@ import { EditAlarmDetailsDialogComponent } from './profile/alarm/edit-alarm-deta
|
||||
import { AlarmRuleConditionDialogComponent } from '@home/components/profile/alarm/alarm-rule-condition-dialog.component';
|
||||
import { DefaultTenantProfileConfigurationComponent } from './profile/tenant/default-tenant-profile-configuration.component';
|
||||
import { TenantProfileConfigurationComponent } from './profile/tenant/tenant-profile-configuration.component';
|
||||
import { CopyDeviceCredentialsComponent } from './device/copy-device-credentials.component';
|
||||
|
||||
@NgModule({
|
||||
declarations:
|
||||
@ -211,6 +212,7 @@ import { TenantProfileConfigurationComponent } from './profile/tenant/tenant-pro
|
||||
AlarmScheduleComponent,
|
||||
DeviceWizardDialogComponent,
|
||||
DeviceCredentialsComponent,
|
||||
CopyDeviceCredentialsComponent,
|
||||
AlarmScheduleDialogComponent,
|
||||
EditAlarmDetailsDialogComponent
|
||||
],
|
||||
@ -293,6 +295,7 @@ import { TenantProfileConfigurationComponent } from './profile/tenant/tenant-pro
|
||||
RuleChainAutocompleteComponent,
|
||||
DeviceWizardDialogComponent,
|
||||
DeviceCredentialsComponent,
|
||||
CopyDeviceCredentialsComponent,
|
||||
AlarmScheduleInfoComponent,
|
||||
AlarmScheduleComponent,
|
||||
AlarmScheduleDialogComponent,
|
||||
|
||||
@ -51,16 +51,17 @@
|
||||
ngxClipboard
|
||||
(cbOnSuccess)="onDeviceIdCopied($event)"
|
||||
[cbContent]="entity?.id?.id"
|
||||
[disabled]="(isLoading$ | async)"
|
||||
[fxShow]="!isEdit">
|
||||
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon>
|
||||
<span translate>device.copyId</span>
|
||||
</button>
|
||||
<button mat-raised-button
|
||||
(click)="copyAccessToken($event)"
|
||||
[fxShow]="!isEdit">
|
||||
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon>
|
||||
<span translate>device.copyAccessToken</span>
|
||||
</button>
|
||||
<tb-copy-device-credentials
|
||||
[fxShow]="!isEdit"
|
||||
[disabled]="(isLoading$ | async)"
|
||||
[credentials]="componentsData.deviceCredential"
|
||||
[deviceId]="entity?.id">
|
||||
</tb-copy-device-credentials>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mat-padding" fxLayout="column">
|
||||
|
||||
@ -21,10 +21,9 @@ import { EntityComponent } from '../../components/entity/entity.component';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import {
|
||||
createDeviceConfiguration,
|
||||
createDeviceProfileConfiguration, createDeviceTransportConfiguration,
|
||||
createDeviceTransportConfiguration,
|
||||
DeviceData,
|
||||
DeviceInfo,
|
||||
DeviceProfileData,
|
||||
DeviceProfileInfo,
|
||||
DeviceProfileType,
|
||||
DeviceTransportType
|
||||
@ -33,8 +32,6 @@ import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { NULL_UUID } from '@shared/models/id/has-uuid';
|
||||
import { ActionNotificationShow } from '@core/notification/notification.actions';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DeviceService } from '@core/http/device.service';
|
||||
import { ClipboardService } from 'ngx-clipboard';
|
||||
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
|
||||
|
||||
@Component({
|
||||
@ -46,12 +43,12 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
|
||||
|
||||
entityType = EntityType;
|
||||
|
||||
componentsData: any;
|
||||
|
||||
deviceScope: 'tenant' | 'customer' | 'customer_user';
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
protected translate: TranslateService,
|
||||
private deviceService: DeviceService,
|
||||
private clipboardService: ClipboardService,
|
||||
@Inject('entity') protected entityValue: DeviceInfo,
|
||||
@Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<DeviceInfo>,
|
||||
public fb: FormBuilder) {
|
||||
@ -60,6 +57,7 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
|
||||
|
||||
ngOnInit() {
|
||||
this.deviceScope = this.entitiesTableConfig.componentsData.deviceScope;
|
||||
this.componentsData = this.entitiesTableConfigValue.componentsData;
|
||||
super.ngOnInit();
|
||||
}
|
||||
|
||||
@ -114,26 +112,6 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
|
||||
}));
|
||||
}
|
||||
|
||||
copyAccessToken($event) {
|
||||
if (this.entity.id) {
|
||||
this.deviceService.getDeviceCredentials(this.entity.id.id, true).subscribe(
|
||||
(deviceCredentials) => {
|
||||
const credentialsId = deviceCredentials.credentialsId;
|
||||
if (this.clipboardService.copyFromContent(credentialsId)) {
|
||||
this.store.dispatch(new ActionNotificationShow(
|
||||
{
|
||||
message: this.translate.instant('device.accessTokenCopiedMessage'),
|
||||
type: 'success',
|
||||
duration: 750,
|
||||
verticalPosition: 'bottom',
|
||||
horizontalPosition: 'right'
|
||||
}));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
onDeviceProfileUpdated() {
|
||||
this.entitiesTableConfig.table.updateData(false);
|
||||
}
|
||||
|
||||
@ -63,6 +63,7 @@ import { DeviceTabsComponent } from '@home/pages/device/device-tabs.component';
|
||||
import { HomeDialogsService } from '@home/dialogs/home-dialogs.service';
|
||||
import { DeviceWizardDialogComponent } from '@home/components/wizard/device-wizard-dialog.component';
|
||||
import { BaseData, HasId } from '@shared/models/base-data';
|
||||
import { isDefinedAndNotNull } from '@core/utils';
|
||||
|
||||
@Injectable()
|
||||
export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<DeviceInfo>> {
|
||||
@ -115,7 +116,8 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
|
||||
const routeParams = route.params;
|
||||
this.config.componentsData = {
|
||||
deviceScope: route.data.devicesType,
|
||||
deviceProfileId: null
|
||||
deviceProfileId: null,
|
||||
deviceCredential: null
|
||||
};
|
||||
this.customerId = routeParams.customerId;
|
||||
return this.store.pipe(select(selectAuthUser), take(1)).pipe(
|
||||
@ -479,6 +481,11 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
|
||||
deviceId: device.id.id,
|
||||
isReadOnly: this.config.componentsData.deviceScope === 'customer_user'
|
||||
}
|
||||
}).afterClosed().subscribe(deviceCredential => {
|
||||
if (isDefinedAndNotNull(deviceCredential)) {
|
||||
this.config.table.onEntityUpdated(device);
|
||||
this.config.componentsData.deviceCredential = deviceCredential;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -814,8 +814,10 @@
|
||||
"details": "Details",
|
||||
"copyId": "Copy device Id",
|
||||
"copyAccessToken": "Copy access token",
|
||||
"copy-mqtt-authentication": "Copy MQTT authentication",
|
||||
"idCopiedMessage": "Device Id has been copied to clipboard",
|
||||
"accessTokenCopiedMessage": "Device access token has been copied to clipboard",
|
||||
"mqtt-authentication-copied-message": "Device MQTT authentication has been copied to clipboard",
|
||||
"assignedToCustomer": "Assigned to customer",
|
||||
"unable-delete-device-alias-title": "Unable to delete device alias",
|
||||
"unable-delete-device-alias-text": "Device alias '{{deviceAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user