diff --git a/application/src/main/data/json/system/widget_bundles/edge_widgets.json b/application/src/main/data/json/system/widget_bundles/edge_widgets.json index 32047f20a4..6412ff9d99 100644 --- a/application/src/main/data/json/system/widget_bundles/edge_widgets.json +++ b/application/src/main/data/json/system/widget_bundles/edge_widgets.json @@ -7,7 +7,7 @@ "widgetTypes": [ { "alias": "edges_overview", - "name": "Edges Quick Overview", + "name": "Edge Quick Overview", "descriptor": { "type": "latest", "sizeX": 7.5, @@ -15,10 +15,10 @@ "resources": [], "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n};\n\nself.onDestroy = function() {\n};\n", - "settingsSchema": "{}", + "controllerScript": "self.onInit = function() {\n};\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n dataKeysOptional: true\n };\n}\n\nself.onDestroy = function() {\n};\n", + "settingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n", - "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{},\"title\":\"Edges Quick Overview\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"widgetStyle\":{},\"actions\":{}}" + "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"showTitleIcon\":true,\"titleIcon\":\"router\",\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{},\"title\":\"Edge Quick Overview\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"widgetStyle\":{},\"actions\":{}}" } } ] diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java index 30e30080ee..939bfb3648 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java @@ -62,6 +62,7 @@ public class Edge extends SearchTextBasedWithAdditionalInfo implements H this.customerId = edge.getCustomerId(); this.rootRuleChainId = edge.getRootRuleChainId(); this.type = edge.getType(); + this.label = edge.getLabel(); this.name = edge.getName(); this.routingKey = edge.getRoutingKey(); this.secret = edge.getSecret(); diff --git a/ui-ngx/src/app/core/http/edge.service.ts b/ui-ngx/src/app/core/http/edge.service.ts index 4cb7e239d2..7e4974aec4 100644 --- a/ui-ngx/src/app/core/http/edge.service.ts +++ b/ui-ngx/src/app/core/http/edge.service.ts @@ -104,4 +104,8 @@ export class EdgeService { public findMissingToRelatedRuleChains(edgeId: string, config?: RequestConfig): Observable { return this.http.get(`/api/edge/missingToRelatedRuleChains/${edgeId}`, defaultHttpOptionsFromConfig(config)); } + + public findByName(edgeName: string, config?: RequestConfig): Observable { + return this.http.get(`/api/tenant/edges?edgeName=${edgeName}`, defaultHttpOptionsFromConfig(config)); + } } diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts index ac9e6af793..7da7bf61f7 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -45,6 +45,7 @@ import { DataKey, Datasource, DatasourceType, KeyInfo } from '@app/shared/models import { UtilsService } from '@core/services/utils.service'; import { AliasFilterType, EntityAlias, EntityAliasFilter, EntityAliasFilterResult } from '@shared/models/alias.models'; import { + EdgeImportEntityData, EntitiesKeysByQuery, entityFields, EntityInfo, @@ -52,7 +53,7 @@ import { ImportEntityData } from '@shared/models/entity.models'; import { EntityRelationService } from '@core/http/entity-relation.service'; -import { deepClone, isDefined, isDefinedAndNotNull } from '@core/utils'; +import { deepClone, generateSecret, guid, isDefined, isDefinedAndNotNull } from '@core/utils'; import { Asset } from '@shared/models/asset.models'; import { Device, DeviceCredentialsType } from '@shared/models/device.models'; import { AttributeService } from '@core/http/attribute.service'; @@ -76,6 +77,7 @@ import { import { alarmFields } from '@shared/models/alarm.models'; import { EdgeService } from "@core/http/edge.service"; import { RuleChainType } from "@shared/models/rule-chain.models"; +import { Edge } from '@shared/models/edge.models'; @Injectable({ providedIn: 'root' @@ -924,6 +926,51 @@ export class EntityService { public saveEntityParameters(entityType: EntityType, entityData: ImportEntityData, update: boolean, config?: RequestConfig): Observable { + const saveEntityObservable: Observable> = this.getSaveEntityObservable(entityType, entityData, config); + return saveEntityObservable.pipe( + mergeMap((entity) => { + return this.saveEntityData(entity.id, entityData, config).pipe( + map(() => { + return { create: { entity: 1 } } as ImportEntitiesResultInfo; + }), + catchError(err => of({ error: { entity: 1 } } as ImportEntitiesResultInfo)) + ); + }), + catchError(err => { + if (update) { + let findEntityObservable: Observable>; + switch (entityType) { + case EntityType.DEVICE: + findEntityObservable = this.deviceService.findByName(entityData.name, config); + break; + case EntityType.ASSET: + findEntityObservable = this.assetService.findByName(entityData.name, config); + break; + case EntityType.EDGE: + findEntityObservable = this.edgeService.findByName(entityData.name, config); + break; + } + return findEntityObservable.pipe( + mergeMap((entity) => { + const updateEntityTasks: Observable[] = this.getUpdateEntityTasks(entityType, entityData, entity, config); + return forkJoin(updateEntityTasks).pipe( + map(() => { + return { update: { entity: 1 } } as ImportEntitiesResultInfo; + }), + catchError(updateError => of({ error: { entity: 1 } } as ImportEntitiesResultInfo)) + ); + }), + catchError(findErr => of({ error: { entity: 1 } } as ImportEntitiesResultInfo)) + ); + } else { + return of({ error: { entity: 1 } } as ImportEntitiesResultInfo); + } + }) + ); + } + + private getSaveEntityObservable(entityType: EntityType, entityData: ImportEntityData, + config?: RequestConfig): Observable> { let saveEntityObservable: Observable>; switch (entityType) { case EntityType.DEVICE: @@ -954,70 +1001,92 @@ export class EntityService { }; saveEntityObservable = this.assetService.saveAsset(asset, config); break; + case EntityType.EDGE: + const edgeEntityData: EdgeImportEntityData = entityData as EdgeImportEntityData; + const edge: Edge = { + name: edgeEntityData.name, + type: edgeEntityData.type, + label: edgeEntityData.label, + additionalInfo: { + description: edgeEntityData.description + }, + edgeLicenseKey: edgeEntityData.edgeLicenseKey, + cloudEndpoint: edgeEntityData.cloudEndpoint !== '' ? edgeEntityData.cloudEndpoint : window.location.origin, + routingKey: edgeEntityData.routingKey !== '' ? edgeEntityData.routingKey : guid(), + secret: edgeEntityData.secret !== '' ? edgeEntityData.secret : generateSecret(20) + }; + saveEntityObservable = this.edgeService.saveEdge(edge, config); + break; } - return saveEntityObservable.pipe( - mergeMap((entity) => { - return this.saveEntityData(entity.id, entityData, config).pipe( - map(() => { - return { create: { entity: 1 } } as ImportEntitiesResultInfo; - }), - catchError(err => of({ error: { entity: 1 } } as ImportEntitiesResultInfo)) - ); - }), - catchError(err => { - if (update) { - let findEntityObservable: Observable>; - switch (entityType) { + return saveEntityObservable; + + } + + private getUpdateEntityTasks(entityType: EntityType, entityData: ImportEntityData | EdgeImportEntityData, + entity: BaseData, config?: RequestConfig): Observable[] { + const tasks: Observable[] = []; + let result; + let additionalInfo; + switch (entityType) { + case EntityType.ASSET: + case EntityType.DEVICE: + result = entity as (Device | Asset); + additionalInfo = result.additionalInfo || {}; + if (result.label !== entityData.label || + result.type !== entityData.type || + additionalInfo.description !== entityData.description || + (result.id.entityType === EntityType.DEVICE && (additionalInfo.gateway !== entityData.gateway)) ) { + result.label = entityData.label; + result.type = entityData.type; + result.additionalInfo = additionalInfo; + result.additionalInfo.description = entityData.description; + if (result.id.entityType === EntityType.DEVICE) { + result.additionalInfo.gateway = entityData.gateway; + } + switch (result.id.entityType) { case EntityType.DEVICE: - findEntityObservable = this.deviceService.findByName(entityData.name, config); + tasks.push(this.deviceService.saveDevice(result, config)); break; case EntityType.ASSET: - findEntityObservable = this.assetService.findByName(entityData.name, config); + tasks.push(this.assetService.saveAsset(result, config)); break; } - return findEntityObservable.pipe( - mergeMap((entity) => { - const tasks: Observable[] = []; - const result: Device & Asset = entity as (Device | Asset); - const additionalInfo = result.additionalInfo || {}; - if (result.label !== entityData.label || - result.type !== entityData.type || - additionalInfo.description !== entityData.description || - (result.id.entityType === EntityType.DEVICE && (additionalInfo.gateway !== entityData.gateway)) ) { - result.label = entityData.label; - result.type = entityData.type; - result.additionalInfo = additionalInfo; - result.additionalInfo.description = entityData.description; - if (result.id.entityType === EntityType.DEVICE) { - result.additionalInfo.gateway = entityData.gateway; - } - if (result.id.entityType === EntityType.DEVICE && result.deviceProfileId) { - delete result.deviceProfileId; - } - switch (result.id.entityType) { - case EntityType.DEVICE: - tasks.push(this.deviceService.saveDevice(result, config)); - break; - case EntityType.ASSET: - tasks.push(this.assetService.saveAsset(result, config)); - break; - } - } - tasks.push(this.saveEntityData(entity.id, entityData, config)); - return forkJoin(tasks).pipe( - map(() => { - return { update: { entity: 1 } } as ImportEntitiesResultInfo; - }), - catchError(updateError => of({ error: { entity: 1 } } as ImportEntitiesResultInfo)) - ); - }), - catchError(findErr => of({ error: { entity: 1 } } as ImportEntitiesResultInfo)) - ); - } else { - return of({ error: { entity: 1 } } as ImportEntitiesResultInfo); } - }) - ); + tasks.push(this.saveEntityData(entity.id, entityData, config)); + break; + case EntityType.EDGE: + result = entity as Edge; + additionalInfo = result.additionalInfo || {}; + const edgeEntityData: EdgeImportEntityData = entityData as EdgeImportEntityData; + if (result.label !== edgeEntityData.label || + result.type !== edgeEntityData.type || + (edgeEntityData.cloudEndpoint !== '' && result.cloudEndpoint !== edgeEntityData.cloudEndpoint) || + (edgeEntityData.edgeLicenseKey !== '' && result.edgeLicenseKey !== edgeEntityData.edgeLicenseKey) || + (edgeEntityData.routingKey !== '' && result.routingKey !== edgeEntityData.routingKey) || + (edgeEntityData.secret !== '' && result.secret !== edgeEntityData.secret) || + additionalInfo.description !== edgeEntityData.description) { + result.label = edgeEntityData.label; + result.type = edgeEntityData.type; + result.additionalInfo = additionalInfo; + result.additionalInfo.description = edgeEntityData.description; + if (edgeEntityData.cloudEndpoint !== '') { + result.cloudEndpoint = edgeEntityData.cloudEndpoint; + } + if (edgeEntityData.edgeLicenseKey !== '') { + result.edgeLicenseKey = edgeEntityData.edgeLicenseKey; + } + if (edgeEntityData.routingKey !== '') { + result.routingKey = edgeEntityData.routingKey; + } + if (edgeEntityData.secret !== '') { + result.secret = edgeEntityData.secret; + } + tasks.push(this.edgeService.saveEdge(result, config)); + } + tasks.push(this.saveEntityData(entity.id, edgeEntityData, config)); + break; + } + return tasks; } public saveEntityData(entityId: EntityId, entityData: ImportEntityData, config?: RequestConfig): Observable { diff --git a/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-config.ts b/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-config.ts index 2db23eeb97..64bac0313f 100644 --- a/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/edge/edge-downlink-table-config.ts @@ -222,9 +222,9 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig[] = []; for (let i = 0; i < partSize; i++) { - const importEntityPromise = - this.entityService.saveEntityParameters(entityType, entitiesData[i], updateData, config).pipe( + let saveEntityPromise: Observable; + saveEntityPromise = this.entityService.saveEntityParameters(entityType, entitiesData[i], updateData, config); + const importEntityPromise = saveEntityPromise.pipe( tap((res) => { if (importEntityCompleted) { importEntityCompleted(); @@ -411,7 +407,7 @@ export class ImportExportService { throw new Error('Invalid rule chain file'); } else if (ruleChainImport.ruleChain.type !== expectedRuleChainType) { this.store.dispatch(new ActionNotificationShow( - {message: this.translate.instant('rulechain.invalid-rulechain-type-error', { expectedRuleChainType: expectedRuleChainType }), + {message: this.translate.instant('rulechain.invalid-rulechain-type-error', {expectedRuleChainType}), type: 'error'})); throw new Error('Invalid rule chain type'); } else { @@ -603,7 +599,7 @@ export class ImportExportService { private editMissingAliases(widgets: Array, isSingleWidget: boolean, customTitle: string, missingEntityAliases: EntityAliases): Observable { - let allowedEntityTypes: Array = + const allowedEntityTypes: Array = this.entityService.prepareAllowedEntityTypesList(null, true); return this.dialog.open { diff --git a/ui-ngx/src/app/modules/home/components/import-export/table-columns-assignment.component.ts b/ui-ngx/src/app/modules/home/components/import-export/table-columns-assignment.component.ts index 157259fbf3..6f0bd04fcc 100644 --- a/ui-ngx/src/app/modules/home/components/import-export/table-columns-assignment.component.ts +++ b/ui-ngx/src/app/modules/home/components/import-export/table-columns-assignment.component.ts @@ -93,6 +93,14 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce { value: ImportEntityColumnType.timeseries } ); break; + case EntityType.EDGE: + this.columnTypes.push( + { value: ImportEntityColumnType.edgeLicenseKey }, + { value: ImportEntityColumnType.cloudEndpoint }, + { value: ImportEntityColumnType.routingKey }, + { value: ImportEntityColumnType.secret } + ); + break; } } @@ -118,6 +126,10 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce const isSelectCredentials = this.columns.findIndex((column) => column.type === ImportEntityColumnType.accessToken) > -1; const isSelectGateway = this.columns.findIndex((column) => column.type === ImportEntityColumnType.isGateway) > -1; const isSelectDescription = this.columns.findIndex((column) => column.type === ImportEntityColumnType.description) > -1; + const isSelectEdgeLicenseKey = this.columns.findIndex((column) => column.type === ImportEntityColumnType.edgeLicenseKey) > -1; + const isSelectCloudEndpoint = this.columns.findIndex((column) => column.type === ImportEntityColumnType.cloudEndpoint) > -1; + const isSelectRoutingKey = this.columns.findIndex((column) => column.type === ImportEntityColumnType.routingKey) > -1; + const isSelectSecret = this.columns.findIndex((column) => column.type === ImportEntityColumnType.secret) > -1; const hasInvalidColumn = this.columns.findIndex((column) => !this.columnValid(column)) > -1; this.valid = isSelectName && isSelectType && !hasInvalidColumn; @@ -135,6 +147,22 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce if (accessTokenColumnType) { accessTokenColumnType.disabled = isSelectCredentials; } + const edgeLicenseKeyColumnType = this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.edgeLicenseKey); + if (edgeLicenseKeyColumnType) { + edgeLicenseKeyColumnType.disabled = isSelectEdgeLicenseKey; + } + const cloudEndpointColumnType = this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.cloudEndpoint); + if (cloudEndpointColumnType) { + cloudEndpointColumnType.disabled = isSelectCloudEndpoint; + } + const routingKeyColumnType = this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.routingKey); + if (routingKeyColumnType) { + routingKeyColumnType.disabled = isSelectRoutingKey; + } + const secretColumnType = this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.secret); + if (secretColumnType) { + secretColumnType.disabled = isSelectSecret; + } if (this.propagateChange) { this.propagateChange(this.columns); } else { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.ts index ed9e6fd559..657cc92efe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.ts @@ -87,7 +87,7 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni if (datasource.type === DatasourceType.entity && datasource.entity.id.entityType === EntityType.EDGE) { var selectedEdge: BaseData = datasource.entity; this.getCustomerTitle(selectedEdge.id.id); - this.ctx.widgetTitle = selectedEdge.name; + this.ctx.widgetTitle = `${selectedEdge.name} Quick Overview`; cb(this.loadNodesForEdge(selectedEdge.id.id, selectedEdge)); } else if (datasource.type === DatasourceType.function) { cb(this.loadNodesForEdge(datasource.entityId, datasource.entity)); diff --git a/ui-ngx/src/app/modules/home/dialogs/home-dialogs.service.ts b/ui-ngx/src/app/modules/home/dialogs/home-dialogs.service.ts index 69b183bb3f..fc7fd73384 100644 --- a/ui-ngx/src/app/modules/home/dialogs/home-dialogs.service.ts +++ b/ui-ngx/src/app/modules/home/dialogs/home-dialogs.service.ts @@ -36,6 +36,8 @@ export class HomeDialogsService { return this.openImportDialogCSV(entityType, 'device.import', 'device.device-file'); case EntityType.ASSET: return this.openImportDialogCSV(entityType, 'asset.import', 'asset.asset-file'); + case EntityType.EDGE: + return this.openImportDialogCSV(entityType, 'edge.import', 'edge.edge-file'); } } diff --git a/ui-ngx/src/app/modules/home/pages/customer/customer.component.html b/ui-ngx/src/app/modules/home/pages/customer/customer.component.html index c8c109ece0..9c37b567b2 100644 --- a/ui-ngx/src/app/modules/home/pages/customer/customer.component.html +++ b/ui-ngx/src/app/modules/home/pages/customer/customer.component.html @@ -43,7 +43,8 @@ @@ -85,7 +85,7 @@ ngxClipboard (cbOnSuccess)="onEdgeInfoCopied('key')" [cbContent]="entity?.routingKey" - [fxShow]="!isEdit && edgeScope === 'tenant'"> + [fxShow]="!isEdit && (edgeScope === 'tenant' || edgeScope === 'customer')"> edge.copy-edge-key @@ -93,7 +93,7 @@ ngxClipboard (cbOnSuccess)="onEdgeInfoCopied('secret')" [cbContent]="entity?.secret" - [fxShow]="!isEdit && edgeScope === 'tenant'"> + [fxShow]="!isEdit && (edgeScope === 'tenant' || edgeScope === 'customer')"> edge.copy-edge-secret @@ -101,7 +101,7 @@ ngxClipboard [disabled]="(isLoading$ | async)" (click)="onEntityAction($event, 'syncEdge')" - [fxShow]="!isEdit && edgeScope === 'tenant'"> + [fxShow]="!isEdit && (edgeScope === 'tenant' || edgeScope === 'customer')"> edge.sync @@ -111,12 +111,12 @@ - edge.assigned-to-customer + edge.assignedToCustomer
- {{ 'edge.public' | translate }} + [fxShow]="!isEdit && entity?.customerIsPublic && edgeScope === 'tenant'"> + {{ 'edge.edge-public' | translate }}
@@ -132,7 +132,7 @@ [required]="true" [entityType]="entityType.EDGE"> -
+
edge.edge-license-key @@ -142,7 +142,7 @@
-
+
edge.cloud-endpoint-hint
edge.cloud-endpoint @@ -153,7 +153,7 @@
-
+
edge.edge-key @@ -164,7 +164,7 @@
-
+
edge.edge-secret diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge.component.ts b/ui-ngx/src/app/modules/home/pages/edge/edge.component.ts index 57ed06cef0..757d012642 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edge.component.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edge.component.ts @@ -26,7 +26,6 @@ import { NULL_UUID } from '@shared/models/id/has-uuid'; import { ActionNotificationShow } from '@core/notification/notification.actions'; import { generateSecret, guid } from '@core/utils'; import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; -import { WINDOW } from '@core/services/window.service'; @Component({ selector: 'tb-edge', @@ -43,15 +42,14 @@ export class EdgeComponent extends EntityComponent { protected translate: TranslateService, @Inject('entity') protected entityValue: EdgeInfo, @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig, - public fb: FormBuilder, - @Inject(WINDOW) protected window: Window) { + public fb: FormBuilder) { super(store, fb, entityValue, entitiesTableConfigValue); } ngOnInit() { this.edgeScope = this.entitiesTableConfig.componentsData.edgeScope; this.entityForm.patchValue({ - cloudEndpoint: this.window.location.origin + cloudEndpoint: window.location.origin }); super.ngOnInit(); } @@ -94,7 +92,7 @@ export class EdgeComponent extends EntityComponent { name: entity.name, type: entity.type, label: entity.label, - cloudEndpoint: entity.cloudEndpoint ? entity.cloudEndpoint : this.window.location.origin, + cloudEndpoint: entity.cloudEndpoint ? entity.cloudEndpoint : window.location.origin, edgeLicenseKey: entity.edgeLicenseKey, routingKey: entity.routingKey, secret: entity.secret, diff --git a/ui-ngx/src/app/shared/models/entity.models.ts b/ui-ngx/src/app/shared/models/entity.models.ts index ae3fa30f17..00b21d8961 100644 --- a/ui-ngx/src/app/shared/models/entity.models.ts +++ b/ui-ngx/src/app/shared/models/entity.models.ts @@ -45,6 +45,13 @@ export interface ImportEntityData { timeseries: AttributeData[]; } +export interface EdgeImportEntityData extends ImportEntityData { + secret: string; + routingKey: string; + cloudEndpoint: string; + edgeLicenseKey: string; +} + export interface ImportEntitiesResultInfo { create?: { entity: number; diff --git a/ui-ngx/src/assets/locale/locale.constant-de_DE.json b/ui-ngx/src/assets/locale/locale.constant-de_DE.json index 541bf1469f..289bbaa0be 100644 --- a/ui-ngx/src/assets/locale/locale.constant-de_DE.json +++ b/ui-ngx/src/assets/locale/locale.constant-de_DE.json @@ -731,7 +731,6 @@ "no-edges-matching": "Keine passenden Rand '{{entity}}' gefunden.", "rulechain-templates": "Regelkettenvorlagen", "add": "Rand hinzufügen", - "view": "Rand anzeigen", "no-edges-text": "Kein Rand gefunden.", "edge-details": "Details der Rand", "add-edge-text": "Neue Rand hinzufügen", @@ -754,7 +753,6 @@ "id-copied-message": "Regelketten-ID wurde in die Zwischenablage kopiert", "sync": "Sync Edge", "sync-message": "Edge wurde synchronisiert", - "permissions": "Berechtigungen", "edge-required": "Rand ist erforderlich.", "edge-type": "Randtyp", "edge-type-required": "Randtyp ist erforderlich.", @@ -777,14 +775,12 @@ "make-private-edge-text": "Nach der Bestätigung werden der Rand und dessen Daten privat und sind für andere nicht mehr zugänglich.", "import": "Rand importieren", "label": "Bezeichnung", - "assign-to-edge": "Assign to edge", "assign-new-edge": "Neue Rand zuordnen", "manage-edge-dashboards": "Rand-Dashboards verwalten", "unassign-from-edge": "Rand zuweisen", "dashboards": "Rand Dashboards", "manage-edge-rulechains": "Randregelkette verwalten", "rulechains": "Rand Regelketten", - "rulechain": "Rand Regelkette", "edge-key": "Rand Schlüssel", "copy-edge-key": "Rand Schlüssel kopieren", "edge-key-copied-message": "Rand Schlüssel wurde in die Zwischenablage kopiert", @@ -797,18 +793,85 @@ "assets": "Rand Objekte", "devices": "Objekte Geräte", "entity-views": "Objekte Entitätsansichten", - "set-root-rulechain-text": "Bitte wählen Sie die Regelkette zur Wurzel rule chain für die Rand", - "set-root-rulechain-to-edges": "Regelkette zur Wurzel machen für die Rand", - "set-root-rulechain-to-edges-text": "Die Regelkette zur Wurzel für { count, plural, 1 {1 Rand} other {# Rand} } machen", - "status": "Von Rand empfangen", - "success": "Bereitgestellt", - "failed": "Steht aus", "entity-id": "Entität ID", - "entity-info": "Entitätsinfo", "event-action": "Ereignisaktion", "load-entity-error": "Entität nicht gefunden. Fehler beim Laden der Informationen", "unassign-edges-text": "Nach der Bestätigung werden alle ausgewählten Kanten nicht zugewiesen und sind für den Kunden nicht zugänglich.", - "unassign-edges-title": "Sind Sie sicher, dass Sie die Zuordnung aufheben möchten { count, plural, 1 {1 Rand} other {# Rand} }?" + "unassign-edges-title": "Sind Sie sicher, dass Sie die Zuordnung aufheben möchten { count, plural, 1 {1 Rand} other {# Rand} }?", + "edge-rulechains": "Kantenregelketten", + "edge-license-key-hint": "Um Ihre Lizenz zu erhalten, navigieren Sie zur Preisseite und wählen Sie die beste Lizenzoption für Ihre aus Fall.", + "assignedToCustomer": "Dem Kunden zugewiesen", + "edge-public": "Edge ist öffentlich", + "search": "Kanten durchsuchen", + "selected-edges": "{Anzahl, Plural, 1 {1 Kante} andere {# Kanten}} ausgewählt", + "any-edge": "Beliebige Kante", + "dashboard": "Kanten-Dashboard", + "sync-process-started-successfully": "Synchronisierungsprozess erfolgreich gestartet!", + "delete-edges-action-title": "Löschen { count, plural, 1 {1 Rand} other {# Rand} }", + "set-root-rule-chain-text": "Bitte wählen Sie die Regelkette zur Wurzel rule chain für die Rand", + "set-root-rule-chain-to-edges": "Regelkette zur Wurzel machen für die Rand", + "set-root-rule-chain-to-edges-text": "Die Regelkette zur Wurzel für { count, plural, 1 {1 Rand} other {# Rand} } machen", + "status": "Von Rand empfangen", + "deployed": "Bereitgestellt", + "pending": "Steht aus", + "edge-file": "Edge-Datei", + "name-starts-with": "Der Kantenname beginnt mit", + "rulechain-template": "Regelkettenvorlage", + "unassign-edges-action-title": "Heben Sie die Zuordnung von {count, plural, 1 {1 edge} other {# edge}} vom Kunden auf", + "enter-edge-type": "Geben Sie den Kantentyp ein", + "no-edge-types-matching": "Es wurden keine Kantentypen gefunden, die mit '{{entitySubtype}}' übereinstimmen.", + "edge-type-list-empty": "Keine Kantentypen ausgewählt.", + "edge-types": "Kantentypen", + "license-key-hint": "Um Ihre Lizenz zu erhalten, navigieren Sie zur Preisseite und wählen Sie die beste Lizenzoption für Ihre aus Fall.", + "cloud-endpoint-hint": "Edge erfordert HTTP-Zugriff auf die Cloud (ThingsBoard CE / PE), um den Lizenzschlüssel zu überprüfen. Bitte geben Sie die Cloud-URL an, zu der Edge eine Verbindung herstellen kann.", + "missing-related-rule-chains-title": "In Edge fehlen verwandte Regelketten.", + "missing-related-rule-chains-text": "Randregelkette (n) zugewiesen Verwenden Sie Regelknoten, die Nachrichten an Regelkette (n) weiterleiten, die dieser Kante nicht zugeordnet sind.

Liste der fehlenden Regelketten:
{{missingRuleChains}}", + "downlinks": "Downlinks", + "no-downlinks-prompt": "Keine Downlinks gefunden", + "assigned-to-customer-widget": "Zugewiesen an: {{customerTitle}}", + "widget-datasource-error": "Dieses Widget unterstützt nur EDGE-Entitätsdatenquellen" + }, + "edge-event": { + "type-dashboard": "Dashboard", + "type-asset": "Asset", + "type-device": "Device", + "type-device-profile": "Device Profile", + "type-entity-view": "Entity View", + "type-alarm": "Alarm", + "type-rule-chain": "Rule Chain", + "type-rule-chain-metadata": "Rule Chain Metadata", + "type-edge": "Edge", + "type-entity-group": "Entity Group", + "type-scheduler-event": "Scheduler Event", + "type-white-labeling": "White Labeling", + "type-login-white-labeling": "White Labeling Login", + "type-user": "User", + "type-tenant": "Tenant", + "type-customer": "Customer", + "type-custom-translation": "Custom Translation", + "type-relation": "Relation", + "type-widgets-bundle": "Widgets Bundle", + "type-widgets-type": "Widgets Type", + "type-admin-settings": "Admin Settings", + "action-type-added": "Added", + "action-type-deleted": "Deleted", + "action-type-updated": "Updated", + "action-type-post-attributes": "Post Attributes", + "action-type-attributes-updated": "Attributes Updated", + "action-type-attributes-deleted": "Attributes Deleted", + "action-type-timeseries-updated": "Timeseries Updated", + "action-type-credentials-updated": "Credentials Updated", + "action-type-assigned-to-customer": "Assigned to Customer", + "action-type-unassigned-from-customer": "Unassigned from Customer", + "action-type-relation-add-or-update": "Relation Add or Update", + "action-type-relation-deleted": "Relation Deleted", + "action-type-rpc-call": "RPC Call", + "action-type-alarm-ack": "Alarm Ack", + "action-type-alarm-clear": "Alarm Clear", + "action-type-assigned-to-edge": "Assigned to Edge", + "action-type-unassigned-from-edge": "Unassigned from Edge", + "action-type-credentials-request": "Credentials Request", + "action-type-entity-merge-request": "Entity Merge Request" }, "error": { "unable-to-connect": "Es konnte keine Verbindung zum Server hergestellt werden! Bitte überprüfen Sie Ihre Internetverbindung.", @@ -1405,7 +1468,12 @@ "unset-auto-assign-to-edge": "Deaktiviert die Zuordnung der Regelkette zu Kanten bei der Erstellung", "unset-auto-assign-to-edge-title": "Möchten Sie die Kantenregelkette '{{ruleChainName}}' bei der Erstellung unbedingt den Kanten zuweisen?", "unset-auto-assign-to-edge-text": "Nach der Bestätigung wird die Kantenregelkette bei der Erstellung nicht mehr automatisch den Kanten zugewiesen.", - "edge-template-root": "Vorlagenstamm" + "edge-template-root": "Vorlagenstamm", + "search": "Suchen Sie nach Regelketten", + "selected-rulechains": "{count, plural, 1 {1 Regelkette} andere {# Regelketten}} ausgewählt", + "open-rulechain": "Regelkette öffnen", + "assign-to-edge": "Rand zuweisen", + "edge-rulechain": "Kantenregelkette" }, "rulenode": { "details": "Details", diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 06da3ceacc..1b5331bf2a 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -629,7 +629,8 @@ "default-customer-required": "Default customer is required in order to debug dashboard on Tenant level", "search": "Search customers", "selected-customers": "{ count, plural, 1 {1 customer} other {# customers} } selected", - "edges": "Customer edge instances" + "edges": "Customer edge instances", + "manage-edges": "Manage edges" }, "datetime": { "date-from": "Date from", @@ -1197,7 +1198,6 @@ "rulechains": "Rule chains", "edge-rulechains": "Edge Rule chains", "add": "Add Edge", - "view": "View Edge", "no-edges-text": "No edges found", "edge-details": "Edge details", "add-edge-text": "Add new edge", @@ -1217,14 +1217,12 @@ "cloud-endpoint-required": "Cloud Endpoint is required.", "cloud-endpoint-hint": "Edge requires HTTP(s) access to Cloud (ThingsBoard CE/PE) to verify the license key. Please specify Cloud URL that Edge is able to connect to.", "description": "Description", - "entity-info": "Entity info", "details": "Details", "events": "Events", "copy-id": "Copy Edge Id", "id-copied-message": "Edge Id has been copied to clipboard", "sync": "Sync Edge", "sync-message": "Edge has been synchronized", - "permissions": "Permissions", "edge-required": "Edge required", "edge-type": "Edge type", "edge-type-required": "Edge type is required.", @@ -1235,6 +1233,8 @@ "assign-to-customer-text": "Please select the customer to assign the edge(s)", "assign-edge-to-customer": "Assign Edge(s) To Customer", "assign-edge-to-customer-text": "Please select the edges to assign to the customer", + "assignedToCustomer": "Assigned to customer", + "edge-public": "Edge is public", "assigned-to-customer": "Assigned to: {{customerTitle}}", "unassign-from-customer": "Unassign from customer", "assign-edges-text": "Assign { count, plural, 1 {1 edge} other {# edges} } to customer", @@ -1273,9 +1273,6 @@ "set-root-rule-chain-text": "Please select root rule chain for edge(s)", "set-root-rule-chain-to-edges": "Set root rule chain for Edge(s)", "set-root-rule-chain-to-edges-text": "Set root rule chain for { count, plural, 1 {1 edge} other {# edges} }", - "status": "Received by edge", - "success": "Deployed", - "failed": "Pending", "search": "Search edges", "selected-edges": "{ count, plural, 1 {1 edge} other {# edges} } selected", "any-edge": "Any edge", @@ -1581,7 +1578,6 @@ "type-stats": "Statistics", "type-debug-rule-node": "Debug", "type-debug-rule-chain": "Debug", - "type-edge-event": "Downlink", "no-events-prompt": "No events found", "error": "Error", "alarm": "Alarm", @@ -1981,9 +1977,9 @@ "access-token": "Access token", "isgateway": "Is Gateway", "description": "Description", - "edgeLicenseKey": "License Key", - "cloudEndpoint": "Cloud Endpoint", - "routingKey": "Edge key", + "edge-license-key": "License Key", + "cloud-endpoint": "Cloud Endpoint", + "routing-key": "Edge key", "secret": "Edge secret" }, "stepper-text":{ diff --git a/ui-ngx/src/assets/locale/locale.constant-es_ES.json b/ui-ngx/src/assets/locale/locale.constant-es_ES.json index 125e6cf4b1..f56cd60989 100644 --- a/ui-ngx/src/assets/locale/locale.constant-es_ES.json +++ b/ui-ngx/src/assets/locale/locale.constant-es_ES.json @@ -753,7 +753,6 @@ "no-edges-matching": "No se encontraron bordes que coincidan con '{{entity}}'", "rulechain-templates": "Plantillas, de cadena de reglas", "add": "Agregar borde", - "view": "Ver borde", "no-edges-text": "No se encontraron bordes", "edge-details": "Detalles del borde", "add-edge-text": "Agregar nuevo borde", @@ -776,12 +775,10 @@ "id-copied-message": "El ID de borde se ha copiado al portapapeles", "sync": "Sinc Edge", "sync-message": "Edge se ha sincronizado", - "permissions": "Permisos", "edge-required": "Edge required", "edge-type": "Type de la bordure", "edge-type-required": "El tipo de borde es requerido.", "select-edge-type": "Seleccionar tipo de borde", - "assign-to-edge": "Asignar al borde", "assign-to-customer": "Asignar al cliente", "assign-to-customer-text": "Seleccione el cliente para asignar los bordes", "assign-edge-to-customer": "Asignar borde(s) al cliente", @@ -806,7 +803,6 @@ "dashboards": "Paneles de borde", "manage-edge-rulechains": "Administrar cadenas de reglas de borde", "rulechains": "Cadenas de regla de borde", - "rulechain": "Cadena de regla de borde", "edge-key": "Clave de borde", "copy-edge-key": "Copiar clave de borde", "edge-key-copied-message": "La clave de borde se ha copiado al portapapeles", @@ -819,18 +815,83 @@ "assets": "Activos de borde", "devices": "Dispositivos de borde", "entity-views": "Vistas de entidad de borde", - "set-root-rulechain-text": "Seleccione la cadena de reglas raíz para los bordes", - "set-root-rulechain-to-edges": "Establecer la cadena de reglas raíz para Edge (s)", - "set-root-rulechain-to-edges-text": "Establecer la cadena de la regla raíz para {count, plural, 1 {1 borde} other {# bordes}}", - "status": "Recibido por borde", - "success": "Desplegada", - "failed": "Pendiente", "entity-id": "ID de entidad", - "entity-info": "Entity info", "event-action": "Información de la entidad", "load-entity-error": "Entidad no encontrada. No se pudo cargar la información", "unassign-edges-text": "Después de la confirmación de todos los bordes seleccionados, se anulará la asignación y el cliente no podrá acceder a ellos.", - "unassign-edges-title": "¿Está seguro de que desea anular la asignación de {count, plural, 1 {1 borde} other {# bordes}}?" + "unassign-edges-title": "¿Está seguro de que desea anular la asignación de {count, plural, 1 {1 borde} other {# bordes}}?", + "edge-rulechains": "Cadenas de reglas de borde", + "edge-license-key-hint": "Para obtener su licencia, vaya a la página de precios y seleccione la mejor opción de licencia para su caso.", + "assignedToCustomer": "Asignada a la cliente", + "edge-public": "Edge es pública", + "set-root-rule-chain-text": "Seleccione la cadena de reglas raíz para los bordes", + "set-root-rule-chain-to-edges": "Establecer cadena de reglas raíz para Edge (s)", + "set-root-rule-chain-to-edges-text": "Establecer cadena de reglas raíz para {count, plural, 1 {1 edge} other {# ends}}", + "search": "Bordes de búsqueda", + "selected-edges": "{count, plural, 1 {1 borde} other {# bordes}} seleccionados", + "any-edge": "Cualquier bordee", + "dashboard": "Panel de control Edge", + "deployed": "Desplegada", + "pending": "Pending", + "sync-process-started-successfully": "¡El proceso de sincronización se inició correctamente!", + "edge-file": "Archivo de borde", + "name-starts-with": "Edge name starts with", + "rulechain-template": "Plantilla de cadena de reglas", + "unassign-edges-action-title": "Anular la asignación de {count, plural, 1 {1 borde} other {# bordes}} del cliente", + "enter-edge-type": "Ingrese el tipo de borde", + "no-edge-types-matching": "No se encontraron tipos de aristas que coincidan con '{{entitySubtype}}'.", + "edge-type-list-empty": "No se seleccionó ningún tipo de borde.", + "edge-types": "Tipos de bordes", + "license-key-hint": "Para obtener su licencia, vaya a la página de precios y seleccione la mejor opción de licencia para su caso.", + "cloud-endpoint-hint": "Edge requiere acceso HTTP (s) a la nube (ThingsBoard CE / PE) para verificar la clave de licencia. Especifique la URL de la nube a la que Edge puede conectarse.", + "missing-related-rule-chains-title": "Al borde le faltan cadenas de reglas relacionadas", + "missing-related-rule-chains-text": "Asignado a la (s) cadena (s) de reglas de borde usa nodos de reglas que reenvían mensajes a cadenas de reglas que no están asignadas a este borde.

Lista de cadenas de reglas faltantes:
{{missingRuleChains}}", + "downlinks": "Enlaces descendentes", + "no-downlinks-prompt": "No se encontraron enlaces descendentes", + "assigned-to-customer-widget": "Asignado a: {{customerTitle}}", + "widget-datasource-error": "Este widget solo admite la fuente de datos de la entidad EDGE" + }, + "edge-event": { + "type-dashboard": "Dashboard", + "type-asset": "Asset", + "type-device": "Device", + "type-device-profile": "Device Profile", + "type-entity-view": "Entity View", + "type-alarm": "Alarm", + "type-rule-chain": "Rule Chain", + "type-rule-chain-metadata": "Rule Chain Metadata", + "type-edge": "Edge", + "type-entity-group": "Entity Group", + "type-scheduler-event": "Scheduler Event", + "type-white-labeling": "White Labeling", + "type-login-white-labeling": "White Labeling Login", + "type-user": "User", + "type-tenant": "Tenant", + "type-customer": "Customer", + "type-custom-translation": "Custom Translation", + "type-relation": "Relation", + "type-widgets-bundle": "Widgets Bundle", + "type-widgets-type": "Widgets Type", + "type-admin-settings": "Admin Settings", + "action-type-added": "Added", + "action-type-deleted": "Deleted", + "action-type-updated": "Updated", + "action-type-post-attributes": "Post Attributes", + "action-type-attributes-updated": "Attributes Updated", + "action-type-attributes-deleted": "Attributes Deleted", + "action-type-timeseries-updated": "Timeseries Updated", + "action-type-credentials-updated": "Credentials Updated", + "action-type-assigned-to-customer": "Assigned to Customer", + "action-type-unassigned-from-customer": "Unassigned from Customer", + "action-type-relation-add-or-update": "Relation Add or Update", + "action-type-relation-deleted": "Relation Deleted", + "action-type-rpc-call": "RPC Call", + "action-type-alarm-ack": "Alarm Ack", + "action-type-alarm-clear": "Alarm Clear", + "action-type-assigned-to-edge": "Assigned to Edge", + "action-type-unassigned-from-edge": "Unassigned from Edge", + "action-type-credentials-request": "Credentials Request", + "action-type-entity-merge-request": "Entity Merge Request" }, "error": { "unable-to-connect": "Imposible conectar con el servidor! Por favor, revise su conexión a internet.", @@ -1576,7 +1637,12 @@ "unset-auto-assign-to-edge": "Desmarcar asignar cadena de reglas a los bordes en la creación", "unset-auto-assign-to-edge-title": "¿Está seguro de que desea anular la asignación de la cadena de reglas de borde '{{ruleChainName}}' a los bordes en la creación?", "unset-auto-assign-to-edge-text": "Después de la confirmación, la cadena de reglas de borde ya no se asignará automáticamente a los bordes en la creación.", - "edge-template-root": "Raíz de plantilla" + "edge-template-root": "Raíz de plantilla", + "search": "Cadenas de reglas de búsqueda", + "selected-rulechains": "{count, plural, 1 {1 cadena de reglas} otras {# cadenas de reglas}} seleccionadas", + "open-rulechain": "Cadena de reglas abierta", + "assign-to-edge": "Asignar a Edge", + "edge-rulechain": "Cadena de regla de borde" }, "rulenode": { "details": "Detalles", diff --git a/ui-ngx/src/assets/locale/locale.constant-fr_FR.json b/ui-ngx/src/assets/locale/locale.constant-fr_FR.json index b16ffe3268..074042d65b 100644 --- a/ui-ngx/src/assets/locale/locale.constant-fr_FR.json +++ b/ui-ngx/src/assets/locale/locale.constant-fr_FR.json @@ -749,7 +749,6 @@ "no-edges-matching": "Aucun bordure correspondant à {{entity}} n'a été trouvé.", "rulechain-templates": "Modèles de chaîne de règles", "add": "Ajouter un bordure", - "view": "Afficher la bordure", "no-edges-text": "Aucun bordure trouvé", "edge-details": "Détails de la bordure", "add-edge-text": "Ajouter une nouveau bordure", @@ -772,12 +771,10 @@ "id-copied-message": "Id de la bordure a été copié dans le presse-papier", "sync": "Sync Edge", "sync-message": "Edge a été synchronisé", - "permissions": "Autorisations", "edge-required": "Bordure est requise", "edge-type": "Type de la bordure", "edge-type-required": "Type de la bordure est requise.", "select-edge-type": "Selectionner un type de la bordure", - "assign-to-edge": "Attribuer au bord", "assign-to-customer": "Attribuer au client", "assign-to-customer-text": "Veuillez sélectionner la bordure pour attribuer le ou les dispositifs", "assign-edge-to-customer": "Attribuer la bordure au client", @@ -802,7 +799,6 @@ "dashboards": "Tableau de bord de la bordure", "manage-edge-rulechains": "Gérer les chaînes de règles", "rulechains": "Chaînes de règles de la bordure", - "rulechain": "Chaîne de règles de la bordure", "edge-key": "Clé de la bordure", "copy-edge-key": "Copier clé de la bordure", "edge-key-copied-message": "Clé de la bordure a été copié dans le presse-papier", @@ -815,18 +811,79 @@ "assets": "Actifs de la bordure", "devices": "Dispositifs de la bordure", "entity-views": "Vues de l'entité bordure", - "set-root-rulechain-text": "Veuillez sélectionner la chaîne de règles racine pour les bordure(s)", - "set-rootrule-chain-to-edges": "Définir la chaîne de règles racine pour bordure(s)", - "set-root-rulechain-to-edges-text": "Définir la chaîne de règles racine pour {count, plural, 1 {1 bordure} other {# bordures} }", - "status": "Reçu par bord", - "success": "Déployée", - "failed": "En attente", "entity-id": "ID d'entité", - "entity-info": "Informations sur l'entité", "event-action": "Action d'événement", "load-entity-error": "Entité introuvable. Échec du chargement des informations", "unassign-edges-text": "Après la confirmation, tous les bordures sélectionnés ne seront plus attribués et ne seront pas accessibles par le client.", - "unassign-edges-title": "Voulez-vous vraiment annuler l'attribution de {count, plural, 1 {1 bordure} other {# bordures}}?" + "unassign-edges-title": "Voulez-vous vraiment annuler l'attribution de {count, plural, 1 {1 bordure} other {# bordures}}?", + "edge-file": "Fichier Edge", + "edge-rulechains": "Chaînes de règles Edge", + "name-starts-with": "Le nom du bord commence par", + "edge-license-key-hint": "Pour obtenir votre licence, accédez à la page de tarification and select the best license option for your case.", + "cloud-endpoint-hint": "Edge nécessite un accès HTTP (s) au Cloud (ThingsBoard CE / PE) pour vérifier la clé de licence. Veuillez spécifier l'URL du cloud à laquelle Edge peut se connecter.", + "assignedToCustomer": "Attribué au client", + "edge-public": "Edge est public", + "set-root-rule-chain-text": "Veuillez sélectionner la chaîne de règles racine pour les arêtes", + "set-root-rule-chain-to-edges": "Définir la chaîne de règles racine pour Edge (s)", + "set-root-rule-chain-to-edges-text": "Définir la chaîne de règles racine pour {count, plural, 1 {1 edge} other {# edges}}", + "search": "Rechercher les bords", + "selected-edges": "{count, plural, 1 {1 edge} other {# bords}} sélectionné", + "any-edge": "Tout bord", + "no-edge-types-matching": "Aucun type d'arête correspondant à \"{{entitySubtype}}\" n'a été trouvé.", + "edge-type-list-empty": "Aucun type d'arête sélectionné.", + "edge-types": "Types de bords", + "dashboard": "Tableau de bord Edge", + "enter-edge-type": "Entrez le type d'arête", + "deployed": "Déployé", + "pending": "En attente", + "downlinks": "Liens descendants", + "no-downlinks-prompt": "Aucun lien descendant trouvé", + "sync-process-started-successfully": "Le processus de synchronisation a démarré avec succès!", + "missing-related-rule-chains-title": "Edge n'a pas de chaîne (s) de règles associées", + "missing-related-rule-chains-text": "Les chaînes de règles affectées aux tronçons utilisent des nœuds de règles qui transfèrent les messages vers les chaînes de règles non affectées à ce tronçon.

Liste des chaînes de règles manquantes:
{{missingRuleChains}}", + "widget-datasource-error": "Ce widget prend en charge uniquement la source de données d'entité EDGE" + }, + "edge-event": { + "type-dashboard": "Dashboard", + "type-asset": "Asset", + "type-device": "Device", + "type-device-profile": "Device Profile", + "type-entity-view": "Entity View", + "type-alarm": "Alarm", + "type-rule-chain": "Rule Chain", + "type-rule-chain-metadata": "Rule Chain Metadata", + "type-edge": "Edge", + "type-entity-group": "Entity Group", + "type-scheduler-event": "Scheduler Event", + "type-white-labeling": "White Labeling", + "type-login-white-labeling": "White Labeling Login", + "type-user": "User", + "type-tenant": "Tenant", + "type-customer": "Customer", + "type-custom-translation": "Custom Translation", + "type-relation": "Relation", + "type-widgets-bundle": "Widgets Bundle", + "type-widgets-type": "Widgets Type", + "type-admin-settings": "Admin Settings", + "action-type-added": "Added", + "action-type-deleted": "Deleted", + "action-type-updated": "Updated", + "action-type-post-attributes": "Post Attributes", + "action-type-attributes-updated": "Attributes Updated", + "action-type-attributes-deleted": "Attributes Deleted", + "action-type-timeseries-updated": "Timeseries Updated", + "action-type-credentials-updated": "Credentials Updated", + "action-type-assigned-to-customer": "Assigned to Customer", + "action-type-unassigned-from-customer": "Unassigned from Customer", + "action-type-relation-add-or-update": "Relation Add or Update", + "action-type-relation-deleted": "Relation Deleted", + "action-type-rpc-call": "RPC Call", + "action-type-alarm-ack": "Alarm Ack", + "action-type-alarm-clear": "Alarm Clear", + "action-type-assigned-to-edge": "Assigned to Edge", + "action-type-unassigned-from-edge": "Unassigned from Edge", + "action-type-credentials-request": "Credentials Request", + "action-type-entity-merge-request": "Entity Merge Request" }, "entity": { "add-alias": "Ajouter un alias d'entité", @@ -1450,7 +1507,13 @@ "unset-auto-assign-to-edge": "Non défini, attribuer une chaîne de règles aux arêtes lors de la création", "unset-auto-assign-to-edge-title": "Voulez-vous vraiment annuler l'attribution de la chaîne de règles d'arête \"{{ruleChainName}}\" aux arêtes lors de la création?", "unset-auto-assign-to-edge-text": "Après la confirmation, la chaîne de règles d'arêtes ne sera plus automatiquement affectée aux arêtes lors de la création.", - "edge-template-root": "Racine du modèle" + "edge-template-root": "Racine du modèle", + "search": "Rechercher des chaînes de règles", + "selected-rulechains": "{count, plural, 1 {1 rule chain} other {# rule chains}} sélectionné", + "open-rulechain": "Chaîne de règles ouverte", + "assign-to-edge": "Attribuer à Edge", + "edge-rulechain": "Chaîne de règles Edge", + "unassign-rulechains-from-edge-title": "Voulez-vous vraiment annuler l'attribution de {count, plural, 1 {1 rulechain} other {# rulechains}}?" }, "rulenode": { "add": "Ajouter un noeud de règle",