device wizard and device component revert changes

This commit is contained in:
Maksym Dudnik 2023-06-30 11:42:36 +03:00
parent bebee3e43b
commit 44d16b2150
7 changed files with 17 additions and 274 deletions

View File

@ -22,7 +22,6 @@ import { DeviceCredentialsComponent } from '@home/components/device/device-crede
import { DeviceCredentialsLwm2mComponent } from '@home/components/device/device-credentials-lwm2m.component';
import { DeviceCredentialsLwm2mServerComponent } from '@home/components/device/device-credentials-lwm2m-server.component';
import { DeviceCredentialsMqttBasicComponent } from '@home/components/device/device-credentials-mqtt-basic.component';
import { DeviceExampleCommandComponent } from '@home/components/device/device-example-command.component';
@NgModule({
declarations: [
@ -30,8 +29,7 @@ import { DeviceExampleCommandComponent } from '@home/components/device/device-ex
DeviceCredentialsComponent,
DeviceCredentialsLwm2mComponent,
DeviceCredentialsLwm2mServerComponent,
DeviceCredentialsMqttBasicComponent,
DeviceExampleCommandComponent
DeviceCredentialsMqttBasicComponent
],
imports: [
CommonModule,
@ -42,8 +40,7 @@ import { DeviceExampleCommandComponent } from '@home/components/device/device-ex
DeviceCredentialsComponent,
DeviceCredentialsLwm2mComponent,
DeviceCredentialsLwm2mServerComponent,
DeviceCredentialsMqttBasicComponent,
DeviceExampleCommandComponent
DeviceCredentialsMqttBasicComponent
]
})
export class DeviceCredentialsModule { }

View File

@ -1,86 +0,0 @@
<!--
Copyright © 2016-2023 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 mat-dialog-content tb-toast fxLayout="column" toastTarget="dockerCommandDialogContent">
<mat-button-toggle-group [formControl]="protocolCtrl" class="protocol-toggle">
<mat-button-toggle value="mqtt" aria-label="mqtt">
MQTT
</mat-button-toggle>
<mat-button-toggle value="coap" aria-label="coap">
COAP
</mat-button-toggle>
<mat-button-toggle value="http" aria-label="html">
HTTP
</mat-button-toggle>
</mat-button-toggle-group>
<span class="help-title" innerHTML="{{ translate.get('device.telemetry-commands-help-link', {helpLink}) | async }}"></span>
<div class="mat-content" fxLayout="column">
<div class="mat-content" fxLayout="column" *ngIf="protocolCtrl.value === 'mqtt'">
<span>MQTT </span>
<span>{{'device.telemetry-command-setup-step'| translate}} <span [innerHTML]="mqttSetup"></span></span>
<span class="protocol-send-command">{{'device.telemetry-command-send-step'| translate}} </span>
<div fxLayout="row wrap" fxLayoutAlign="start center">
<pre class="tb-highlight" fxFlex><code class="pre-wrap">{{ mqttCode }}</code></pre>
<button mat-icon-button
color="primary"
ngxClipboard
cbContent="{{ mqttCode }}"
(cbOnSuccess)="onDockerCodeCopied()"
matTooltip="{{ 'device.transportCommandCopiedMessage' | translate }}"
matTooltipPosition="above">
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon>
</button>
</div>
</div>
<div class="mat-content" fxLayout="column" *ngIf="protocolCtrl.value === 'coap'">
<span>COAP </span>
<span>{{'device.telemetry-command-setup-step'| translate}} <span [innerHTML]="coapSetup"></span></span>
<span class="protocol-send-command">{{'device.telemetry-command-send-step-coap'| translate}}</span>
<div fxLayout="row wrap" fxLayoutAlign="start center">
<pre class="tb-highlight" fxFlex><code class="pre-wrap">{{ coapCode }}</code></pre>
<button mat-icon-button
color="primary"
ngxClipboard
cbContent="{{ coapCode }}"
(cbOnSuccess)="onDockerCodeCopied()"
matTooltip="{{ 'device.transportCommandCopiedMessage' | translate }}"
matTooltipPosition="above">
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon>
</button>
<pre class="tb-highlight" fxFlex="100"><code
class="pre-wrap">JSON example: {{'[{"temperature": 40}, {"isRainy": true}]'}}</code></pre>
</div>
</div>
<div class="mat-content" fxLayout="column" *ngIf="protocolCtrl.value === 'http'">
<span>HTTP </span>
<span>{{'device.telemetry-command-setup-step'| translate}} <span [innerHTML]="httpSetup"></span></span>
<span class="protocol-send-command">{{'device.telemetry-command-send-step'| translate}}</span>
<div fxLayout="row wrpa" fxLayoutAlign="start center">
<pre class="tb-highlight" fxFlex><code class="pre-wrap">{{ httpCode }}</code></pre>
<button mat-icon-button
color="primary"
ngxClipboard
cbContent="{{ httpCode }}"
(cbOnSuccess)="onDockerCodeCopied()"
matTooltip="{{ 'device.transportCommandCopiedMessage' | translate }}"
matTooltipPosition="above">
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon>
</button>
</div>
</div>
</div>
</div>

View File

@ -1,41 +0,0 @@
/**
* Copyright © 2016-2023 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.
*/
:host {
mat-button-toggle-group, .protocol-title {
margin-bottom: 20px;
}
span {
margin-bottom: 10px;
}
.protocol-toggle {
width: fit-content;
}
.help-title {
padding-bottom: 5px;
}
.protocol-send-command {
width: 100%;
}
.pre-wrap {
white-space: pre-wrap;
}
}

View File

@ -1,98 +0,0 @@
///
/// Copyright © 2016-2023 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, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Router } from '@angular/router';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core';
import { ActionNotificationShow } from '@core/notification/notification.actions';
import { helpBaseUrl } from '@shared/models/constants';
@Component({
selector: 'tb-device-example-command',
templateUrl: './device-example-command.component.html',
styleUrls: ['./device-example-command.component.scss']
})
export class DeviceExampleCommandComponent implements OnInit {
@Input()
token: string;
helpLink: string = helpBaseUrl + '/docs/reference/protocols/';
mqttCode: string;
coapCode: string;
httpCode: string;
mqttSetup: string;
coapSetup: string;
httpSetup: string;
protocolCtrl: FormControl;
constructor(protected router: Router,
protected store: Store<AppState>,
public translate: TranslateService) {
}
ngOnInit(): void {
const HOST = window.location.hostname;
this.mqttCode = `mosquitto_pub -d -q 1 -h ${HOST} -t "v1/devices/me/telemetry" -u "${this.token}" -m "{"temperature":42}"`;
this.coapCode = `cat telemetry-data.json | coap post coap://${HOST}/api/v1/${this.token}/telemetry`;
this.httpCode = `curl -v -X POST --data "{"temperature":42,"humidity":73}" http://${HOST}/api/v1/${this.token}/telemetry --header "Content-Type:application/json"`;
this.protocolCtrl = new FormControl('mqtt');
const mqttLink = '<a href="https://thingsboard.io/docs/getting-started-guides/helloworld/?connectdevice=mqtt-windows"> Mqtt Guide</a>';
// @ts-ignore
const platform = window.navigator?.userAgentData?.platform || window.navigator.platform,
macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'],
windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'];
if (macosPlatforms.indexOf(platform) !== -1) {
this.mqttSetup = 'brew install mosquitto-clients';
this.coapSetup = 'npm install coap-cli -g';
this.httpSetup = 'brew install curl';
} else if (windowsPlatforms.indexOf(platform) !== -1) {
this.mqttSetup = mqttLink;
this.coapSetup = 'npm install coap-cli -g';
this.httpSetup = 'not required, available by default in windows 10+';
} else if (/Linux/.test(platform)) {
this.mqttSetup = 'sudo apt-get install mosquitto-clients';
this.coapSetup = 'npm install coap-cli -g';
this.httpSetup = 'sudo apt-get install curl';
}
}
onDockerCodeCopied() {
this.store.dispatch(new ActionNotificationShow(
{
message: this.translate.instant('gateway.command-copied-message'),
type: 'success',
target: 'dockerCommandDialogContent',
duration: 1200,
verticalPosition: 'bottom',
horizontalPosition: 'left'
}));
}
}

View File

@ -29,7 +29,7 @@
</mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content>
<mat-horizontal-stepper [linear]="true" [labelPosition]="labelPosition" #addDeviceWizardStepper (selectionChange)="changeStep($event)" *ngIf="!deviceCredentials">
<mat-horizontal-stepper [linear]="true" [labelPosition]="labelPosition" #addDeviceWizardStepper (selectionChange)="changeStep($event)">
<ng-template matStepperIcon="edit">
<mat-icon>check</mat-icon>
</ng-template>
@ -178,17 +178,9 @@
</form>
</mat-step>
</mat-horizontal-stepper>
<div *ngIf="deviceCredentials" class="commands-container">
<tb-gateway-command *ngIf="device?.additionalInfo?.gateway"
[token]="deviceCredentials.credentialsId">
</tb-gateway-command>
<tb-device-example-command *ngIf="!device?.additionalInfo?.gateway"
[token]="deviceCredentials.credentialsId">
</tb-device-example-command>
</div>
</div>
<div mat-dialog-actions style="padding: 0">
<div class="dialog-actions-row" fxFlex fxLayout="row" fxLayoutAlign="end center" *ngIf="!deviceCredentials">
<div class="dialog-actions-row" fxFlex fxLayout="row" fxLayoutAlign="end center">
<button mat-stroked-button *ngIf="selectedIndex > 0"
[disabled]="(isLoading$ | async)"
(click)="previousStep()">{{ 'action.back' | translate }}</button>
@ -203,11 +195,10 @@
<div class="dialog-actions-row" fxFlex fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="end center">
<button mat-button
[disabled]="(isLoading$ | async)"
*ngIf="!deviceCredentials"
(click)="cancel()">{{ 'action.cancel' | translate }}</button>
<button mat-raised-button
[disabled]="(isLoading$ | async)"
color="primary"
(click)="add()">{{ (deviceCredentials ? 'action.close': 'action.add') | translate }}</button>
(click)="add()">{{ 'action.add' | translate }}</button>
</div>
</div>

View File

@ -37,10 +37,6 @@
}
:host ::ng-deep {
.commands-container {
padding: 24px;
}
.mat-mdc-dialog-content {
display: flex;
flex-direction: column;

View File

@ -24,8 +24,6 @@ import { Router } from '@angular/router';
import {
createDeviceProfileConfiguration,
createDeviceProfileTransportConfiguration,
Device,
DeviceCredentials,
DeviceProfile,
DeviceProfileInfo,
DeviceProfileType,
@ -59,9 +57,9 @@ import { deepTrim } from '@core/utils';
styleUrls: ['./device-wizard-dialog.component.scss']
})
export class DeviceWizardDialogComponent extends
DialogComponent<DeviceWizardDialogComponent, Device> implements OnDestroy, ErrorStateMatcher {
DialogComponent<DeviceWizardDialogComponent, boolean> implements OnDestroy, ErrorStateMatcher {
@ViewChild('addDeviceWizardStepper') addDeviceWizardStepper: MatStepper;
@ViewChild('addDeviceWizardStepper', {static: true}) addDeviceWizardStepper: MatStepper;
selectedIndex = 0;
@ -71,7 +69,7 @@ export class DeviceWizardDialogComponent extends
entityType = EntityType;
deviceTransportTypes = Object.values(DeviceTransportType) as DeviceTransportType[];
deviceTransportTypes = Object.values(DeviceTransportType);
deviceTransportTypeTranslations = deviceTransportTypeTranslationMap;
@ -93,10 +91,6 @@ export class DeviceWizardDialogComponent extends
serviceType = ServiceType.TB_RULE_ENGINE;
device: Device;
deviceCredentials: DeviceCredentials;
private subscriptions: Subscription[] = [];
private currentDeviceProfileTransportType = DeviceTransportType.DEFAULT;
@ -104,7 +98,7 @@ export class DeviceWizardDialogComponent extends
protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: AddEntityDialogData<BaseData<EntityId>>,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher,
public dialogRef: MatDialogRef<DeviceWizardDialogComponent, Device>,
public dialogRef: MatDialogRef<DeviceWizardDialogComponent, boolean>,
private deviceProfileService: DeviceProfileService,
private deviceService: DeviceService,
private breakpointObserver: BreakpointObserver,
@ -269,15 +263,13 @@ export class DeviceWizardDialogComponent extends
}
add(): void {
if (this.deviceCredentials) {
this.dialogRef.close(this.device);
} else if (this.allValid()) {
if (this.allValid()) {
this.createDeviceProfile().pipe(
mergeMap(profileId => this.createDevice(profileId)),
mergeMap(device => this.saveCredentials(device)),
mergeMap(device => this.saveCredentials(device))
).subscribe(
(device) => {
this.device = device;
(created) => {
this.dialogRef.close(created);
}
);
}
@ -334,7 +326,7 @@ export class DeviceWizardDialogComponent extends
}
}
private createDevice(profileId): Observable<Device> {
private createDevice(profileId): Observable<BaseData<HasId>> {
const device = {
name: this.deviceWizardFormGroup.get('name').value,
label: this.deviceWizardFormGroup.get('label').value,
@ -357,16 +349,15 @@ export class DeviceWizardDialogComponent extends
this.addDeviceWizardStepper.selectedIndex = 0;
return throwError(e);
})
) as Observable<Device>;
);
}
private saveCredentials(device: Device): Observable<Device> {
private saveCredentials(device: BaseData<HasId>): Observable<boolean> {
if (this.credentialsFormGroup.get('setCredential').value) {
return this.deviceService.getDeviceCredentials(device.id.id).pipe(
mergeMap(
(deviceCredentials) => {
const deviceCredentialsValue = {...deviceCredentials, ...this.credentialsFormGroup.value.credential};
this.deviceCredentials = deviceCredentialsValue;
return this.deviceService.saveDeviceCredentials(deviceCredentialsValue).pipe(
catchError(e => {
this.addDeviceWizardStepper.selectedIndex = 1;
@ -379,14 +370,7 @@ export class DeviceWizardDialogComponent extends
);
}
),
map(() => device));
} else {
return this.deviceService.getDeviceCredentials(device.id.id).pipe(
map((deviceCredentials) => {
this.deviceCredentials = deviceCredentials;
return device;
})
);
map(() => true));
}
}