diff --git a/ui-ngx/src/app/core/http/asset.service.ts b/ui-ngx/src/app/core/http/asset.service.ts index f272dccfc0..b3f5f86c10 100644 --- a/ui-ngx/src/app/core/http/asset.service.ts +++ b/ui-ngx/src/app/core/http/asset.service.ts @@ -89,4 +89,18 @@ export class AssetService { return this.http.get(`/api/tenant/assets?assetName=${assetName}`, defaultHttpOptionsFromConfig(config)); } + public assignAssetToEdge(edgeId: string, assetId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/edge/${edgeId}/asset/${assetId}`, null, defaultHttpOptionsFromConfig(config)); + } + + public unassignAssetFromEdge(assetId: string, config?: RequestConfig) { + return this.http.delete(`/api/edge/asset/${assetId}`, defaultHttpOptionsFromConfig(config)); + } + + public getEdgeAssets(edgeId, pageLink: PageLink, type: string = '', + config?: RequestConfig): Observable> { + return this.http.get>(`/api/edge/${edgeId}/assets${pageLink.toQuery()}&type=${type}`, + defaultHttpOptionsFromConfig(config)); + } + } diff --git a/ui-ngx/src/app/core/http/component-descriptor.service.ts b/ui-ngx/src/app/core/http/component-descriptor.service.ts index a3198b862a..d024778f15 100644 --- a/ui-ngx/src/app/core/http/component-descriptor.service.ts +++ b/ui-ngx/src/app/core/http/component-descriptor.service.ts @@ -53,7 +53,7 @@ export class ComponentDescriptorService { } } - public getComponentDescriptorsByTypes(componentTypes: Array, + public getComponentDescriptorsByTypes(componentTypes: Array, type: string, config?: RequestConfig): Observable> { let result: ComponentDescriptor[] = []; for (let i = componentTypes.length - 1; i >= 0; i--) { @@ -67,7 +67,7 @@ export class ComponentDescriptorService { if (!componentTypes.length) { return of(result); } else { - return this.http.get>(`/api/components?componentTypes=${componentTypes.join(',')}`, + return this.http.get>(`/api/components/${type}?componentTypes=${componentTypes.join(',')}`, defaultHttpOptionsFromConfig(config)).pipe( map((componentDescriptors) => { componentDescriptors.forEach((componentDescriptor) => { diff --git a/ui-ngx/src/app/core/http/dashboard.service.ts b/ui-ngx/src/app/core/http/dashboard.service.ts index 42ba3834c9..111ea9bfe4 100644 --- a/ui-ngx/src/app/core/http/dashboard.service.ts +++ b/ui-ngx/src/app/core/http/dashboard.service.ts @@ -157,4 +157,19 @@ export class DashboardService { return this.stDiffObservable; } + public getEdgeDashboards(edgeId: string, pageLink: PageLink, type: string = '', + config?: RequestConfig): Observable> { + return this.http.get>(`/api/edge/${edgeId}/dashboards${pageLink.toQuery()}&type=${type}`, + defaultHttpOptionsFromConfig(config)) + } + + public assignDashboardToEdge(edgeId: string, dashboardId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/edge/${edgeId}/dashboard/${dashboardId}`, null, + defaultHttpOptionsFromConfig(config)); + } + + public unassignDashboardFromEdge(edgeId: string, dashboardId: string, config?: RequestConfig) { + return this.http.delete(`/api/edge/${edgeId}/dashboard/${dashboardId}`, defaultHttpOptionsFromConfig(config)); + } + } diff --git a/ui-ngx/src/app/core/http/device.service.ts b/ui-ngx/src/app/core/http/device.service.ts index 2d31503bd1..1055c1e53e 100644 --- a/ui-ngx/src/app/core/http/device.service.ts +++ b/ui-ngx/src/app/core/http/device.service.ts @@ -143,4 +143,18 @@ export class DeviceService { return this.http.delete(`/api/customer/device/${deviceName}/claim`, defaultHttpOptionsFromConfig(config)); } + public assignDeviceToEdge(edgeId: string, deviceId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/edge/${edgeId}/device/${deviceId}`, defaultHttpOptionsFromConfig(config)); + } + + public unassignDeviceFromEdge(deviceId: string, config?: RequestConfig) { + return this.http.delete(`/api/edge/device/${deviceId}`, defaultHttpOptionsFromConfig(config)); + } + + public getEdgeDevices(edgeId: string, pageLink: PageLink, type: string = '', + config?: RequestConfig): Observable> { + return this.http.get>(`/api/edge/${edgeId}/devices${pageLink.toQuery()}&type=${type}`, + defaultHttpOptionsFromConfig(config)) + } + } diff --git a/ui-ngx/src/app/core/http/edge.service.ts b/ui-ngx/src/app/core/http/edge.service.ts new file mode 100644 index 0000000000..588fbe6d64 --- /dev/null +++ b/ui-ngx/src/app/core/http/edge.service.ts @@ -0,0 +1,94 @@ +/// +/// 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 { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; +import { Observable } from 'rxjs'; +import { HttpClient } from '@angular/common/http'; +import { PageLink } from '@shared/models/page/page-link'; +import { PageData } from '@shared/models/page/page-data'; +import { EntitySubtype } from '@app/shared/models/entity-type.models'; +import {Edge, EdgeInfo, EdgeSearchQuery } from "@shared/models/edge.models"; + +@Injectable({ + providedIn: 'root' +}) +export class EdgeService { + + constructor( + private http: HttpClient + ) { } + + public getEdges(edgeIds: Array, config?: RequestConfig): Observable> { + return this.http.get>(`/api/edges?edgeIds=${edgeIds.join(',')}`, + defaultHttpOptionsFromConfig(config)); + } + + public getEdge(edgeId: string, config?: RequestConfig): Observable { + return this.http.get(`/api/edge/${edgeId}`, defaultHttpOptionsFromConfig(config)); + } + + public saveEdge(edge: Edge, config?: RequestConfig): Observable { + return this.http.post('/api/edge', edge, defaultHttpOptionsFromConfig(config)); + } + + public deleteEdge(edgeId: string, config?: RequestConfig) { + return this.http.delete(`/api/edge/${edgeId}`, defaultHttpOptionsFromConfig(config)); + } + + public getEdgeTypes(config?: RequestConfig): Observable> { + return this.http.get>('/api/edge/types', defaultHttpOptionsFromConfig(config)); + } + + public getTenantEdges(pageLink: PageLink, type: string = '', + config?: RequestConfig): Observable> { + return this.http.get>(`/api/tenant/edges${pageLink.toQuery()}&type=${type}`, + defaultHttpOptionsFromConfig(config)); + } + + public getCustomerEdges(customerId: string, pageLink: PageLink, type: string = '', + config?: RequestConfig): Observable> { + return this.http.get>(`/api/customer/${customerId}/edges${pageLink.toQuery()}&type=${type}`, + defaultHttpOptionsFromConfig(config)); + } + + public assignEdgeToCustomer(customerId: string, edgeId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/customer/${customerId}/edge/${edgeId}`, null, defaultHttpOptionsFromConfig(config)); + } + + public unassignEdgeFromCustomer(edgeId: string, config?: RequestConfig) { + return this.http.delete(`/api/customer/edge/${edgeId}`, defaultHttpOptionsFromConfig(config)); + } + + public makeEdgePublic(edgeId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/customer/public/edge/${edgeId}`, null, defaultHttpOptionsFromConfig(config)); + } + + public setRootRuleChain(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/edge/${edgeId}/${ruleChainId}/root`, null, defaultHttpOptionsFromConfig(config)); + } + + public getTenantEdgeInfos(pageLink: PageLink, type: string = '', + config?: RequestConfig): Observable> { + return this.http.get>(`/api/tenant/edgeInfos${pageLink.toQuery()}&type=${type}`, + defaultHttpOptionsFromConfig(config)); + } + + public findByQuery(query: EdgeSearchQuery, config?: RequestConfig): Observable> { + return this.http.post>('/api/edges', query, defaultHttpOptionsFromConfig(config)); + } + +} diff --git a/ui-ngx/src/app/core/http/entity-view.service.ts b/ui-ngx/src/app/core/http/entity-view.service.ts index d7fd2b2ab4..55ac1c6550 100644 --- a/ui-ngx/src/app/core/http/entity-view.service.ts +++ b/ui-ngx/src/app/core/http/entity-view.service.ts @@ -83,4 +83,19 @@ export class EntityViewService { return this.http.post>('/api/entityViews', query, defaultHttpOptionsFromConfig(config)); } + public assignEntityViewToEdge(edgeId: string, entityViewId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/edge/${edgeId}/entityView/${entityViewId}`, null, + defaultHttpOptionsFromConfig(config)); + } + + public unassignEntityViewFromEdge(entityViewId: string, config?: RequestConfig) { + return this.http.delete(`/api/edge/entityView/${entityViewId}`, defaultHttpOptionsFromConfig(config)); + } + + public getEdgeEntityViews(edgeId: string, pageLink: PageLink, type: string = '', + config?: RequestConfig): Observable> { + return this.http.get>(`/api/edge/${edgeId}/entityViews${pageLink.toQuery()}&type=${type}`, + 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 8437704faa..4a72b6af1b 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -57,6 +57,9 @@ import { Asset, AssetSearchQuery } from '@shared/models/asset.models'; import { Device, DeviceCredentialsType, DeviceSearchQuery } from '@shared/models/device.models'; import { EntityViewSearchQuery } from '@shared/models/entity-view.models'; import { AttributeService } from '@core/http/attribute.service'; +import { EdgeService } from "@core/http/edge.service"; +import {EdgeSearchQuery} from "@shared/models/edge.models"; +import {ruleChainType} from "@shared/models/rule-chain.models"; @Injectable({ providedIn: 'root' @@ -67,6 +70,7 @@ export class EntityService { private http: HttpClient, private store: Store, private deviceService: DeviceService, + private edgeService: EdgeService, private assetService: AssetService, private entityViewService: EntityViewService, private tenantService: TenantService, @@ -90,6 +94,9 @@ export class EntityService { case EntityType.ASSET: observable = this.assetService.getAsset(entityId, config); break; + case EntityType.EDGE: + observable = this.edgeService.getEdge(entityId, config); + break; case EntityType.ENTITY_VIEW: observable = this.entityViewService.getEntityView(entityId, config); break; @@ -157,6 +164,9 @@ export class EntityService { case EntityType.ASSET: observable = this.assetService.getAssets(entityIds, config); break; + case EntityType.EDGE: + observable = this.edgeService.getEdges(entityIds, config); + break; case EntityType.ENTITY_VIEW: observable = this.getEntitiesByIdsObservable( (id) => this.entityViewService.getEntityView(id, config), @@ -265,6 +275,14 @@ export class EntityService { entitiesObservable = this.assetService.getTenantAssetInfos(pageLink, subType, config); } break; + case EntityType.EDGE: + pageLink.sortOrder.property = 'name'; + if (authUser.authority === Authority.CUSTOMER_USER) { + entitiesObservable = this.edgeService.getCustomerEdges(customerId, pageLink, subType, config); + } else { + entitiesObservable = this.edgeService.getTenantEdgeInfos(pageLink, subType, config); + } + break; case EntityType.ENTITY_VIEW: pageLink.sortOrder.property = 'name'; if (authUser.authority === Authority.CUSTOMER_USER) { @@ -292,7 +310,12 @@ export class EntityService { break; case EntityType.RULE_CHAIN: pageLink.sortOrder.property = 'name'; - entitiesObservable = this.ruleChainService.getRuleChains(pageLink, config); + entitiesObservable = this.ruleChainService.getRuleChains(pageLink, ruleChainType.core, config); + // TODO: deaflynx: change solution + // console.log("route.routerState.snapshot.url", this.route.routerState.snapshot.url); + // if (this.route.url.includes('edges')) { + // entitiesObservable = this.ruleChainService.getRuleChains(pageLink, edgeRuleChainType, config); + // } else { entitiesObservable = this.ruleChainService.getRuleChains(pageLink, subType, config); } break; case EntityType.DASHBOARD: pageLink.sortOrder.property = 'title'; @@ -390,6 +413,8 @@ export class EntityService { return entityTypes.indexOf(EntityType.ASSET) > -1 ? true : false; case AliasFilterType.deviceType: return entityTypes.indexOf(EntityType.DEVICE) > -1 ? true : false; + case AliasFilterType.edgeType: + return entityTypes.indexOf(EntityType.EDGE) > -1 ? true : false; case AliasFilterType.entityViewType: return entityTypes.indexOf(EntityType.ENTITY_VIEW) > -1 ? true : false; case AliasFilterType.relationsQuery: @@ -416,6 +441,8 @@ export class EntityService { return entityTypes.indexOf(EntityType.ASSET) > -1 ? true : false; case AliasFilterType.deviceSearchQuery: return entityTypes.indexOf(EntityType.DEVICE) > -1 ? true : false; + case AliasFilterType.edgeSearchQuery: + return entityTypes.indexOf(EntityType.EDGE) > -1 ? true : false; case AliasFilterType.entityViewSearchQuery: return entityTypes.indexOf(EntityType.ENTITY_VIEW) > -1 ? true : false; } @@ -449,6 +476,8 @@ export class EntityService { return entityType === EntityType.ASSET; case AliasFilterType.deviceType: return entityType === EntityType.DEVICE; + case AliasFilterType.edgeType: + return entityType === EntityType.EDGE; case AliasFilterType.entityViewType: return entityType === EntityType.ENTITY_VIEW; case AliasFilterType.relationsQuery: @@ -457,6 +486,8 @@ export class EntityService { return entityType === EntityType.ASSET; case AliasFilterType.deviceSearchQuery: return entityType === EntityType.DEVICE; + case AliasFilterType.edgeSearchQuery: + return entityType === EntityType.EDGE; case AliasFilterType.entityViewSearchQuery: return entityType === EntityType.ENTITY_VIEW; } @@ -474,6 +505,7 @@ export class EntityService { case Authority.TENANT_ADMIN: entityTypes.push(EntityType.DEVICE); entityTypes.push(EntityType.ASSET); + entityTypes.push(EntityType.EDGE); entityTypes.push(EntityType.ENTITY_VIEW); entityTypes.push(EntityType.TENANT); entityTypes.push(EntityType.CUSTOMER); @@ -486,6 +518,7 @@ export class EntityService { case Authority.CUSTOMER_USER: entityTypes.push(EntityType.DEVICE); entityTypes.push(EntityType.ASSET); + entityTypes.push(EntityType.EDGE); entityTypes.push(EntityType.ENTITY_VIEW); entityTypes.push(EntityType.CUSTOMER); entityTypes.push(EntityType.DASHBOARD); @@ -531,6 +564,7 @@ export class EntityService { entityFieldKeys.push(entityFields.type.keyName); break; case EntityType.DEVICE: + case EntityType.EDGE: case EntityType.ASSET: entityFieldKeys.push(entityFields.name.keyName); entityFieldKeys.push(entityFields.type.keyName); @@ -704,6 +738,19 @@ export class EntityService { } ) ); + case AliasFilterType.edgeType: + return this.getEntitiesByNameFilter(EntityType.EDGE, filter.edgeNameFilter, maxItems, + filter.edgeType, {ignoreLoading: true, ignoreErrors: true}).pipe( + map((entities) => { + if (entities && entities.length || !failOnEmpty) { + result.entities = this.entitiesToEntitiesInfo(entities); + return result; + } else { + throw new Error(); + } + } + ) + ); case AliasFilterType.entityViewType: return this.getEntitiesByNameFilter(EntityType.ENTITY_VIEW, filter.entityViewNameFilter, maxItems, filter.entityViewType, {ignoreLoading: true, ignoreErrors: true}).pipe( @@ -763,6 +810,7 @@ export class EntityService { } case AliasFilterType.assetSearchQuery: case AliasFilterType.deviceSearchQuery: + case AliasFilterType.edgeSearchQuery: case AliasFilterType.entityViewSearchQuery: result.stateEntity = filter.rootStateEntity; if (result.stateEntity && stateEntityId) { @@ -793,6 +841,10 @@ export class EntityService { const deviceSearchQuery = searchQuery as DeviceSearchQuery; deviceSearchQuery.deviceTypes = filter.deviceTypes; findByQueryObservable = this.deviceService.findByQuery(deviceSearchQuery, {ignoreLoading: true, ignoreErrors: true}); + } else if (filter.type === AliasFilterType.edgeSearchQuery) { + const edgeSearchQuery = searchQuery as EdgeSearchQuery; + edgeSearchQuery.edgeTypes = filter.edgeTypes; + findByQueryObservable = this.edgeService.findByQuery(edgeSearchQuery, {ignoreLoading: true, ignoreErrors: true}); } else if (filter.type === AliasFilterType.entityViewSearchQuery) { const entityViewSearchQuery = searchQuery as EntityViewSearchQuery; entityViewSearchQuery.entityViewTypes = filter.entityViewTypes; diff --git a/ui-ngx/src/app/core/http/public-api.ts b/ui-ngx/src/app/core/http/public-api.ts index db477c3a8c..6b549cb3c6 100644 --- a/ui-ngx/src/app/core/http/public-api.ts +++ b/ui-ngx/src/app/core/http/public-api.ts @@ -24,6 +24,7 @@ export * from './customer.service'; export * from './dashboard.service'; export * from './device.service'; export * from './entity.service'; +export * from './edge.service'; export * from './entity-relation.service'; export * from './entity-view.service'; export * from './event.service'; diff --git a/ui-ngx/src/app/core/http/rule-chain.service.ts b/ui-ngx/src/app/core/http/rule-chain.service.ts index c93d67c58b..888a04209f 100644 --- a/ui-ngx/src/app/core/http/rule-chain.service.ts +++ b/ui-ngx/src/app/core/http/rule-chain.service.ts @@ -25,6 +25,7 @@ import { RuleChain, RuleChainConnectionInfo, RuleChainMetaData, + ruleChainType, ruleChainNodeComponent, ruleNodeTypeComponentTypes, unknownNodeComponent @@ -59,8 +60,8 @@ export class RuleChainService { private translate: TranslateService ) { } - public getRuleChains(pageLink: PageLink, config?: RequestConfig): Observable> { - return this.http.get>(`/api/ruleChains${pageLink.toQuery()}`, + public getRuleChains(pageLink: PageLink, type: string, config?: RequestConfig): Observable> { + return this.http.get>(`/api/ruleChains${pageLink.toQuery()}&type=${type}`, defaultHttpOptionsFromConfig(config)); } @@ -110,12 +111,12 @@ export class RuleChainService { ); } - public getRuleNodeComponents(ruleNodeConfigResourcesModulesMap: {[key: string]: any}, config?: RequestConfig): + public getRuleNodeComponents(ruleNodeConfigResourcesModulesMap: {[key: string]: any}, type: string, config?: RequestConfig): Observable> { if (this.ruleNodeComponents) { return of(this.ruleNodeComponents); } else { - return this.loadRuleNodeComponents(config).pipe( + return this.loadRuleNodeComponents(type, config).pipe( mergeMap((components) => { return this.resolveRuleNodeComponentsUiResources(components, ruleNodeConfigResourcesModulesMap).pipe( map((ruleNodeComponents) => { @@ -198,8 +199,8 @@ export class RuleChainService { } } - private loadRuleNodeComponents(config?: RequestConfig): Observable> { - return this.componentDescriptorService.getComponentDescriptorsByTypes(ruleNodeTypeComponentTypes, config).pipe( + private loadRuleNodeComponents(type: string, config?: RequestConfig): Observable> { + return this.componentDescriptorService.getComponentDescriptorsByTypes(ruleNodeTypeComponentTypes, type, config).pipe( map((components) => { const ruleNodeComponents: RuleNodeComponentDescriptor[] = []; components.forEach((component) => { @@ -286,4 +287,40 @@ export class RuleChainService { ); } + public getEdgeRuleChains(edgeId: string, pageLink: PageLink, + config?:RequestConfig): Observable> { + return this.http.get>(`/api/edge/${edgeId}/ruleChains${pageLink.toQuery()}`, + defaultHttpOptionsFromConfig(config) ) + } + + public getEdgesRuleChains(pageLink: PageLink, config?: RequestConfig): Observable> { + return this.getRuleChains(pageLink, ruleChainType.edge, config); + } + + public assignRuleChainToEdge(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/edge/${edgeId}/ruleChain/${ruleChainId}`, null, + defaultHttpOptionsFromConfig(config)); + } + + public unassignRuleChainFromEdge(edgeId: string, ruleChainId: string, config?: RequestConfig) { + return this.http.delete(`/api/edge/${edgeId}/ruleChain/${ruleChainId}`, defaultHttpOptionsFromConfig(config)); + } + + public setDefaultRootEdgeRuleChain(ruleChainId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/ruleChain/${ruleChainId}/defaultRootEdge`, defaultHttpOptionsFromConfig(config)); + } + + public addDefaultEdgeRuleChain(ruleChainId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/ruleChain/${ruleChainId}/defaultEdge`, defaultHttpOptionsFromConfig(config)); + } + + public removeDefaultEdgeRuleChain(ruleChainId: string, config?: RequestConfig): Observable { + return this.http.delete(`/api/ruleChain/${ruleChainId}/defaultEdge`, defaultHttpOptionsFromConfig(config)); + } + + public getDefaultEdgeRuleChains(pageLink: PageLink, config?: RequestConfig): Observable> { + return this.http.get>(`/api/ruleChain/defaultEdgeRuleChains${pageLink.toQuery()}`, + defaultHttpOptionsFromConfig(config)); + } + } diff --git a/ui-ngx/src/app/core/services/menu.service.ts b/ui-ngx/src/app/core/services/menu.service.ts index 6032bf24f3..ad8d80f876 100644 --- a/ui-ngx/src/app/core/services/menu.service.ts +++ b/ui-ngx/src/app/core/services/menu.service.ts @@ -180,9 +180,24 @@ export class MenuService { }, { name: 'rulechain.rulechains', - type: 'link', + type: 'toggle', path: '/ruleChains', - icon: 'settings_ethernet' + height: '80px', + icon: 'settings_ethernet', + pages: [ + { + name: 'rulechain.rulechains', + type: 'link', + path: '/ruleChains', + icon: 'settings_ethernet' + }, + { + name: 'rulechain.edge-rulechains', + type: 'link', + path: '/edgesRuleChains', + icon: 'router' + } + ] }, { name: 'customer.customers', @@ -208,6 +223,12 @@ export class MenuService { path: '/entityViews', icon: 'view_quilt' }, + { + name: 'edge.edges', + type: 'link', + path: '/edges', + icon: 'router' + }, { name: 'widget.widget-library', type: 'link', @@ -240,6 +261,11 @@ export class MenuService { name: 'rulechain.rulechains', icon: 'settings_ethernet', path: '/ruleChains' + }, + { + name: 'rulechain.edge-rulechains', + icon: 'router', + path: '/edgesRuleChains' } ] }, @@ -283,6 +309,16 @@ export class MenuService { } ] }, + { + name: 'edge.management', + places: [ + { + name: 'edge.edges', + icon: 'router', + path: '/edges' + } + ] + }, { name: 'dashboard.management', places: [ diff --git a/ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts index d7e03bc79f..720a2d0771 100644 --- a/ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts @@ -28,6 +28,7 @@ import { EntityViewService } from '@core/http/entity-view.service'; import { DashboardService } from '@core/http/dashboard.service'; import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; +import { EdgeService } from "@core/http/edge.service"; export interface AddEntitiesToCustomerDialogData { customerId: string; @@ -57,6 +58,7 @@ export class AddEntitiesToCustomerDialogComponent extends @Inject(MAT_DIALOG_DATA) public data: AddEntitiesToCustomerDialogData, private deviceService: DeviceService, private assetService: AssetService, + private edgeService: EdgeService, private entityViewService: EntityViewService, private dashboardService: DashboardService, @SkipSelf() private errorStateMatcher: ErrorStateMatcher, @@ -79,6 +81,10 @@ export class AddEntitiesToCustomerDialogComponent extends this.assignToCustomerTitle = 'asset.assign-asset-to-customer'; this.assignToCustomerText = 'asset.assign-asset-to-customer-text'; break; + case EntityType.EDGE: + this.assignToCustomerTitle = 'edge.assign-edge-to-customer'; + this.assignToCustomerText = 'edge.assign-edge-to-customer-text'; + break; case EntityType.ENTITY_VIEW: this.assignToCustomerTitle = 'entity-view.assign-entity-view-to-customer'; this.assignToCustomerText = 'entity-view.assign-entity-view-to-customer-text'; @@ -122,6 +128,8 @@ export class AddEntitiesToCustomerDialogComponent extends return this.deviceService.assignDeviceToCustomer(customerId, entityId); case EntityType.ASSET: return this.assetService.assignAssetToCustomer(customerId, entityId); + case EntityType.EDGE: + return this.edgeService.assignEdgeToCustomer(customerId, entityId); case EntityType.ENTITY_VIEW: return this.entityViewService.assignEntityViewToCustomer(customerId, entityId); case EntityType.DASHBOARD: diff --git a/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.html b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.html new file mode 100644 index 0000000000..ca1722dc24 --- /dev/null +++ b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.html @@ -0,0 +1,57 @@ + +
+ +

{{ assignToEdgeTitle | translate }}

+ + +
+ + +
+
+
+ {{ assignToEdgeText | translate }} + + +
+
+
+ + +
+
diff --git a/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.ts b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.ts new file mode 100644 index 0000000000..cba40c88d9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.ts @@ -0,0 +1,142 @@ +/// +/// 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, OnInit, SkipSelf } from '@angular/core'; +import { ErrorStateMatcher } from '@angular/material/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms'; +import { DeviceService } from '@core/http/device.service'; +import { EdgeService } from "@core/http/edge.service"; +import { EntityType } from '@shared/models/entity-type.models'; +import { forkJoin, Observable } from 'rxjs'; +import { AssetService } from '@core/http/asset.service'; +import { EntityViewService } from '@core/http/entity-view.service'; +import { DashboardService } from '@core/http/dashboard.service'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { Router } from '@angular/router'; +import { RuleChainService } from "@core/http/rule-chain.service"; + +export interface AddEntitiesToEdgeDialogData { + edgeId: string; + entityType: EntityType; +} + +@Component({ + selector: 'tb-add-entities-to-edge-dialog', + templateUrl: './add-entities-to-edge-dialog.component.html', + providers: [{provide: ErrorStateMatcher, useExisting: AddEntitiesToEdgeDialogComponent}], + styleUrls: [] +}) +export class AddEntitiesToEdgeDialogComponent extends + DialogComponent implements OnInit, ErrorStateMatcher { + + addEntitiesToEdgeFormGroup: FormGroup; + + submitted = false; + + entityType: EntityType; + + assignToEdgeTitle: string; + assignToEdgeText: string; + + constructor(protected store: Store, + protected router: Router, + @Inject(MAT_DIALOG_DATA) public data: AddEntitiesToEdgeDialogData, + private deviceService: DeviceService, + private edgeService: EdgeService, + private assetService: AssetService, + private entityViewService: EntityViewService, + private dashboardService: DashboardService, + private ruleChainService: RuleChainService, + @SkipSelf() private errorStateMatcher: ErrorStateMatcher, + public dialogRef: MatDialogRef, + public fb: FormBuilder) { + super(store, router, dialogRef); + this.entityType = data.entityType; + } + + ngOnInit(): void { + this.addEntitiesToEdgeFormGroup = this.fb.group({ + entityIds: [null, [Validators.required]] + }); + switch (this.data.entityType) { + case EntityType.DEVICE: + this.assignToEdgeTitle = 'device.assign-device-to-edge'; + this.assignToEdgeText = 'device.assign-device-to-edge-text'; + break; + case EntityType.RULE_CHAIN: + this.assignToEdgeTitle = 'rulechain.assign-rulechain-to-edge'; + this.assignToEdgeText = 'rulechain.assign-rulechain-to-edge-text'; + break; + case EntityType.ASSET: + this.assignToEdgeTitle = 'asset.assign-asset-to-edge'; + this.assignToEdgeText = 'asset.assign-asset-to-edge-text'; + break; + case EntityType.ENTITY_VIEW: + this.assignToEdgeTitle = 'entity-view.assign-entity-view-to-edge'; + this.assignToEdgeText = 'entity-view.assign-entity-view-to-edge-text'; + break; + case EntityType.DASHBOARD: + this.assignToEdgeTitle = 'dashboard.assign-dashboard-to-edge'; + this.assignToEdgeText = 'dashboard.assign-dashboard-to-edge-text'; + break; + } + } + + isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { + const originalErrorState = this.errorStateMatcher.isErrorState(control, form); + const customErrorState = !!(control && control.invalid && this.submitted); + return originalErrorState || customErrorState; + } + + cancel(): void { + this.dialogRef.close(false); + } + + assign(): void { + this.submitted = true; + const entityIds: Array = this.addEntitiesToEdgeFormGroup.get('entityIds').value; + const tasks: Observable[] = []; + entityIds.forEach( + (entityId) => { + tasks.push(this.getAssignToEdgeTask(this.data.edgeId, entityId)); + } + ); + forkJoin(tasks).subscribe( + () => { + this.dialogRef.close(true); + } + ); + } + + private getAssignToEdgeTask(edgeId: string, entityId: string): Observable { + switch (this.data.entityType) { + case EntityType.DEVICE: + return this.deviceService.assignDeviceToEdge(edgeId, entityId); + case EntityType.ASSET: + return this.assetService.assignAssetToEdge(edgeId, entityId); + case EntityType.ENTITY_VIEW: + return this.entityViewService.assignEntityViewToEdge(edgeId, entityId); + case EntityType.DASHBOARD: + return this.dashboardService.assignDashboardToEdge(edgeId, entityId); + case EntityType.RULE_CHAIN: + return this.ruleChainService.assignRuleChainToEdge(edgeId, entityId); + } + } + +} diff --git a/ui-ngx/src/app/modules/home/dialogs/home-dialogs.module.ts b/ui-ngx/src/app/modules/home/dialogs/home-dialogs.module.ts index 4a9ae93300..609937149f 100644 --- a/ui-ngx/src/app/modules/home/dialogs/home-dialogs.module.ts +++ b/ui-ngx/src/app/modules/home/dialogs/home-dialogs.module.ts @@ -20,12 +20,14 @@ import { SharedModule } from '@app/shared/shared.module'; import { AssignToCustomerDialogComponent } from '@modules/home/dialogs/assign-to-customer-dialog.component'; import { AddEntitiesToCustomerDialogComponent } from '@modules/home/dialogs/add-entities-to-customer-dialog.component'; import { HomeDialogsService } from './home-dialogs.service'; +import { AddEntitiesToEdgeDialogComponent } from "@home/dialogs/add-entities-to-edge-dialog.component"; @NgModule({ declarations: [ AssignToCustomerDialogComponent, - AddEntitiesToCustomerDialogComponent + AddEntitiesToCustomerDialogComponent, + AddEntitiesToEdgeDialogComponent ], imports: [ CommonModule, @@ -33,7 +35,8 @@ import { HomeDialogsService } from './home-dialogs.service'; ], exports: [ AssignToCustomerDialogComponent, - AddEntitiesToCustomerDialogComponent + AddEntitiesToCustomerDialogComponent, + AddEntitiesToEdgeDialogComponent ], providers: [ HomeDialogsService diff --git a/ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts index d199af2542..3ca3adfe3e 100644 --- a/ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts @@ -58,6 +58,11 @@ import { AssetId } from '@app/shared/models/id/asset-id'; import { AssetTabsComponent } from '@home/pages/asset/asset-tabs.component'; import { HomeDialogsService } from '@home/dialogs/home-dialogs.service'; import { DeviceInfo } from '@shared/models/device.models'; +import { EdgeService } from "@core/http/edge.service"; +import { + AddEntitiesToEdgeDialogComponent, + AddEntitiesToEdgeDialogData +} from "@home/dialogs/add-entities-to-edge-dialog.component"; @Injectable() export class AssetsTableConfigResolver implements Resolve> { @@ -65,11 +70,13 @@ export class AssetsTableConfigResolver implements Resolve = new EntityTableConfig(); private customerId: string; + private edgeId: string; constructor(private store: Store, private broadcast: BroadcastService, private assetService: AssetService, private customerService: CustomerService, + private edgeService: EdgeService, private dialogService: DialogService, private homeDialogs: HomeDialogsService, private translate: TranslateService, @@ -111,6 +118,7 @@ export class AssetsTableConfigResolver implements Resolve { if (authUser.authority === Authority.CUSTOMER_USER) { @@ -128,7 +136,13 @@ export class AssetsTableConfigResolver implements Resolve + this.config.tableTitle = edge.name + ': ' + this.translate.instant('asset.assets') ), + ).subscribe(); + } + else { this.config.tableTitle = this.translate.instant('asset.assets'); } this.config.columns = this.configureColumns(this.config.componentsData.assetScope); @@ -168,6 +182,10 @@ export class AssetsTableConfigResolver implements Resolve this.assetService.getTenantAssetInfos(pageLink, this.config.componentsData.assetType); this.config.deleteEntity = id => this.assetService.deleteAsset(id.id); + } else if (assetScope === 'edge') { + this.config.entitiesFetchFunction = pageLink => + this.assetService.getEdgeAssets(this.edgeId, pageLink, this.config.componentsData.assetType); + this.config.deleteEntity = id => this.assetService.deleteAsset(id.id); } else { this.config.entitiesFetchFunction = pageLink => this.assetService.getCustomerAssetInfos(this.customerId, pageLink, this.config.componentsData.assetType); @@ -221,6 +239,16 @@ export class AssetsTableConfigResolver implements Resolve (entity.edgeId && entity.edgeId.id !== NULL_UUID), + onAction: ($event, entity) => this.unassignFromEdge($event, entity) + } + ); + } return actions; } @@ -236,6 +264,16 @@ export class AssetsTableConfigResolver implements Resolve this.unassignAssetsFromEdge($event, entities) + } + ); + } if (assetScope === 'customer') { actions.push( { @@ -277,6 +315,16 @@ export class AssetsTableConfigResolver implements Resolve true, + onAction: ($event) => this.addAssetsToEdge($event) + } + ); + } return actions; } @@ -309,6 +357,26 @@ export class AssetsTableConfigResolver implements Resolve(AddEntitiesToEdgeDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + edgeId: this.edgeId, + entityType: EntityType.ASSET + } + }).afterClosed() + .subscribe((res) => { + if (res) { + this.config.table.updateData(); + } + }); + } + makePublic($event: Event, asset: Asset) { if ($event) { $event.stopPropagation(); @@ -426,4 +494,54 @@ export class AssetsTableConfigResolver implements Resolve { + if (res) { + this.assetService.unassignAssetFromEdge(asset.id.id).subscribe( + () => { + this.config.table.updateData(); + } + ); + } + } + ); + } + + unassignAssetsFromEdge($event: Event, assets: Array) { + if ($event) { + $event.stopPropagation(); + } + this.dialogService.confirm( + this.translate.instant('asset.unassign-assets-from-edge-title', {count: assets.length}), + this.translate.instant('asset.unassign-assets-from-edge-text'), + this.translate.instant('action.no'), + this.translate.instant('action.yes'), + true + ).subscribe((res) => { + if (res) { + const tasks: Observable[] = []; + assets.forEach( + (asset) => { + tasks.push(this.assetService.unassignAssetFromEdge(asset.id.id)); + } + ); + forkJoin(tasks).subscribe( + () => { + this.config.table.updateData(); + } + ); + } + } + ); + } + } diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts b/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts new file mode 100644 index 0000000000..482d97a186 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts @@ -0,0 +1,139 @@ +/// +/// 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 "@home/components/entity/entities-table.component"; +import { Authority } from "@shared/models/authority.enum"; +import { EdgesTableConfigResolver } from "@home/pages/edge/edges-table-config.resolver" +import { AssetsTableConfigResolver } from "@home/pages/asset/assets-table-config.resolver"; +import { DevicesTableConfigResolver } from "@home/pages/device/devices-table-config.resolver"; +import { EntityViewsTableConfigResolver } from "@home/pages/entity-view/entity-views-table-config.resolver"; +import { DashboardsTableConfigResolver } from "@home/pages/dashboard/dashboards-table-config.resolver"; +import { RuleChainsTableConfigResolver } from "@home/pages/rulechain/rulechains-table-config.resolver"; + +const routes: Routes = [ + { + path: 'edges', + data: { + breadcrumb: { + label: 'edge.edges', + icon: 'router' + } + }, + children: [ + { + path: '', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.edges', + edgeScope: 'tenant' + }, + resolve: { + entitiesTableConfig: EdgesTableConfigResolver + } + }, + { + path: ':edgeId/ruleChains', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.rulechains', + ruleChainScope: 'edge', + breadcrumb: { + label: 'edge.rulechains', + icon: 'settings_ethernet' + }, + }, + resolve: { + entitiesTableConfig: RuleChainsTableConfigResolver + } + }, + { + path: ':edgeId/assets', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.assets', + assetsType: 'edge', + breadcrumb: { + label: 'edge.assets', + icon: 'domain' + } + }, + resolve: { + entitiesTableConfig: AssetsTableConfigResolver + } + }, + { + path: ':edgeId/devices', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.devices', + devicesType: 'edge', + breadcrumb: { + label: 'edge.devices', + icon: 'devices_other' + } + }, + resolve: { + entitiesTableConfig: DevicesTableConfigResolver + } + }, + { + path: ':edgeId/entityViews', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.entity-views', + entityViewsType: 'edge', + breadcrumb: { + label: 'edge.entity-views', + icon: 'view_quilt' + }, + }, + resolve: { + entitiesTableConfig: EntityViewsTableConfigResolver + } + }, + { + path: ':edgeId/dashboards', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.dashboards', + dashboardsType: 'edge', + breadcrumb: { + label: 'edge.dashboards', + icon: 'dashboard' + } + }, + resolve: { + entitiesTableConfig: DashboardsTableConfigResolver + } + }] + }] + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + providers: [ + EdgesTableConfigResolver + ] +}) +export class EdgeRoutingModule { } diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.html b/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.html new file mode 100644 index 0000000000..0155fb5013 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.html @@ -0,0 +1,23 @@ + + + diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.scss b/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.scss new file mode 100644 index 0000000000..bd3bc86b1c --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.scss @@ -0,0 +1,49 @@ +/** + * 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 '../../../../../scss/constants'; + +:host { + flex: 1; + display: flex; + justify-content: flex-start; + min-width: 150px; +} + +:host ::ng-deep { + tb-entity-subtype-select { + width: 100%; + + mat-form-field { + font-size: 16px; + + .mat-form-field-wrapper { + padding-bottom: 0; + } + + .mat-form-field-underline { + bottom: 0; + } + + @media #{$mat-xs} { + width: 100%; + + .mat-form-field-infix { + width: auto !important; + } + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.ts b/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.ts new file mode 100644 index 0000000000..c0a27b2385 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.ts @@ -0,0 +1,42 @@ +/// +/// 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 { EntityTableHeaderComponent } from "@home/components/entity/entity-table-header.component"; +import { EntityType } from "@shared/models/entity-type.models"; +import { Store } from "@ngrx/store"; +import { AppState } from "@core/core.state"; +import { EdgeInfo } from "@shared/models/edge.models"; + +@Component({ + selector: 'tb-edge-table-header', + templateUrl: './edge-table-header.component.html', + styleUrls: ['./edge-table-header.component.scss'] +}) +export class EdgeTableHeaderComponent extends EntityTableHeaderComponent { + + entityType = EntityType; + + constructor(protected store: Store) { + super(store); + } + + edgeTypeChanged(edgeType: string) { + this.entitiesTableConfig.componentsData.edgeType = edgeType; + this.entitiesTableConfig.table.resetSortAndFilter(true); + } + +} diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.html b/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.html new file mode 100644 index 0000000000..ec894a6319 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.html @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.ts new file mode 100644 index 0000000000..860081e0a1 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.ts @@ -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 {EdgeInfo} from "@shared/models/edge.models"; +import {EntityTabsComponent} from "@home/components/entity/entity-tabs.component"; + +@Component({ + selector: 'tb-edge-tabs', + templateUrl: './edge-tabs.component.html', + styleUrls: [] +}) +export class EdgeTabsComponent extends EntityTabsComponent { + + constructor(protected store: Store) { + super(store); + } + + ngOnInit() { + super.ngOnInit(); + } + +} diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge.component.html b/ui-ngx/src/app/modules/home/pages/edge/edge.component.html new file mode 100644 index 0000000000..ed85648a8f --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge.component.html @@ -0,0 +1,124 @@ + +
+ + + + +
+ +
+
+
+ + edge.assigned-to-customer + + +
+ {{ 'edge.public' | translate }} +
+
+
+ + edge.name + + + {{ 'edge.name-required' | translate }} + + + + + + edge.label + + + +
+ + edge.description + + +
+
+
+
+ + edge.edge-key + + +
+ +
+
+
+ + edge.edge-secret + + +
+ +
+
+
diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge.component.scss b/ui-ngx/src/app/modules/home/pages/edge/edge.component.scss new file mode 100644 index 0000000000..bb3718c2da --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge.component.scss @@ -0,0 +1,18 @@ +/** + * 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. + */ +:host { + +} 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 new file mode 100644 index 0000000000..de4327d232 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge.component.ts @@ -0,0 +1,138 @@ +/// +/// 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 } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { AppState } from "@core/core.state"; +import { EntityComponent } from "@home/components/entity/entity.component"; +import {FormBuilder, FormControl, FormGroup, NgModel, Validators} from "@angular/forms"; +import { EntityType } from "@shared/models/entity-type.models"; +import { EdgeInfo } from "@shared/models/edge.models"; +import { TranslateService } from "@ngx-translate/core"; +import { NULL_UUID } from "@shared/models/id/has-uuid"; +import { ActionNotificationShow } from "@core/notification/notification.actions"; +import { guid, isUndefined } from "@core/utils"; +import { EntityTableConfig } from "@home/models/entity/entities-table-config.models"; + +@Component({ + selector: 'tb-edge', + templateUrl: './edge.component.html', + styleUrls: ['./edge.component.scss'] +}) + +export class EdgeComponent extends EntityComponent{ + + entityType = EntityType; + edgeScope: 'tenant' | 'customer' | 'customer_user'; + + constructor(protected store: Store, + protected translate: TranslateService, + @Inject('entity') protected entityValue: EdgeInfo, + @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig, + public fb: FormBuilder) { + super(store, fb, entityValue, entitiesTableConfigValue); + } + + ngOnInit() { + this.edgeScope = this.entitiesTableConfig.componentsData.edgeScope; + super.ngOnInit() + } + + hideDelete() { + if (this.entitiesTableConfig) { + return !this.entitiesTableConfig.deleteEnabled(this.entity); + } else { + return false; + } + } + + isAssignedToCustomer(entity: EdgeInfo): boolean { + return entity && entity.customerId && entity.customerId.id !== NULL_UUID; + } + + buildForm(entity: EdgeInfo): FormGroup { + return this.fb.group( + { + name: [entity ? entity.name : '', [Validators.required]], + type: [entity ? entity.type : null, [Validators.required]], + label: [entity ? entity.label : ''], + routingKey: guid(), + secret: this.generateSecret(20), + additionalInfo: this.fb.group( + { + description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''] + } + ) + } + ); + } + + updateForm(entity: EdgeInfo) { + this.entityForm.patchValue({name: entity.name}); + this.entityForm.patchValue({type: entity.type}); + this.entityForm.patchValue({label: entity.label}); + this.entityForm.patchValue({routingKey: entity.routingKey}); + this.entityForm.patchValue({secret: entity.secret}); + this.entityForm.patchValue({additionalInfo: { + description: entity.additionalInfo ? entity.additionalInfo.description : ''}}); + } + + onEdgeIdCopied($event) { + this.store.dispatch(new ActionNotificationShow( + { + message: this.translate.instant('edge.id-copied-message'), + type: 'success', + duration: 750, + verticalPosition: 'bottom', + horizontalPosition: 'left' + })); + } + + onEdgeKeyCopied($event) { + this.store.dispatch(new ActionNotificationShow( + { + message: this.translate.instant('edge.edge-key-copied-message'), + type: 'success', + duration: 750, + verticalPosition: 'bottom', + horizontalPosition: 'left' + })); + } + + onEdgeSecretCopied($event) { + this.store.dispatch(new ActionNotificationShow( + { + message: this.translate.instant('edge.edge-secret-copied-message'), + type: 'success', + duration: 750, + verticalPosition: 'bottom', + horizontalPosition: 'left' + })); + } + + generateSecret(length): string { + if (isUndefined(length) || length == null) { + length = 1; + } + var l = length > 10 ? 10 : length; + var str = Math.random().toString(36).substr(2, l); + if (str.length >= length) { + return str; + } + return str.concat(this.generateSecret(length - str.length)); + } + +} diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge.module.ts b/ui-ngx/src/app/modules/home/pages/edge/edge.module.ts new file mode 100644 index 0000000000..89018a58b4 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edge.module.ts @@ -0,0 +1,42 @@ +/// +/// 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 { HomeDialogsModule } from "@home/dialogs/home-dialogs.module"; +import { HomeComponentsModule } from "@home/components/home-components.module"; +import { EdgeRoutingModule } from "@home/pages/edge/edge-routing.module"; +import { EdgeComponent } from '@modules/home/pages/edge/edge.component'; +import { EdgeTableHeaderComponent } from "@home/pages/edge/edge-table-header.component"; +import { EdgeTabsComponent } from "@home/pages/edge/edge-tabs.component"; + +@NgModule({ + declarations: [ + EdgeComponent, + EdgeTableHeaderComponent, + EdgeTabsComponent + ], + imports: [ + CommonModule, + SharedModule, + HomeDialogsModule, + HomeComponentsModule, + EdgeRoutingModule + ] +}) + +export class EdgeModule { } diff --git a/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts new file mode 100644 index 0000000000..895274d10c --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts @@ -0,0 +1,509 @@ +/// +/// 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 { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; +import { + CellActionDescriptor, + checkBoxCell, + DateEntityTableColumn, + EntityTableColumn, + EntityTableConfig, + GroupActionDescriptor, + HeaderActionDescriptor +} 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 { forkJoin, Observable, of } from 'rxjs'; +import { select, Store } from '@ngrx/store'; +import { selectAuthUser } from '@core/auth/auth.selectors'; +import { map, mergeMap, take, tap } from 'rxjs/operators'; +import { AppState } from '@core/core.state'; +import { Authority } from '@app/shared/models/authority.enum'; +import { CustomerService } from '@core/http/customer.service'; +import { Customer } from '@app/shared/models/customer.model'; +import { NULL_UUID } from '@shared/models/id/has-uuid'; +import { BroadcastService } from '@core/services/broadcast.service'; +import { MatDialog } from '@angular/material/dialog'; +import { DialogService } from '@core/services/dialog.service'; +import { + AssignToCustomerDialogComponent, + AssignToCustomerDialogData +} from '@modules/home/dialogs/assign-to-customer-dialog.component'; +import { + AddEntitiesToCustomerDialogComponent, + AddEntitiesToCustomerDialogData +} from '../../dialogs/add-entities-to-customer-dialog.component'; +import { HomeDialogsService } from '@home/dialogs/home-dialogs.service'; + +import { Edge, EdgeInfo } from "@shared/models/edge.models"; +import { EdgeService } from "@core/http/edge.service"; +import { EdgeComponent } from "@home/pages/edge/edge.component"; +import { EdgeTableHeaderComponent } from "@home/pages/edge/edge-table-header.component"; +import { EdgeId } from "@shared/models/id/edge-id"; +import { EdgeTabsComponent } from "@home/pages/edge/edge-tabs.component"; + +@Injectable() +export class EdgesTableConfigResolver implements Resolve> { + + private readonly config: EntityTableConfig = new EntityTableConfig(); + private customerId: string; + + constructor(private store: Store, + private broadcast: BroadcastService, + private edgeService: EdgeService, + private customerService: CustomerService, + private dialogService: DialogService, + private homeDialogs: HomeDialogsService, + private translate: TranslateService, + private datePipe: DatePipe, + private router: Router, + private dialog: MatDialog) { + + this.config.entityType = EntityType.EDGE; + this.config.entityComponent = EdgeComponent; + this.config.entityTabsComponent = EdgeTabsComponent; + this.config.entityTranslations = entityTypeTranslations.get(EntityType.EDGE); + this.config.entityResources = entityTypeResources.get(EntityType.EDGE); + + this.config.deleteEntityTitle = edge => this.translate.instant('edge.delete-edge-title', {edgeName: edge.name}); + this.config.deleteEntityContent = () => this.translate.instant('edge.delete-edge-text'); + this.config.deleteEntitiesTitle = count => this.translate.instant('edge.delete-edges-title', {count}); + this.config.deleteEntitiesContent = () => this.translate.instant('edge.delete-edges-text'); + + this.config.loadEntity = id => this.edgeService.getEdge(id.id); + this.config.saveEntity = edge => { + return this.edgeService.saveEdge(edge).pipe( + tap(() => { + this.broadcast.broadcast('edgeSaved'); + }), + mergeMap((savedEdge) => this.edgeService.getEdge(savedEdge.id.id) + )); + }; + + this.config.onEntityAction = action => this.onEdgeAction(action); + this.config.detailsReadonly = () => this.config.componentsData.edgeScope === 'customer_user'; + + this.config.headerComponent = EdgeTableHeaderComponent; + + } + + resolve(route: ActivatedRouteSnapshot): Observable> { + const routeParams = route.params; + this.config.componentsData = { + edgeScope: route.data.edgeScope, + edgeType: '' + }; + this.customerId = routeParams.customerId; + return this.store.pipe(select(selectAuthUser), take(1)).pipe( + tap((authUser) => { + if (authUser.authority === Authority.CUSTOMER_USER) { + this.config.componentsData.edgeScope = 'customer_user'; + this.customerId = authUser.customerId; + } + }), + mergeMap(() => + this.customerId ? this.customerService.getCustomer(this.customerId) : of(null as Customer) + ), + map((parentCustomer) => { + if (parentCustomer) { + if (parentCustomer.additionalInfo && parentCustomer.additionalInfo.isPublic) { + this.config.tableTitle = this.translate.instant('customer.public-edges'); + } else { + this.config.tableTitle = parentCustomer.title + ': ' + this.translate.instant('edge.edges'); + } + } else { + this.config.tableTitle = this.translate.instant('edge.edges'); + } + this.config.columns = this.configureColumns(this.config.componentsData.edgeScope); + this.configureEntityFunctions(this.config.componentsData.edgeScope); + this.config.cellActionDescriptors = this.configureCellActions(this.config.componentsData.edgeScope); + this.config.groupActionDescriptors = this.configureGroupActions(this.config.componentsData.edgeScope); + this.config.addActionDescriptors = this.configureAddActions(this.config.componentsData.edgeScope); + this.config.addEnabled = this.config.componentsData.edgeScope !== 'customer_user'; + this.config.entitiesDeleteEnabled = this.config.componentsData.edgeScope === 'tenant'; + this.config.deleteEnabled = () => this.config.componentsData.edgeScope === 'tenant'; + return this.config; + }) + ); + } + + configureColumns(edgeScope: string): Array> { + const columns: Array> = [ + new DateEntityTableColumn('createdTime', 'common.created-time', this.datePipe, '150px'), + new EntityTableColumn('name', 'edge.name', '25%'), + new EntityTableColumn('type', 'edge.edge-type', '25%'), + new EntityTableColumn('label', 'edge.label', '25%') + ]; + if (edgeScope === 'tenant') { + columns.push( + new EntityTableColumn('customerTitle', 'customer.customer', '25%'), + new EntityTableColumn('customerIsPublic', 'edge.public', '60px', + entity => { + return checkBoxCell(entity.customerIsPublic); + }, () => ({}), false), + ); + } + return columns; + } + + configureEntityFunctions(edgeScope: string): void { + if (edgeScope === 'tenant') { + this.config.entitiesFetchFunction = pageLink => + this.edgeService.getTenantEdgeInfos(pageLink, this.config.componentsData.edgeType); + this.config.deleteEntity = id => this.edgeService.deleteEdge(id.id); + } + if (edgeScope === 'customer') { + this.config.entitiesFetchFunction = pageLink => + this.edgeService.getCustomerEdges(this.customerId, pageLink, this.config.componentsData.edgeType); + this.config.deleteEntity = id => this.edgeService.unassignEdgeFromCustomer(id.id); + } + } + + configureCellActions(edgeScope: string): Array> { + const actions: Array> = []; + if (edgeScope === 'tenant') { + actions.push( + { + name: this.translate.instant('edge.make-public'), + icon: 'share', + isEnabled: (entity) => (!entity.customerId || entity.customerId.id === NULL_UUID), + onAction: ($event, entity) => this.makePublic($event, entity) + }, + { + name: this.translate.instant('edge.assign-to-customer'), + icon: 'assignment_ind', + isEnabled: (entity) => (!entity.customerId || entity.customerId.id === NULL_UUID), + onAction: ($event, entity) => this.assignToCustomer($event, [entity.id]) + }, + { + name: this.translate.instant('edge.unassign-from-customer'), + icon: 'assignment_return', + isEnabled: (entity) => (entity.customerId && entity.customerId.id !== NULL_UUID && !entity.customerIsPublic), + onAction: ($event, entity) => this.unassignFromCustomer($event, entity) + }, + { + name: this.translate.instant('edge.make-private'), + icon: 'reply', + isEnabled: (entity) => (entity.customerId && entity.customerId.id !== NULL_UUID && entity.customerIsPublic), + onAction: ($event, entity) => this.unassignFromCustomer($event, entity) + }, + { + name: this.translate.instant('edge.manage-edge-assets'), + icon: 'domain', + isEnabled: (entity) => true, + onAction: ($event, entity) => this.openEdgeAssets($event, entity) + }, + { + name: this.translate.instant('edge.manage-edge-devices'), + icon: 'devices_other', + isEnabled: (entity) => true, + onAction: ($event, entity) => this.openEdgeDevices($event, entity) + }, + { + name: this.translate.instant('edge.manage-edge-entity-views'), + icon: 'view_quilt', + isEnabled: (entity) => true, + onAction: ($event, entity) => this.openEdgeEntityViews($event, entity) + }, + { + name: this.translate.instant('edge.manage-edge-dashboards'), + icon: 'dashboard', + isEnabled: (entity) => true, + onAction: ($event, entity) => this.openEdgeDashboards($event, entity) + }, + { + name: this.translate.instant('edge.manage-edge-rulechains'), + icon: 'settings_ethernet', + isEnabled: (entity) => true, + onAction: ($event, entity) => this.openEdgeRuleChains($event, entity) + } + ); + } + if (edgeScope === 'customer') { + actions.push( + { + name: this.translate.instant('edge.unassign-from-customer'), + icon: 'assignment_return', + isEnabled: (entity) => (entity.customerId && entity.customerId.id !== NULL_UUID && !entity.customerIsPublic), + onAction: ($event, entity) => this.unassignFromCustomer($event, entity) + }, + { + name: this.translate.instant('edge.make-private'), + icon: 'reply', + isEnabled: (entity) => (entity.customerId && entity.customerId.id !== NULL_UUID && entity.customerIsPublic), + onAction: ($event, entity) => this.unassignFromCustomer($event, entity) + }, + ); + } + return actions; + } + + configureGroupActions(edgeScope: string): Array> { + const actions: Array> = []; + if (edgeScope === 'tenant') { + actions.push( + { + name: this.translate.instant('edge.assign-edge-to-customer-text'), + icon: 'assignment_ind', + isEnabled: true, + onAction: ($event, entities) => this.assignToCustomer($event, entities.map((entity) => entity.id)) + } + ); + } + if (edgeScope === 'customer') { + actions.push( + { + name: this.translate.instant('edge.unassign-from-customer'), + icon: 'assignment_return', + isEnabled: true, + onAction: ($event, entities) => this.unassignEdgesFromCustomer($event, entities) + } + ); + } + return actions; + } + + configureAddActions(edgeScope: string): Array { + const actions: Array = []; + if (edgeScope === 'tenant') { + actions.push( + { + name: this.translate.instant('edge.add-edge-text'), + icon: 'insert_drive_file', + isEnabled: () => true, + onAction: ($event) => this.config.table.addEntity($event) + }, + { + name: this.translate.instant('edge.import'), + icon: 'file_upload', + isEnabled: () => true, + onAction: ($event) => this.importEdges($event) + } + ); + } + if (edgeScope === 'customer') { + actions.push( + { + name: this.translate.instant('edge.assign-new-edge'), + icon: 'add', + isEnabled: () => true, + onAction: ($event) => this.addEdgesToCustomer($event) + } + ); + } + return actions; + } + + importEdges($event: Event) { + this.homeDialogs.importEntities(EntityType.EDGE).subscribe((res) => { + if (res) { + this.broadcast.broadcast('edgeSaved'); + this.config.table.updateData(); + } + }); + } + + addEdgesToCustomer($event: Event) { + if ($event) { + $event.stopPropagation(); + } + this.dialog.open(AddEntitiesToCustomerDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + customerId: this.customerId, + entityType: EntityType.EDGE + } + }).afterClosed() + .subscribe((res) => { + if (res) { + this.config.table.updateData(); + } + }); + } + + makePublic($event: Event, edge: Edge) { + if ($event) { + $event.stopPropagation(); + } + this.dialogService.confirm( + this.translate.instant('edge.make-public-edge-title', {edgeName: edge.name}), + this.translate.instant('edge.make-public-edge-text'), + this.translate.instant('action.no'), + this.translate.instant('action.yes'), + true + ).subscribe((res) => { + if (res) { + this.edgeService.makeEdgePublic(edge.id.id).subscribe( + () => { + this.config.table.updateData(); + } + ); + } + } + ); + } + + openEdgeDashboards($event, edge) { + if ($event) { + $event.stopPropagation(); + } + this.router.navigateByUrl(`edges/${edge.id.id}/dashboards`); + } + + openEdgeRuleChains($event, edge) { + if ($event) { + $event.stopPropagation(); + } + this.router.navigateByUrl(`edges/${edge.id.id}/ruleChains`); + } + + openEdgeAssets($event: Event, edge: Edge) { + if ($event) { + $event.stopPropagation(); + } + this.router.navigateByUrl(`edges/${edge.id.id}/assets`); + } + + openEdgeDevices($event, edge) { + if ($event) { + $event.stopPropagation(); + } + this.router.navigateByUrl(`edges/${edge.id.id}/devices`); + } + + openEdgeEntityViews($event, edge) { + if ($event) { + $event.stopPropagation(); + } + this.router.navigateByUrl(`edges/${edge.id.id}/entityViews`); + } + + assignToCustomer($event: Event, edgesIds: Array) { + if ($event) { + $event.stopPropagation(); + } + this.dialog.open(AssignToCustomerDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + entityIds: edgesIds, + entityType: EntityType.EDGE + } + }).afterClosed() + .subscribe((res) => { + if (res) { + this.config.table.updateData(); + } + }); + } + + unassignFromCustomer($event: Event, edge: EdgeInfo) { + if ($event) { + $event.stopPropagation(); + } + const isPublic = edge.customerIsPublic; + let title; + let content; + if (isPublic) { + title = this.translate.instant('edge.make-private-edge-title', {edgeName: edge.name}); + content = this.translate.instant('edge.make-private-edge-text'); + } else { + title = this.translate.instant('edge.unassign-edge-title', {edgeName: edge.name}); + content = this.translate.instant('edge.unassign-edge-text'); + } + this.dialogService.confirm( + title, + content, + this.translate.instant('action.no'), + this.translate.instant('action.yes'), + true + ).subscribe((res) => { + if (res) { + this.edgeService.unassignEdgeFromCustomer(edge.id.id).subscribe( + () => { + this.config.table.updateData(); + } + ); + } + } + ); + } + + unassignEdgesFromCustomer($event: Event, edges: Array) { + if ($event) { + $event.stopPropagation(); + } + this.dialogService.confirm( + this.translate.instant('edge.unassign-edge-title', {count: edges.length}), + this.translate.instant('edge.unassign-edge-text'), + this.translate.instant('action.no'), + this.translate.instant('action.yes'), + true + ).subscribe((res) => { + if (res) { + const tasks: Observable[] = []; + edges.forEach( + (edge) => { + tasks.push(this.edgeService.unassignEdgeFromCustomer(edge.id.id)); + } + ); + forkJoin(tasks).subscribe( + () => { + this.config.table.updateData(); + } + ); + } + } + ); + } + + onEdgeAction(action: EntityAction): boolean { + switch (action.action) { + case 'makePublic': + this.makePublic(action.event, action.entity); + return true; + case 'assignToCustomer': + this.assignToCustomer(action.event, [action.entity.id]); + return true; + case 'unassignFromCustomer': + this.unassignFromCustomer(action.event, action.entity); + return true; + case 'openEdgeAssets': + this.openEdgeAssets(action.event, action.entity); + return true; + case 'openEdgeDevices': + this.openEdgeDevices(action.event, action.entity); + return true; + case 'openEdgeEntityViews': + this.openEdgeEntityViews(action.event, action.entity); + return true; + case 'openEdgeDashboards': + this.openEdgeDashboards(action.event, action.entity); + return true; + case 'openEdgeRuleChains': + this.openEdgeRuleChains(action.event, action.entity); + return true; + } + } + +} diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts index 99c8bf2a9f..5dd77ad05e 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts @@ -109,7 +109,8 @@ export class RuleNodeComponentsResolver implements Resolve> { - return this.ruleChainService.getRuleNodeComponents(ruleNodeConfigResourcesModulesMap); + const type = route.data.type; + return this.ruleChainService.getRuleNodeComponents(ruleNodeConfigResourcesModulesMap, type); } } diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts index 3dff54f6f5..83c85434f2 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts @@ -27,7 +27,7 @@ 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 { RuleChain } from '@shared/models/rule-chain.models'; +import {RuleChain, ruleChainType} from '@shared/models/rule-chain.models'; import { RuleChainService } from '@core/http/rule-chain.service'; import { RuleChainComponent } from '@modules/home/pages/rulechain/rulechain.component'; import { DialogService } from '@core/services/dialog.service'; @@ -105,7 +105,7 @@ export class RuleChainsTableConfigResolver implements Resolve this.translate.instant('rulechain.delete-rulechains-title', {count}); this.config.deleteEntitiesContent = () => this.translate.instant('rulechain.delete-rulechains-text'); - this.config.entitiesFetchFunction = pageLink => this.ruleChainService.getRuleChains(pageLink); + this.config.entitiesFetchFunction = pageLink => this.ruleChainService.getRuleChains(pageLink, ruleChainType.core); this.config.loadEntity = id => this.ruleChainService.getRuleChain(id.id); this.config.saveEntity = ruleChain => this.ruleChainService.saveRuleChain(ruleChain); this.config.deleteEntity = id => this.ruleChainService.deleteRuleChain(id.id); diff --git a/ui-ngx/src/app/shared/components/entity/entity-autocomplete.component.ts b/ui-ngx/src/app/shared/components/entity/entity-autocomplete.component.ts index 893d746afc..c65c01dcc4 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-autocomplete.component.ts @@ -153,6 +153,11 @@ export class EntityAutocompleteComponent implements ControlValueAccessor, OnInit this.noEntitiesMatchingText = 'device.no-devices-matching'; this.entityRequiredText = 'device.device-required'; break; + case EntityType.EDGE: + this.entityText = 'edge.edge'; + this.noEntitiesMatchingText = 'edge.no-edges-matching'; + this.entityRequiredText = 'edge.edge-required'; + break; case EntityType.ENTITY_VIEW: this.entityText = 'entity-view.entity-view'; this.noEntitiesMatchingText = 'entity-view.no-entity-views-matching'; diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts index 59d7920106..0a10bf4778 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts @@ -27,6 +27,7 @@ import { BroadcastService } from '@app/core/services/broadcast.service'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { AssetService } from '@core/http/asset.service'; import { EntityViewService } from '@core/http/entity-view.service'; +import { EdgeService } from "@core/http/edge.service"; @Component({ selector: 'tb-entity-subtype-autocomplete', @@ -82,6 +83,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, public translate: TranslateService, private deviceService: DeviceService, private assetService: AssetService, + private edgeService: EdgeService, private entityViewService: EntityViewService, private fb: FormBuilder) { this.subTypeFormGroup = this.fb.group({ @@ -115,6 +117,14 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, this.subTypes = null; }); break; + case EntityType.EDGE: + this.selectEntitySubtypeText = 'edge.select-edge-type'; + this.entitySubtypeText = 'edge.edge-type'; + this.entitySubtypeRequiredText = 'edge.edge-type-required'; + this.broadcastSubscription = this.broadcast.on('edgeSaved', () => { + this.subTypes = null; + }); + break; case EntityType.ENTITY_VIEW: this.selectEntitySubtypeText = 'entity-view.select-entity-view-type'; this.entitySubtypeText = 'entity-view.entity-view-type'; @@ -202,6 +212,9 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, case EntityType.DEVICE: subTypesObservable = this.deviceService.getDeviceTypes({ignoreLoading: true}); break; + case EntityType.EDGE: + subTypesObservable = this.edgeService.getEdgeTypes({ignoreLoading: true}); + break; case EntityType.ENTITY_VIEW: subTypesObservable = this.entityViewService.getEntityViewTypes({ignoreLoading: true}); break; diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts index 8ccd81edf5..de5e1bc6f8 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts @@ -27,6 +27,7 @@ import { MatChipInputEvent, MatChipList } from '@angular/material/chips'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { AssetService } from '@core/http/asset.service'; import { DeviceService } from '@core/http/device.service'; +import { EdgeService } from "@core/http/edge.service"; import { EntityViewService } from '@core/http/entity-view.service'; import { BroadcastService } from '@core/services/broadcast.service'; import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; @@ -96,6 +97,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, public translate: TranslateService, private assetService: AssetService, private deviceService: DeviceService, + private edgeService: EdgeService, private entityViewService: EntityViewService, private fb: FormBuilder) { this.entitySubtypeListFormGroup = this.fb.group({ @@ -139,6 +141,15 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, this.entitySubtypes = null; }); break; + case EntityType.EDGE: + this.placeholder = this.required ? this.translate.instant('edge.enter-edge-type') + : this.translate.instant('edge-any-edge'); + this.secondaryPlaceholder = '+' + this.translate.instant('edge.edge-type'); + this.noSubtypesMathingText = 'edge.no-edge-types-matching'; + this.broadcastSubscription = this.broadcast.on('edgeSaved', () => { + this.entitySubtypes = null; + }); + break; case EntityType.ENTITY_VIEW: this.placeholder = this.required ? this.translate.instant('entity-view.enter-entity-view-type') : this.translate.instant('entity-view.any-entity-view'); @@ -260,6 +271,9 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, case EntityType.DEVICE: subTypesObservable = this.deviceService.getDeviceTypes({ignoreLoading: true}); break; + case EntityType.EDGE: + subTypesObservable = this.edgeService.getEdgeTypes({ignoreLoading: true}); + break; case EntityType.ENTITY_VIEW: subTypesObservable = this.entityViewService.getEntityViewTypes({ignoreLoading: true}); break; diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts index 72540ad4c8..4642255c8f 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts @@ -25,6 +25,7 @@ import { DeviceService } from '@core/http/device.service'; import { EntitySubtype, EntityType } from '@app/shared/models/entity-type.models'; import { BroadcastService } from '@app/core/services/broadcast.service'; import { AssetService } from '@core/http/asset.service'; +import { EdgeService } from "@core/http/edge.service"; import { EntityViewService } from '@core/http/entity-view.service'; @Component({ @@ -78,6 +79,7 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni public translate: TranslateService, private deviceService: DeviceService, private assetService: AssetService, + private edgeService: EdgeService, private entityViewService: EntityViewService, private fb: FormBuilder) { this.subTypeFormGroup = this.fb.group({ @@ -111,6 +113,14 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni this.subTypesOptionsSubject.next(''); }); break; + case EntityType.EDGE: + this.entitySubtypeTitle = 'edge.edge-type'; + this.entitySubtypeRequiredText = 'edge.edge-type-required'; + this.broadcastSubscription = this.broadcast.on('edgeSaved',() => { + this.subTypes = null; + this.subTypesOptionsSubject.next(''); + }); + break; case EntityType.ENTITY_VIEW: this.entitySubtypeTitle = 'entity-view.entity-view-type'; this.entitySubtypeRequiredText = 'entity-view.entity-view-type-required'; @@ -208,6 +218,9 @@ export class EntitySubTypeSelectComponent implements ControlValueAccessor, OnIni case EntityType.DEVICE: this.subTypes = this.deviceService.getDeviceTypes({ignoreLoading: true}); break; + case EntityType.EDGE: + this.subTypes = this.edgeService.getEdgeTypes({ignoreLoading: true}); + break; case EntityType.ENTITY_VIEW: this.subTypes = this.entityViewService.getEntityViewTypes({ignoreLoading: true}); break; diff --git a/ui-ngx/src/app/shared/models/alias.models.ts b/ui-ngx/src/app/shared/models/alias.models.ts index 3009685321..d8f619c2e8 100644 --- a/ui-ngx/src/app/shared/models/alias.models.ts +++ b/ui-ngx/src/app/shared/models/alias.models.ts @@ -26,10 +26,12 @@ export enum AliasFilterType { stateEntity = 'stateEntity', assetType = 'assetType', deviceType = 'deviceType', + edgeType = 'edgeType', entityViewType = 'entityViewType', relationsQuery = 'relationsQuery', assetSearchQuery = 'assetSearchQuery', deviceSearchQuery = 'deviceSearchQuery', + edgeSearchQuery = 'edgeSearchQuery', entityViewSearchQuery = 'entityViewSearchQuery' } @@ -41,10 +43,12 @@ export const aliasFilterTypeTranslationMap = new Map( [ AliasFilterType.stateEntity, 'alias.filter-type-state-entity' ], [ AliasFilterType.assetType, 'alias.filter-type-asset-type' ], [ AliasFilterType.deviceType, 'alias.filter-type-device-type' ], + [ AliasFilterType.edgeType, 'alias.filter-type-edge-type' ], [ AliasFilterType.entityViewType, 'alias.filter-type-entity-view-type' ], [ AliasFilterType.relationsQuery, 'alias.filter-type-relations-query' ], [ AliasFilterType.assetSearchQuery, 'alias.filter-type-asset-search-query' ], [ AliasFilterType.deviceSearchQuery, 'alias.filter-type-device-search-query' ], + [ AliasFilterType.edgeSearchQuery, 'alias.filter-type-edge-search-query' ], [ AliasFilterType.entityViewSearchQuery, 'alias.filter-type-entity-view-search-query' ] ] ); @@ -78,6 +82,11 @@ export interface DeviceTypeFilter { deviceNameFilter?: string; } +export interface EdgeTypeFilter { + edgeType?: string; + edgeNameFilter?: string; +} + export interface EntityViewFilter { entityViewType?: string; entityViewNameFilter?: string; @@ -113,6 +122,10 @@ export interface DeviceSearchQueryFilter extends EntitySearchQueryFilter { deviceTypes?: string[]; } +export interface EdgeSearchQueryFilter extends EntitySearchQueryFilter { + edgeTypes?: string[]; +} + export interface EntityViewSearchQueryFilter extends EntitySearchQueryFilter { entityViewTypes?: string[]; } @@ -124,10 +137,12 @@ export type EntityFilters = StateEntityFilter & AssetTypeFilter & DeviceTypeFilter & + EdgeTypeFilter & EntityViewFilter & RelationsQueryFilter & AssetSearchQueryFilter & DeviceSearchQueryFilter & + EdgeSearchQueryFilter & EntityViewSearchQueryFilter; export interface EntityAliasFilter extends EntityFilters { diff --git a/ui-ngx/src/app/shared/models/asset.models.ts b/ui-ngx/src/app/shared/models/asset.models.ts index ab952d26a5..69ce01b6af 100644 --- a/ui-ngx/src/app/shared/models/asset.models.ts +++ b/ui-ngx/src/app/shared/models/asset.models.ts @@ -19,10 +19,12 @@ import { AssetId } from './id/asset-id'; import { TenantId } from '@shared/models/id/tenant-id'; import { CustomerId } from '@shared/models/id/customer-id'; import { EntitySearchQuery } from '@shared/models/relation.models'; +import { EdgeId } from "@shared/models/id/edge-id"; export interface Asset extends BaseData { tenantId?: TenantId; customerId?: CustomerId; + edgeId?: EdgeId; //TODO: deaflynx: "edgeId?" ? name: string; type: string; label: string; diff --git a/ui-ngx/src/app/shared/models/audit-log.models.ts b/ui-ngx/src/app/shared/models/audit-log.models.ts index 165b3c9d46..53f66d5c38 100644 --- a/ui-ngx/src/app/shared/models/audit-log.models.ts +++ b/ui-ngx/src/app/shared/models/audit-log.models.ts @@ -49,7 +49,9 @@ export enum ActionType { ALARM_CLEAR = 'ALARM_CLEAR', LOGIN = 'LOGIN', LOGOUT = 'LOGOUT', - LOCKOUT = 'LOCKOUT' + LOCKOUT = 'LOCKOUT', + ASSIGNED_TO_EDGE = 'ASSIGNED_TO_EDGE', + UNASSIGNED_FROM_EDGE = 'UNASSIGNED_FROM_EDGE' } export enum ActionStatus { @@ -79,7 +81,9 @@ export const actionTypeTranslations = new Map( [ActionType.ALARM_CLEAR, 'audit-log.type-alarm-clear'], [ActionType.LOGIN, 'audit-log.type-login'], [ActionType.LOGOUT, 'audit-log.type-logout'], - [ActionType.LOCKOUT, 'audit-log.type-lockout'] + [ActionType.LOCKOUT, 'audit-log.type-lockout'], + [ActionType.ASSIGNED_TO_EDGE, 'audit-log.type-assigned-to-edge'], + [ActionType.UNASSIGNED_FROM_EDGE, 'audit-log.type-unassigned-from-edge'] ] ); diff --git a/ui-ngx/src/app/shared/models/constants.ts b/ui-ngx/src/app/shared/models/constants.ts index 4c9612489a..4b99a8c0ce 100644 --- a/ui-ngx/src/app/shared/models/constants.ts +++ b/ui-ngx/src/app/shared/models/constants.ts @@ -97,6 +97,7 @@ export const HelpLinks = { customers: helpBaseUrl + '/docs/user-guide/customers', users: helpBaseUrl + '/docs/user-guide/ui/users', devices: helpBaseUrl + '/docs/user-guide/ui/devices', + edges: helpBaseUrl + 'docs/user-guide/ui/edges', assets: helpBaseUrl + '/docs/user-guide/ui/assets', entityViews: helpBaseUrl + '/docs/user-guide/ui/entity-views', entitiesImport: helpBaseUrl + '/docs/user-guide/bulk-provisioning', diff --git a/ui-ngx/src/app/shared/models/edge.models.ts b/ui-ngx/src/app/shared/models/edge.models.ts new file mode 100644 index 0000000000..b7ab7d29a8 --- /dev/null +++ b/ui-ngx/src/app/shared/models/edge.models.ts @@ -0,0 +1,42 @@ +/// +/// 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 { BaseData } from '@shared/models/base-data'; +import { TenantId } from '@shared/models/id/tenant-id'; +import { CustomerId } from '@shared/models/id/customer-id'; +import { EdgeId } from '@shared/models/id/edge-id'; +import { EntitySearchQuery } from '@shared/models/relation.models'; + +export interface Edge extends BaseData { + tenantId?: TenantId; + customerId?: CustomerId; + name: string; + type: string; + secret: string; + routingKey: string; + label?: string; + additionalInfo?: any; +} + +export interface EdgeInfo extends Edge { + customerTitle: string; + customerIsPublic: boolean; + // assignedCustomers?: Array //TODO: deaflynx check usage +} + +export interface EdgeSearchQuery extends EntitySearchQuery { + edgeTypes: Array; +} diff --git a/ui-ngx/src/app/shared/models/entity-type.models.ts b/ui-ngx/src/app/shared/models/entity-type.models.ts index 83b9bcc1fe..a2a2b1b6e3 100644 --- a/ui-ngx/src/app/shared/models/entity-type.models.ts +++ b/ui-ngx/src/app/shared/models/entity-type.models.ts @@ -43,6 +43,7 @@ export enum EntityType { ALARM = 'ALARM', RULE_CHAIN = 'RULE_CHAIN', RULE_NODE = 'RULE_NODE', + EDGE = 'EDGE', ENTITY_VIEW = 'ENTITY_VIEW', WIDGETS_BUNDLE = 'WIDGETS_BUNDLE', WIDGET_TYPE = 'WIDGET_TYPE' @@ -142,6 +143,20 @@ export const entityTypeTranslations = new Map { firstRuleNodeId: RuleNodeId; root: boolean; debugMode: boolean; + type: string; configuration?: any; additionalInfo?: any; } @@ -62,6 +63,11 @@ export interface RuleChainConnectionInfo { type: string; } +export interface RuleChainType { + core: string; + edge: string; +} + export const ruleNodeTypeComponentTypes: ComponentType[] = [ ComponentType.FILTER, @@ -110,3 +116,8 @@ export const inputNodeComponent: RuleNodeComponentDescriptor = { name: 'Input', clazz: 'tb.internal.Input' }; + +export const ruleChainType: RuleChainType = { + core: 'CORE', + edge: 'EDGE' +} 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 544c944b2c..d7b1869bfd 100644 --- a/ui-ngx/src/assets/locale/locale.constant-de_DE.json +++ b/ui-ngx/src/assets/locale/locale.constant-de_DE.json @@ -67,7 +67,7 @@ "general-settings": "Allgemeine Einstellungen", "outgoing-mail": "E-Mail Versand", "outgoing-mail-settings": "Konfiguration des Postausgangsservers", - "system-settings": "Systeminstellungen", + "system-settings": "Systemeinstellungen", "test-mail-sent": "Test E-Mail wurde erfolgreich versendet!", "base-url": "Basis-URL", "base-url-required": "Basis-URL ist erforderlich.", @@ -183,8 +183,6 @@ "filter-type-entity-view-type": "Entitätsansichtstyp", "filter-type-entity-view-type-description": "Entitätsansichten vom Typ '{{entityView}}'", "filter-type-entity-view-type-and-name-description": "Entitätsansichten vom Typ '{{entityView}}' und Name beginnend mit '{{prefix}}'", - "filter-type-edge-type": "Randtyp", - "filter-type-edge-type-description": "Rand vom Typ '{{edgeType}}'", "filter-type-relations-query": "Beziehungsabfrage", "filter-type-relations-query-description": "{{entities}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", "filter-type-asset-search-query": "Objektabfrage", @@ -193,8 +191,6 @@ "filter-type-device-search-query-description": "Geräte vom Typ {{deviceTypes}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", "filter-type-entity-view-search-query": "Entitätsansichtsabfrage", "filter-type-entity-view-search-query-description": "Entitätsansichten vom Typ {{entityViewTypes}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", - "filter-type-edge-search-query": "Randabfrage", - "filter-type-edge-search-query-description": "Rand vom Typ {{edgeTypes}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", "entity-filter": "Entitätsfilter", "resolve-multiple": "Als mehrere Entitäten auflösen", "filter-type": "Filtertyp", @@ -273,14 +269,7 @@ "no-assets-matching": "Es wurden keine zu '{{entity}}' passenden Objekte gefunden.", "asset-required": "Objekt ist erforderlich", "name-starts-with": "Name des Objekts beginnt mit", - "label": "Bezeichnung", - "assign-asset-to-edge": "Objekte dem Rand zuordnen", - "assign-asset-to-edge-text":"Bitte wählen Sie die Objekte aus, die dem Rand zugeordnet werden sollen", - "unassign-from-edge": "Randzuordnung aufheben", - "assign-to-edge": "Einem Rand zuordnen", - "unassign-asset-from-edge-title": "Sind Sie sicher, dass Sie die Zuordnung für das Objekt '{{assetName}}' aufheben möchten?", - "unassign-asset-from-edge-text": "Nach Bestätigung wird die Zuordnung des Objekts aufgehoben und es ist für den Kunden nicht mehr zugänglich.", - "unassign-assets-from-edge-action-title": "Rand { count, plural, 1 {1 Objektzuordnung} other {# Objektzuordnungen} } aufheben" + "label": "Bezeichnung" }, "attribute": { "attributes": "Eigenschaften", @@ -328,8 +317,6 @@ "type-credentials-updated": "Anmeldeinformationen wurden aktualisiert", "type-assigned-to-customer": "Kunden Zuordnung", "type-unassigned-from-customer": "Kunden Zuordnung aufgehoben", - "type-assigned-to-edge": "Rand Zuordnung", - "type-unassigned-from-edge": "Rand Zuordnung aufgehoben", "type-activated": "Aktiviert", "type-suspended": "Ausgesetzt", "type-credentials-read": "Anmeldeinformationen gelesen", @@ -394,7 +381,6 @@ "public-devices": "Öffentliche Geräte", "public-assets": "Öffentliche Objekte", "public-entity-views": "Öffentliche Entitätsansichten", - "public-edges": "Öffentliche Rand", "add": "Kunde hinzufügen", "delete": "Kunde löschen", "manage-customer-users": "Kundenbenutzer verwalten", @@ -403,9 +389,7 @@ "manage-public-devices": "Öffentliche Geräte verwalten", "manage-public-dashboards": "Öffentliche Dashboards verwalten", "manage-customer-assets": "Kundenobjekte verwalten", - "manage-customer-edges": "Randobjekte verwalten", "manage-public-assets": "Öffentliche Objekte verwalten", - "manage-public-edges": "Öffentliche Rand verwalten", "add-customer-text": "Neuen Kunden hinzufügen", "no-customers-text": "Keine Kunden gefunden", "customer-details": "Kundendetails", @@ -430,7 +414,6 @@ "customer-required": "Kunde ist erforderlich", "select-default-customer": "Wählen Sie den Standardkunden aus.", "default-customer": "Standardkunde", - "edges": "Kunden Rand", "default-customer-required": "Ein Standardkunde ist erforderlich, um das Dashboard auf Mandantenebene zu testen." }, "datetime": { @@ -578,21 +561,7 @@ "show-details": "Details anzeigen", "hide-details": "Details ausblenden", "select-state": "Soll-Zustand auswählen", - "state-controller": "Zustandssteuerung", - "manage-assigned-edges": "Zugeordnete Rand verwalten", - "unassign-dashboard-from-edge-text": "Nach der Bestätigung wird die Zuordnung des Dashboards aufgehoben und es ist für der Rand nicht mehr zugänglich.", - "assigned-edges": "Zugeordnete Rand", - "unassign-from-edge": "Zuordnung von Rand aufheben", - "unassign-dashboards-from-edge-action-title": "Zuordnung { count, plural, 1 {1 Dashboard} other {# Dashboards} } vom Rand aufheben", - "unassign-dashboards-from-edge-text": "Nach der Bestätigung wird die Zuordnung aller ausgewählten Dashboards aufgehoben und sie sind für den Rand nicht mehr zugänglich.", - "assign-dashboard-to-edge": "Dashboard(s) dem Rand zuordnen", - "assign-dashboard-to-edge-text": "Bitte wählen Sie die Dashboards aus, die Sie dem Rand zuordnen möchten", - "assign-dashboards-to-edge-text": "Zuordnen { count, plural, 1 {1 Dashboard} other {# Dashboards} } zum Rand", - "unassign-dashboards-from-edge-action-text": "Zuordnung { count, plural, 1 {1 Dashboard} other {# Dashboards} } vom Rand aufheben", - "assign-to-edges": "Dashboard(s) den Rand zuordnen", - "assign-to-edges-text": "Bitte wählen Sie den Rand aus, dem die Dashboards zugeordnet werden sollen", - "unassign-from-edges": "Zuordnung von Dashboard(s) zum Rand aufheben", - "unassign-from-edges-text": "Bitte wählen Sie die Rand aus, für die die Zuordnung von Dashboard(s) aufgehoben werden soll" + "state-controller": "Zustandssteuerung" }, "datakey": { "settings": "Einstellungen", @@ -723,92 +692,11 @@ "is-gateway": "Ist ein Gateway", "public": "Öffentlich", "device-public": "Gerät ist öffentlich", - "select-device": "Gerät auswählen", - "assign-device-to-edge": "Dashboard(s) dem Gerät zuordnen", - "assign-device-to-edge-text":"Bitte wählen Sie die Geräte aus, die Sie dem Rand zuordnen möchten", - "unassign-from-edge": "Zuordnung von Rand aufheben", - "assign-to-edge": "Einem Rand zuordnen", - "assign-to-edge-text": "Bitte wählen Sie die Geräte aus, die Sie dem Rand zuordnen möchten", - "unassign-device-from-edge-title": "Sind Sie sicher, dass Sie die Zuordnung zum Gerät '{{deviceName}}' wirklich aufheben möchten?", - "unassign-device-from-edge-text": "Nach der Bestätigung ist das Gerät nicht zugeordnet und für den Kunden nicht zugänglich.", - "unassign-devices-from-edge-action-title": "Zuordnung { count, plural, 1 {1 Gerät} other {# Geräte} } vom Rand aufheben", - "unassign-device-from-edge": "Nicht zugeordnete Geräte", - "unassign-devices-from-edge-title": "Sind Sie sicher, dass Sie { count, plural, 1 {1 Gerät} other {# Geräte} } nicht mehr zuordnen möchten?", - "unassign-devices-from-edge-text": "Nach der Bestätigung werden alle ausgewählten Geräte nicht zugewiesen und sind für den Rand nicht zugänglich." + "select-device": "Gerät auswählen" }, "dialog": { "close": "Dialog schließen" }, - "edge": { - "edge": "Rand", - "edges": "Rand", - "management": "Rand verwalten", - "no-edges-matching": "Keine passenden Rand '{{entity}}' gefunden.", - "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", - "delete": "Rand löschen", - "delete-edges": "Rand löschen", - "delete-edge-title": "Möchten Sie des Rands wirklich löschen '{{edgeName}}'?", - "delete-edge-text": "Seien Sie vorsichtig, nach der Bestätigung werden der Rand und alle zugehörigen Daten nicht wiederhergestellt.", - "delete-edges-title": "Sind Sie sicher, dass Sie die Rand löschen möchten { count, plural, 1 {1 Rand} other {# Rand} }?", - "delete-edges-action-title": "Löschen { count, plural, 1 {1 Rand} other {# Rand} }", - "delete-edges-text": "Vorsicht, nach Bestätigung werden alle ausgewählten Rand entfernt und alle zugehörigen Daten werden nicht wiederhergestellt.", - "name": "Name", - "name-required": "Name ist erforderlich.", - "description": "Beschreibung", - "events": "Ereignisse", - "details": "Details", - "copy-id": "Regelketten-ID kopieren", - "id-copied-message": "Regelketten-ID wurde in die Zwischenablage kopiert", - "permissions": "Berechtigungen", - "edge-required": "Rand ist erforderlich.", - "edge-type": "Randtyp", - "edge-type-required": "Randtyp ist erforderlich.", - "select-edge-type": "Randtyp auswählen", - "assign-to-customer": "Einem Kunden zuordnen", - "assign-to-customer-text": "Bitte wählen Sie den Kunden aus, dem die Rand zugeordnet werden sollen", - "assign-edge-to-customer": "Rand dem Kunden zuordnen", - "assign-edge-to-customer-text": "Bitte wählen Sie die Rand aus, die dem Kunden zugeordnet werden sollen", - "assigned-to-customer": "Kunden Zuordnung", - "unassign-from-customer": "Kunden Zuordnung aufgehoben", - "assign-edges-text": "{ count, plural, 1 {1 Gerät} other {# Geräte} } dem Rand zuordnen", - "unassign-edge-title": "Sind Sie sicher, dass Sie die Zuordnung zum Rand '{{edgeName}}' wirklich aufheben möchten?", - "unassign-edge-text": "Nach der Bestätigung ist der Rand nicht zugeordnet und für den Kunden nicht zugänglich.", - "make-public": "Rand öffentlich machen", - "make-public-edge-title": "Sind Sie sicher, dass Sie der Rand '{{edgeName}}' öffentlich machen möchten?", - "make-public-edge-text": "Nach Bestätigung wird der Rabd und alle zugehörigen Daten anderen zugänglich gemacht.", - "make-private": "Rand privat machen", - "public": "Öffentlich", - "make-private-edge-title": "Sind Sie sicher, dass Sie der Rand '{{edgeName}}' privat machen möchten?", - "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-new-edge": "Neue Rand zuordnen", - "manage-edge-dashboards": "Rand-Dashboards verwalten", - "unassign-from-edge": "Zuordnung zum Rand aufheben", - "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", - "edge-secret": "Rand Geheimnis", - "copy-edge-secret": "Rand Geheimnis kopieren", - "edge-secret-copied-message": "Rand Geheimnis wurde in die Zwischenablage kopiert", - "manage-edge-assets": "Rand-Objekte verwalten", - "manage-edge-devices": "Rand-Geräte verwalten", - "manage-edge-entity-views": "Rand-Entitätsansichten verwalten", - "assets": "Rand Objekte", - "devices": "Objekte Geräte", - "entity-views": "Objekte Entitätsansichten", - "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" - }, "error": { "unable-to-connect": "Es konnte keine Verbindung zum Server hergestellt werden! Bitte überprüfen Sie Ihre Internetverbindung.", "unhandled-error-code": "Unbehandelter Fehlercode: {{errorCode}}", @@ -902,10 +790,6 @@ "type-rulenodes": "Regelknoten", "list-of-rulenodes": "{ count, plural, 1 {Ein Regelknoten} other {Liste von # Regelknoten} }", "rulenode-name-starts-with": "Regelknoten beginnend mit '{{prefix}}'", - "type-edge": "Randtyp", - "type-edges": "Randtyp", - "list-of-edges": "{ count, plural, 1 {1 Rand} other {# Rand} }", - "edge-name-starts-with": "Rand beginnend mit '{{prefix}}'", "type-current-customer": "Aktueller Kunde", "search": "Entitäten suchen", "selected-entities": "{ count, plural, 1 {Entität} other {# Entitäten} } ausgewählt", @@ -978,17 +862,6 @@ "entity-view-types": "Entitätsansichtstypen", "name": "Name", "name-required": "Name ist erforderlich.", - "assign-entity-view-to-edge": "Entitätsansicht dem Rand zuordnen", - "assign-entity-view-to-edge-text":"Bitte wählen Sie die Entitätsansicht aus, die dem Rand zugeordnet werden sollen", - "unassign-from-edge": "Randzuordnung aufheben", - "assign-to-edge": "Einem Rand zuordnen", - "assign-to-edge-text": "Bitte wählen Sie die Entitätsansichte aus, die dem Rand zugeordnet werden sollen", - "unassign-entity-view-from-edge-title": "Sind Sie sicher, dass Sie die Zuordnung für Entitätsansicht '{{entityViewName}}' aufheben möchten?", - "unassign-entity-view-from-edge-text": "Nach Bestätigung wird die Zuordnung des Entitätsansichts aufgehoben und es ist für den Kunden nicht mehr zugänglich.", - "unassign-entity-views-from-edge-action-title": "Rand { count, plural, 1 {1 Entitätsansicht} other {# Entitätsansichte} } aufheben", - "unassign-entity-view-from-edge": "Entitätsansichtzuordnung aufheben", - "unassign-entity-views-from-edge-title": "Sind Sie sicher, dass Sie { count, plural, 1 {1 Entitätsansicht} other {# Entitätsansichte} } nicht mehr zuordnen möchten?", - "unassign-entity-views-from-edge-text": "Nach der Bestätigung werden alle ausgewählten Entitätsansicht nicht zugewiesen und sind für den Rand nicht zugänglich.", "description": "Beschreibung", "events": "Ereignisse", "details": "Details", @@ -1352,8 +1225,6 @@ "rulechain": { "rulechain": "Regelkette", "rulechains": "Regelketten", - "core-rulechains": "Kernregelketten", - "edge-rulechains": "Randregelketten", "root": "Wurzel", "delete": "Regelkette löschen", "name": "Name", @@ -1386,40 +1257,7 @@ "no-rulechains-matching": "Es wurden keine passenden Regelketten für '{{entity}}' gefunden.", "rulechain-required": "Regelkette ist erforderlich", "management": "Regelverwaltung", - "debug-mode": "Modus zur Fehlersuche", - "assign-rulechains": "Regelketten zuweisen", - "assign-new-rulechain": "Neues Regelkette zuweisen", - "delete-rulechains": "Regelketten löschen", - "default": "Standard", - "unassign-rulechain": "Nicht zugeordnete Regelkette", - "unassign-rulechains": "Nicht zugeordnete Regelketten", - "unassign-rulechain-title": "Möchten Sie die Zuordnung die Regelkette '{{ruleChainTitle}}' wirklich aufheben?", - "unassign-rulechains-title": "Sind Sie sicher, dass Sie die Zuordnung aufheben möchten { count, plural, 1 {1 Regelkette} other {# Regelketten} }?", - "manage-assigned-edges": "Zugeordnete Rand verwalten", - "unassign-rulechain-from-edge-text": "Nach der Bestätigung wird die Zuordnung aller ausgewählten Regelkette aufgehoben und sie sind für den Rand nicht mehr zugänglich.", - "assigned-edges": "Zugeordnete Rand", - "unassign-from-edge": "Randzuordnung aufheben", - "unassign-rulechains-from-edge-action-title": "Zuordnung { count, plural, 1 {1 Regelkette} other {# Regelketten} } vom Rand aufheben", - "unassign-rulechains-from-edge-text": "Nach der Bestätigung wird die Zuordnung aller ausgewählten Regelketten aufgehoben und sie sind für den Rand nicht mehr zugänglich.", - "assign-rulechains-to-edge-text": "Zuordnen { count, plural, 1 {1 Regelkette} other {# Regelketten} } zum Rand", - "assign-rulechain-to-edge": "Regelkette(n) dem Rand zuordnen", - "assign-rulechain-to-edge-text": "Bitte wählen Sie die Regelketten aus, die Sie dem Rand zuordnen möchten", - "unassign-rulechains-from-edge-action-text": "Zuordnung { count, plural, 1 {1 Regelkette} other {# Regelketten} } vom Rand aufheben", - "assign-to-edges": "Regelkette(n) den Rand zuordnen", - "assign-to-edges-text": "Zuordnung von Regelkette(n) zum Rand aufheben", - "unassign-from-edges": "Unassign Rule Chain(s) From Edges", - "unassign-from-edges-text": "Bitte wählen Sie die Rand aus, für die die Zuordnung von Regelkette(n) aufgehoben werden soll", - "assigned-to-edges": "Regelketten Zuordnung", - "set-default-root-edge": "Machen Sie Randregelkette zur Wurzel Standard", - "set-default-root-edge-rulechain-title": "Sind Sie sicher, dass Sie die Randregelkette '{{ruleChainName}}' zur Wurzel machen Standard?", - "set-default-root-edge-rulechain-text": "Nach der Bestätigung wird die Randregelkette zur Wurzel Standard und behandelt alle eingehenden Transportnachrichten.", - "invalid-rulechain-type-error": "Regelkette konnte nicht importiert werden: Ungültige Regelkettentyp. Erwarteter Typ ist {{expectedRuleChainType}}.", - "set-default-edge": "Machen Sie Regelkette Standard", - "set-default-edge-title": "Sind Sie sicher, dass Sie die Randregelkette '{{ruleChainName}}' machen Standard?", - "set-default-edge-text": "Nach der Bestätigung wird die Randregelkette für neu erstellte Rand vergeben.", - "remove-default-edge": "Randregelkette Standard entfernen", - "remove-default-edge-title": "Sind Sie sicher, dass Sie die Randregelkette '{{ruleChainName}}' aus der Standardliste entfernen?", - "remove-default-edge-text": "Nach der Bestätigung wird die Randregelkette nicht für neu erstellte Rand vergeben." + "debug-mode": "Modus zur Fehlersuche" }, "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 4d01f8ed0f..28bdc53e99 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -203,8 +203,6 @@ "filter-type-entity-view-type": "Entity View type", "filter-type-entity-view-type-description": "Entity Views of type '{{entityView}}'", "filter-type-entity-view-type-and-name-description": "Entity Views of type '{{entityView}}' and with name starting with '{{prefix}}'", - "filter-type-edge-type": "Edge type", - "filter-type-edge-type-description": "Edges of type '{{edgeType}}'", "filter-type-relations-query": "Relations query", "filter-type-relations-query-description": "{{entities}} that have {{relationType}} relation {{direction}} {{rootEntity}}", "filter-type-asset-search-query": "Asset search query", @@ -213,8 +211,6 @@ "filter-type-device-search-query-description": "Devices with types {{deviceTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}", "filter-type-entity-view-search-query": "Entity view search query", "filter-type-entity-view-search-query-description": "Entity views with types {{entityViewTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}", - "filter-type-edge-search-query": "Edge search query", - "filter-type-edge-search-query-description": "Edges with types {{edgeTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}", "entity-filter": "Entity filter", "resolve-multiple": "Resolve as multiple entities", "filter-type": "Filter type", @@ -296,20 +292,9 @@ "name-starts-with": "Asset name starts with", "import": "Import assets", "asset-file": "Asset file", - "search": "Search assets", + "search": "Search assets", "selected-assets": "{ count, plural, 1 {1 asset} other {# assets} } selected", - "label": "Label", - "assign-asset-to-edge": "Assign Asset(s) To Edge", - "assign-asset-to-edge-text":"Please select the assets to assign to the edge", - "unassign-from-edge": "Unassign from edge", - "assign-to-edge": "Assign to edge", - "assign-to-edge-text": "Please select the edge to assign the asset(s)", - "unassign-asset-from-edge": "Unassign asset", - "unassign-asset-from-edge-title": "Are you sure you want to unassign the asset '{{assetName}}'?", - "unassign-asset-from-edge-text": "After the confirmation the asset will be unassigned and won't be accessible by the edge.", - "unassign-assets-from-edge-action-title": "Unassign { count, plural, 1 {1 asset} other {# assets} } from edge", - "unassign-assets-from-edge-title": "Are you sure you want to unassign { count, plural, 1 {1 asset} other {# assets} }?", - "unassign-assets-from-edge-text": "After the confirmation all selected assets will be unassigned and won't be accessible by the edge." + "label": "Label" }, "attribute": { "attributes": "Attributes", @@ -359,8 +344,6 @@ "type-credentials-updated": "Credentials updated", "type-assigned-to-customer": "Assigned to Customer", "type-unassigned-from-customer": "Unassigned from Customer", - "type-assigned-to-edge": "Assigned to Edge", - "type-unassigned-from-edge": "Unassigned from Edge", "type-activated": "Activated", "type-suspended": "Suspended", "type-credentials-read": "Credentials read", @@ -425,8 +408,8 @@ "public-dashboards": "Public Dashboards", "public-devices": "Public Devices", "public-assets": "Public Assets", - "public-entity-views": "Public Entity Views", "public-edges": "Public Edges", + "public-entity-views": "Public Entity Views", "add": "Add Customer", "delete": "Delete customer", "manage-customer-users": "Manage customer users", @@ -435,9 +418,7 @@ "manage-public-devices": "Manage public devices", "manage-public-dashboards": "Manage public dashboards", "manage-customer-assets": "Manage customer assets", - "manage-customer-edges": "Manage customer edges", "manage-public-assets": "Manage public assets", - "manage-public-edges": "Manage public edges", "add-customer-text": "Add new customer", "no-customers-text": "No customers found", "customer-details": "Customer details", @@ -464,8 +445,7 @@ "default-customer": "Default customer", "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 Edges" + "selected-customers": "{ count, plural, 1 {1 customer} other {# customers} } selected" }, "datetime": { "date-from": "Date from", @@ -618,21 +598,7 @@ "select-state": "Select target state", "state-controller": "State controller", "search": "Search dashboards", - "selected-dashboards": "{ count, plural, 1 {1 dashboard} other {# dashboards} } selected", - "manage-assigned-edges": "Manage assigned edges", - "unassign-dashboard-from-edge-text": "After the confirmation the dashboard will be unassigned and won't be accessible by the edge.", - "assigned-edges": "Assigned edges", - "unassign-from-edge": "Unassign from edge", - "unassign-dashboards-from-edge-action-title": "Unassign { count, plural, 1 {1 dashboard} other {# dashboards} } from edge", - "unassign-dashboards-from-edge-text": "After the confirmation all selected dashboards will be unassigned and won't be accessible by the edge.", - "assign-dashboard-to-edge": "Assign Dashboard(s) To Edge", - "assign-dashboard-to-edge-text": "Please select the dashboards to assign to the edge", - "assign-dashboards-to-edge-text": "Assign { count, plural, 1 {1 dashboard} other {# dashboards} } to edges", - "unassign-dashboards-from-edge-action-text": "Unassign { count, plural, 1 {1 dashboard} other {# dashboards} } from edges", - "assign-to-edges": "Assign Dashboard(s) To Edges", - "assign-to-edges-text": "Please select the edges to assign the dashboard(s)", - "unassign-from-edges": "Unassign Dashboard(s) From Edges", - "unassign-from-edges-text": "Please select the edges to unassign from the dashboard(s)" + "selected-dashboards": "{ count, plural, 1 {1 dashboard} other {# dashboards} } selected" }, "datakey": { "settings": "Settings", @@ -771,18 +737,7 @@ "import": "Import device", "device-file": "Device file", "search": "Search devices", - "selected-devices": "{ count, plural, 1 {1 device} other {# devices} } selected", - "assign-device-to-edge": "Assign Device(s) To Edge", - "assign-device-to-edge-text":"Please select the devices to assign to the edge", - "unassign-from-edge": "Unassign from edge", - "assign-to-edge": "Assign to edge", - "assign-to-edge-text": "Please select the edge to assign the device(s)", - "unassign-device-from-edge-title": "Are you sure you want to unassign the device '{{deviceName}}'?", - "unassign-device-from-edge-text": "After the confirmation the device will be unassigned and won't be accessible by the edge.", - "unassign-devices-from-edge-action-title": "Unassign { count, plural, 1 {1 device} other {# devices} } from edge", - "unassign-device-from-edge": "Unassign device", - "unassign-devices-from-edge-title": "Are you sure you want to unassign { count, plural, 1 {1 device} other {# devices} }?", - "unassign-devices-from-edge-text": "After the confirmation all selected devices will be unassigned and won't be accessible by the edge." + "selected-devices": "{ count, plural, 1 {1 device} other {# devices} } selected" }, "dialog": { "close": "Close dialog" @@ -792,74 +747,77 @@ "row": "Row" }, "edge": { - "edge": "Edge", - "edges": "Edges", - "management": "Edge management", - "no-edges-matching": "No edges matching '{{entity}}' were found.", - "add": "Add Edge", - "view": "View Edge", - "no-edges-text": "No edges found", - "edge-details": "Edge details", - "add-edge-text": "Add new edge", - "delete": "Delete edge", - "delete-edges": "Delete edges", - "delete-edge-title": "Are you sure you want to delete the edge '{{edgeName}}'?", - "delete-edge-text": "Be careful, after the confirmation the edge and all related data will become unrecoverable.", - "delete-edges-title": "Are you sure you want to edge { count, plural, 1 {1 edge} other {# edges} }?", - "delete-edges-action-title": "Delete { count, plural, 1 {1 edge} other {# edges} }", - "delete-edges-text": "Be careful, after the confirmation all selected edges will be removed and all related data will become unrecoverable.", - "name": "Name", - "name-required": "Name is required.", - "description": "Description", - "events": "Events", - "details": "Details", - "copy-id": "Copy Edge Id", - "id-copied-message": "Edge Id has been copied to clipboard", - "permissions": "Permissions", - "edge-required": "Edge required", - "edge-type": "Edge type", - "edge-type-required": "Edge type is required.", - "select-edge-type": "Select edge type", - "assign-to-customer": "Assign to customer", - "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", - "assigned-to-customer": "Assigned to customer", - "unassign-from-customer": "Unassign from customer", - "assign-edges-text": "Assign { count, plural, 1 {1 edge} other {# edges} } to customer", - "unassign-edge-title": "Are you sure you want to unassign the edge '{{edgeName}}'?", - "unassign-edge-text": "After the confirmation the edge will be unassigned and won't be accessible by the customer.", - "make-public": "Make edge public", - "make-public-edge-title": "Are you sure you want to make the edge '{{edgeName}}' public?", - "make-public-edge-text": "After the confirmation the edge and all its data will be made public and accessible by others.", - "make-private": "Make edge private", - "public": "Public", - "make-private-edge-title": "Are you sure you want to make the edge '{{edgeName}}' private?", - "make-private-edge-text": "After the confirmation the edge and all its data will be made private and won't be accessible by others.", - "import": "Import edge", - "label": "Label", - "assign-new-edge": "Assign new edge", - "manage-edge-dashboards": "Manage edge dashboards", - "unassign-from-edge": "Unassign from edge", - "dashboards": "Edge Dashboards", - "manage-edge-rulechains": "Manage edge rule chains", - "rulechains": "Edge Rule Chains", - "rulechain": "Edge Rule Chain", - "edge-key": "Edge key", - "copy-edge-key": "Copy edge key", - "edge-key-copied-message": "Edge key has been copied to clipboard", - "edge-secret": "Edge secret", - "copy-edge-secret": "Copy edge secret", - "edge-secret-copied-message": "Edge secret has been copied to clipboard", - "manage-edge-assets": "Manage edge assets", - "manage-edge-devices": "Manage edge devices", - "manage-edge-entity-views": "Manage edge entity views", - "assets": "Edge assets", - "devices": "Edge devices", - "entity-views": "Edge entity views", - "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} }" + "edge": "Edge", + "edges": "Edges", + "management": "Edge management", + "no-edges-matching": "No edges matching '{{entity}}' were found.", + "add": "Add Edge", + "view": "View Edge", + "no-edges-text": "No edges found", + "edge-details": "Edge details", + "add-edge-text": "Add new edge", + "delete": "Delete edge", + "delete-edges": "Delete edges", + "delete-edge-title": "Are you sure you want to delete the edge '{{edgeName}}'?", + "delete-edge-text": "Be careful, after the confirmation the edge and all related data will become unrecoverable.", + "delete-edges-title": "Are you sure you want to edge { count, plural, 1 {1 edge} other {# edges} }?", + "delete-edges-action-title": "Delete { count, plural, 1 {1 edge} other {# edges} }", + "delete-edges-text": "Be careful, after the confirmation all selected edges will be removed and all related data will become unrecoverable.", + "name": "Name", + "name-required": "Name is required.", + "description": "Description", + "events": "Events", + "details": "Details", + "copy-id": "Copy Edge Id", + "id-copied-message": "Edge Id has been copied to clipboard", + "permissions": "Permissions", + "edge-required": "Edge required", + "edge-type": "Edge type", + "edge-type-required": "Edge type is required.", + "select-edge-type": "Select edge type", + "assign-to-customer": "Assign to customer", + "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", + "assigned-to-customer": "Assigned to customer", + "unassign-from-customer": "Unassign from customer", + "assign-edges-text": "Assign { count, plural, 1 {1 edge} other {# edges} } to customer", + "unassign-edge-title": "Are you sure you want to unassign the edge '{{edgeName}}'?", + "unassign-edge-text": "After the confirmation the edge will be unassigned and won't be accessible by the customer.", + "make-public": "Make edge public", + "make-public-edge-title": "Are you sure you want to make the edge '{{edgeName}}' public?", + "make-public-edge-text": "After the confirmation the edge and all its data will be made public and accessible by others.", + "make-private": "Make edge private", + "public": "Public", + "make-private-edge-title": "Are you sure you want to make the edge '{{edgeName}}' private?", + "make-private-edge-text": "After the confirmation the edge and all its data will be made private and won't be accessible by others.", + "import": "Import edge", + "label": "Label", + "assign-new-edge": "Assign new edge", + "manage-edge-dashboards": "Manage edge dashboards", + "unassign-from-edge": "Unassign from edge", + "dashboards": "Edge Dashboards", + "manage-edge-rulechains": "Manage edge rule chains", + "rulechains": "Edge Rule Chains", + "rulechain": "Edge Rule Chain", + "edge-key": "Edge key", + "copy-edge-key": "Copy edge key", + "edge-key-copied-message": "Edge key has been copied to clipboard", + "edge-secret": "Edge secret", + "copy-edge-secret": "Copy edge secret", + "edge-secret-copied-message": "Edge secret has been copied to clipboard", + "manage-edge-assets": "Manage edge assets", + "manage-edge-devices": "Manage edge devices", + "manage-edge-entity-views": "Manage edge entity views", + "assets": "Edge assets", + "devices": "Edge devices", + "entity-views": "Edge entity views", + "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} }", + "selected-edges": "{ count, plural, 1 {1 edge} other {# edges} } selected", + "name-starts-with": "Edge name starts with", + "search": "Search edges" }, "error": { "unable-to-connect": "Unable to connect to the server! Please check your internet connection.", @@ -954,10 +912,6 @@ "type-rulenodes": "Rule nodes", "list-of-rulenodes": "{ count, plural, 1 {One rule node} other {List of # rule nodes} }", "rulenode-name-starts-with": "Rule nodes whose names start with '{{prefix}}'", - "type-edge": "Edge", - "type-edges": "Edges", - "list-of-edges": "{ count, plural, 1 {One edge} other {List of # edges} }", - "edge-name-starts-with": "Edges whose names start with '{{prefix}}'", "type-current-customer": "Current Customer", "type-current-tenant": "Current Tenant", "search": "Search entities", @@ -1086,18 +1040,7 @@ "make-private-entity-view-title": "Are you sure you want to make the entity view '{{entityViewName}}' private?", "make-private-entity-view-text": "After the confirmation the entity view and all its data will be made private and won't be accessible by others.", "search": "Search entity views", - "selected-entity-views": "{ count, plural, 1 {1 entity view} other {# entity views} } selected", - "assign-entity-view-to-edge": "Assign Entity View(s) To Edge", - "assign-entity-view-to-edge-text":"Please select the entity views to assign to the edge", - "unassign-from-edge": "Unassign from edge", - "assign-to-edge": "Assign to edge", - "assign-to-edge-text": "Please select the edge to assign the entity view(s)", - "unassign-entity-view-from-edge-title": "Are you sure you want to unassign the entity view '{{entityViewName}}'?", - "unassign-entity-view-from-edge-text": "After the confirmation the entity view will be unassigned and won't be accessible by the edge.", - "unassign-entity-views-from-edge-action-title": "Unassign { count, plural, 1 {1 entity view} other {# entity views} } from edge", - "unassign-entity-view-from-edge": "Unassign entity view", - "unassign-entity-views-from-edge-title": "Are you sure you want to unassign { count, plural, 1 {1 entity view} other {# entity views} }?", - "unassign-entity-views-from-edge-text": "After the confirmation all selected entity views will be unassigned and won't be accessible by the edge." + "selected-entity-views": "{ count, plural, 1 {1 entity view} other {# entity views} } selected" }, "event": { "event-type": "Event type", @@ -1553,10 +1496,9 @@ "no-relations-text": "No relations found" }, "rulechain": { + "edge-rulechains": "Edge Rule chains", "rulechain": "Rule chain", "rulechains": "Rule chains", - "core-rulechains": "Core Rule chains", - "edge-rulechains": "Edge Rule chains", "root": "Root", "delete": "Delete rule chain", "name": "Name", @@ -1592,40 +1534,7 @@ "debug-mode": "Debug mode", "search": "Search rule chains", "selected-rulechains": "{ count, plural, 1 {1 rule chain} other {# rule chains} } selected", - "open-rulechain": "Open rule chain", - "assign-rulechains": "Assign rulechains", - "assign-new-rulechain": "Assign new rulechain", - "delete-rulechains": "Delete rulechains", - "default": "Default", - "unassign-rulechain": "Unassign rulechain", - "unassign-rulechains": "Unassign rulechains", - "unassign-rulechain-title": "Are you sure you want to unassign the rulechain '{{ruleChainTitle}}'?", - "unassign-rulechains-title": "Are you sure you want to unassign { count, plural, 1 {1 rulechain} other {# rulechains} }?", - "manage-assigned-edges": "Manage assigned edges", - "unassign-rulechain-from-edge-text": "After the confirmation the rulechain will be unassigned and won't be accessible by the edge.", - "assigned-edges": "Assigned edges", - "unassign-from-edge": "Unassign from edge", - "unassign-rulechains-from-edge-action-title": "Unassign { count, plural, 1 {1 rulechain} other {# rulechains} } from edge", - "unassign-rulechains-from-edge-text": "After the confirmation all selected rulechains will be unassigned and won't be accessible by the edge.", - "assign-rulechains-to-edge-text": "Assign { count, plural, 1 {1 rulechain} other {# rulechains} } to edges", - "assign-rulechain-to-edge": "Assign Rule Chain(s) To Edge", - "assign-rulechain-to-edge-text": "Please select the rulechains to assign to the edge", - "unassign-rulechains-from-edge-action-text": "Unassign { count, plural, 1 {1 rulechain} other {# rulechains} } from edges", - "assign-to-edges": "Assign Rule Chain(s) To Edges", - "assign-to-edges-text": "Please select the edges to assign the rulechain(s)", - "unassign-from-edges": "Unassign Rule Chain(s) From Edges", - "unassign-from-edges-text": "Please select the edges to unassign from the rulechain(s)", - "assigned-to-edges": "Assigned to edges", - "set-default-root-edge": "Make rule chain default root", - "set-default-root-edge-rulechain-title": "Are you sure you want to make the rule chain '{{ruleChainName}}' default edge root?", - "set-default-root-edge-rulechain-text": "After the confirmation the rule chain will become default edge root and will handle all incoming transport messages.", - "invalid-rulechain-type-error": "Unable to import rule chain: Invalid rule chain type. Expected type is {{expectedRuleChainType}}.", - "set-default-edge": "Make edge rule chain default", - "set-default-edge-title": "Are you sure you want to make the edge rule chain '{{ruleChainName}}' default?", - "set-default-edge-text": "After the confirmation the edge rule chain will be added to default list and assigned to newly created edge(s).", - "remove-default-edge": "Remove edge rule chain from defaults", - "remove-default-edge-title": "Are you sure you want to remove the edge rule chain '{{ruleChainName}}' from default list?", - "remove-default-edge-text": "After the confirmation the edge rule chain will not be assigned for a newly created edges." + "open-rulechain": "Open rule chain" }, "rulenode": { "details": "Details", 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 7644dc27e0..17966569af 100644 --- a/ui-ngx/src/assets/locale/locale.constant-es_ES.json +++ b/ui-ngx/src/assets/locale/locale.constant-es_ES.json @@ -9,7 +9,7 @@ "refresh-token-failed": "No se puede actualizar la sesión" }, "action": { - "activate": "Activar", + "activate": "Activar", "suspend": "Suspender", "save": "Guardar", "saveAs": "Guardar como", @@ -192,8 +192,6 @@ "filter-type-entity-view-type": "Tipo de vista de entidad", "filter-type-entity-view-type-description": "Vistas de entidad del tipo '{{entityView}}'", "filter-type-entity-view-type-and-name-description": "Vistas de entidad del tipo '{{entityView}}' y cuyo nombre comience por '{{prefix}}'", - "filter-type-edge-type": "Tipo de borde", - "filter-type-edge-type-description": "Bordes del tipo '{{edgeType}}'", "filter-type-relations-query": "Consulta de relaciones", "filter-type-relations-query-description": "{{entities}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}", "filter-type-asset-search-query": "Búsqueda de activos", @@ -202,14 +200,10 @@ "filter-type-device-search-query-description": "Dispositivos con tipos {{deviceTypes}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}", "filter-type-entity-view-search-query": "Consulta de búsqueda de vista de entidad", "filter-type-entity-view-search-query-description": "Vistas de entidad con tipos {{entityViewTypes}} que tienen tipo de relación {{relationType}} con dirección {{direction}} {{rootEntity}}", - "type-assigned-to-edge": "Asignado a borde", - "type-unassigned-from-edge": "Sin asignar desde bordes", "entity-filter": "Filtro por entidad", "resolve-multiple": "Tomar como múltiples entidades", "filter-type": "Filtro por tipo", "filter-type-required": "Se requiere filtro por tipo.", - "filter-type-edge-type": "Tipo de borde", - "filter-type-edge-type-description": "Bordes del tipo '{{edgeType}}'", "entity-filter-no-entity-matched": "No se han encontrado entidades con el filtro especificado.", "no-entity-filter-specified": "No hay filtro de entidades especificado", "root-state-entity": "Usar estado de panel como raíz", @@ -398,7 +392,6 @@ "public-devices": "Dispositivos Públicos", "public-assets": "Activos Públicos", "public-entity-views": "Vistas de Entidad Públicas", - "public-edge": "Bordes públicos", "add": "Agregar cliente", "delete": "Borrar cliente", "manage-customer-users": "Gestionar usuarios del cliente", @@ -407,8 +400,6 @@ "manage-public-devices": "Gestionar dispositivos públicos", "manage-public-dashboards": "Gestionar paneles públicos", "manage-customer-assets": "Gestionar activos del cliente", - "manage-customer-edge": "Administrar bordes de clientes", - "manage-public-edge": "Administrar bordes públicos", "manage-public-assets": "Gestionar activos públicos", "add-customer-text": "Agregar nuevo cliente", "no-customers-text": "No se encontraron clientes", @@ -427,7 +418,6 @@ "description": "Descripción", "details": "Detalles", "events": "Eventos", - "edge": "Bordes del cliente", "copyId": "Copiar ID de cliente", "idCopiedMessage": "El ID de cliente se ha copiado al portapapeles", "select-customer": "Seleccionar Cliente", @@ -582,21 +572,7 @@ "show-details": "Mostrar detalles", "hide-details": "Ocultar detalles", "select-state": "Seleccionar estado destino (target state)", - "state-controller": "Controlador de estados", - "manage-assigned-edges": "Administrar bordes asignados", - "unassign-dashboard-from-edge-text": "Después de la confirmación, el tablero no será asignado y el borde no podrá acceder a él", - "assigned-edges": "bordes asignados", - "unassign-from-edge": "Anular asignación de borde", - "unassign-dashboards-from-edge-action-title": "Anular asignación { count, plural, 1 {1 panel} other {# paneles} } de borde", - "unassign-dashboards-from-edge-text": "Después de la confirmación, se anulará la asignación de todos los paneles seleccionados y no serán accesibles por de borde", - "assign-dashboard-to-edge": "Asignar panel(es) al borde", - "assign-dashboard-to-edge-text": "Por favor selecciona los paneles para asignar al borde", - "assign-dashboards-to-edge-text": "Asignar { count, plural, 1 {1 panel} other {# paneles} } a los bordes", - "unassign-dashboards-from-edge-action-text": "Anular asignación { count, plural, 1 {1 dashboard} other {# dashboards} } de los bordes", - "assign-to-edges": "Asignar paneles a los bordes", - "assign-to-edges-text": "Seleccione los bordes para asignar los paneles", - "unassign-from-edges": "Desasignar panel (s) de los bordes", - "unassign-from-edge-text": "Seleccione los bordes para desasignar del panel(es)" + "state-controller": "Controlador de estados" }, "datakey": { "settings": "Ajustes", @@ -732,18 +708,7 @@ "device-public": "El dispositivo es público", "select-device": "Seleccionar dispositivo", "device-file": "Archivo de dispositivo", - "import": "Importar dispositivo", - "assign-device-to-edge": "Asignar dispositivo (s) a borde", - "assign-device-to-edge-text": "Seleccione los dispositivos para asignar al borde", - "unassign-from-edge": "Anular asignación de borde", - "assign-to-edge": "Asignar al borde", - "assign-to-edge-text": "Seleccione el borde para asignar los dispositivos", - "unassign-device-from-edge-title": "¿Está seguro de que desea desasignar el dispositivo '{{deviceName}}'?", - "unassign-device-from-edge-text": "Después de la confirmación, el dispositivo no será asignado y el borde no podrá acceder a él", - "unassign-devices-from-edge-action-title": "Anular asignación {count, plural, 1 {1 device} other {# devices}} from edge", - "unassign-device-from-edge": "Desasignar dispositivo", - "unassign-devices-from-edge-title": "¿Está seguro de que desea desasignar {count, plural, 1 {1 device} other {# devices}}?", - "unassign-devices-from-edge-text": "Después de la confirmación, todos los dispositivos seleccionados quedarán sin asignar y el borde no podrá acceder a ellos" + "import": "Importar dispositivo" }, "dialog": { "close": "Cerrar diálogo" @@ -752,76 +717,6 @@ "column": "Columna", "row": "Fila" }, - "edge": { - "edge": "Borde", - "edges": "Bordes", - "management": "Gestión de bordes", - "no-edge-matching": "No se encontraron bordes que coincidan con '{{entity}}'", - "add": "Agregar borde", - "view": "Ver borde", - "no-edge-text": "No se encontraron bordes", - "edge-details": "Detalles del borde", - "add-edge-text": "Agregar nuevo borde", - "delete": "Eliminar borde", - "delete-edges": "Eliminar bordes", - "delete-edge-title": "¿Está seguro de que desea eliminar el borde '{{edgeName}}'?", - "delete-edge-text": "Tenga cuidado, después de la confirmación, el borde y todos los datos relacionados serán irrecuperables", - "delete-edges-title": "¿Está seguro de que desea edge {count, plural, 1 {1 borde} other {# bordes}}?", - "delete-edge-action-title": "Eliminar {cuenta, plural, 1 {1 borde} otro {# bordes}}", - "delete-edges-text": "Tenga cuidado, después de la confirmación se eliminarán todos los bordes seleccionados y todos los datos relacionados se volverán irrecuperables", - "name": "Nombre", - "name-required": "Se requiere nombre", - "description": "Descripción", - "events": "Eventos", - "details": "Detalles", - "copy-id": "Copiar ID de borde", - "id-copied-message": "El ID de borde se ha copiado al portapapeles", - "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-customer": "Asignar al cliente", - "assign-to-customer-text": "Seleccione el cliente para asignar los bordes", - "assign-edge-to-customer": "Asignar borde(s) al cliente", - "assign-edge-to-customer-text": "Seleccione los bordes para asignar al cliente", - "assigned-to-customer": "Asignado al cliente", - "unassign-from-customer": "Anular asignación del cliente", - "assign-edges-text": "Asignar {cuenta, plural, 1 {1 borde} otro {# bordes}} al cliente", - "unassign-edge-title": "¿Está seguro de que desea desasignar el borde '{{edgeName}}'?", - "unassign-edge-text": "Después de la confirmación, el borde quedará sin asignar y el cliente no podrá acceder a él", - "make-public": "Hacer público el borde", - "make-public-edge-title": "¿Estás seguro de que quieres hacer público el edge '{{edgeName}}'?", - "make-public-edge-text": "Después de la confirmación, el borde y todos sus datos serán públicos y accesibles para otros", - "make-private": "Hacer que edge sea privado", - "public": "Public", - "make-private-edge-title": "¿Está seguro de que desea que el borde '{{edgeName}}' sea privado?", - "make-private-edge-text": "Después de la confirmación, el borde y todos sus datos se harán privados y otros no podrán acceder a ellos", - "import": "Importar borde", - "label": "Etiqueta", - "assign-new-edge": "Asignar nuevo borde", - "manage-edge-dashboards": "Administrar paneles de borde", - "unassign-from-edge": "Anular asignación de borde", - "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", - "edge-secret": "Borde secreto", - "copy-edge-secret": "Copiar borde secreto", - "edge-secret-copied-message": "El secreto de borde se ha copiado al portapapeles", - "manage-edge-assets": "Gestionar activos de bordes", - "manage-edge-devices": "Gestionar dispositivos de borde", - "manage-edge-entity-views": "Gestionar vistas de entidad de borde", - "assets": "Activos de borde", - "devices": "Dispositivos de borde", - "entity-views": "Vistas de entidad de borde", - "set-root-rule-chain-text": "Seleccione la cadena de reglas raíz para los bordes", - "set-root-rule-chain-to-edge": "Establecer la cadena de reglas raíz para Edge (s)", - "set-root-rule-chain-to-edge-text": "Establecer la cadena de la regla raíz para {count, plural, 1 {1 borde} other {# bordes}}" - }, "error": { "unable-to-connect": "Imposible conectar con el servidor! Por favor, revise su conexión a internet.", "unhandled-error-code": "Código de error no controlado: {{errorCode}}", @@ -915,10 +810,6 @@ "type-rulenodes": "Nodos de reglas", "list-of-rulenodes": "{ count, plural, 1 {Un nodo de reglas} other {Lista de # nodos de reglas} }", "rulenode-name-starts-with": "Nodos de reglas cuyos nombres comienzan con '{{prefix}}'", - "type-edge": "Borde", - "type-edges": "Bordes", - "list-of-edges": "{cuenta, plural, 1 {Un borde} otro {Lista de # bordes}}", - "edge-name-starts-with": "Bordes cuyos nombres comienzan con '{{prefijo}}'", "type-current-customer": "Cliente Actual", "type-current-tenant": "Propietario Actual", "search": "Buscar entidades", @@ -1041,18 +932,7 @@ "make-public-entity-view-title": "¿Está seguro de que desea que la vista de entidad '{{entityViewName}}' sea pública?", "make-public-entity-view-text": "Después de la confirmación, la vista de la entidad y todos sus datos se harán públicos y accesibles para otros.", "make-private-entity-view-title": "¿Está seguro de que desea que la vista de entidad '{{entityViewName}}' sea privada?", - "make-private-entity-view-text": "Después de la confirmación, la vista de la entidad y todos sus datos se harán privados y no serán accesibles para otros.", - "assign-entity-view-to-edge": "Asignar vista (s) de entidad a borde", - "assign-entity-view-to-edge-text": "Seleccione las vistas de entidad para asignar al borde", - "unassign-from-edge": "Anular asignación de borde", - "assign-to-edge": "Asignar al borde", - "assign-to-edge-text": "Seleccione el borde para asignar las vistas de entidad", - "unassign-entity-view-from-edge-title": "¿Está seguro de que desea anular la asignación de la vista de entidad '{{entityViewName}}'?", - "unassign-entity-view-from-edge-text": "Después de la confirmación, la vista de entidad quedará sin asignar y el borde no podrá acceder a ella", - "unassign-entity-views-from-edge-action-title": "Anular asignación {recuento, plural, 1 {1 vista de entidad} otras {# vistas de entidad}} del borde", - "unassign-entity-view-from-edge": "Anular asignación de vista de entidad", - "unassign-entity-views-from-edge-title": "¿Está seguro de que desea desasignar {count, plural, 1 {1 vista de entidad} other {# vistas de entidad}}?", - "unassign-entity-views-from-edge-text": "Después de la confirmación, todas las vistas de entidad seleccionadas no serán asignadas y el borde no podrá acceder a ellas" + "make-private-entity-view-text": "Después de la confirmación, la vista de la entidad y todos sus datos se harán privados y no serán accesibles para otros." }, "event": { "event-type": "Tipo de evento", @@ -1514,8 +1394,6 @@ "rulechain": { "rulechain": "Cadena de Regla", "rulechains": "Cadenas de Reglas", - "core-rulechains": "Cadenas de reglas centrales", - "edge-rulechains": "Cadenas de reglas de borde", "root": "Raíz", "delete": "Borrar cadena de reglas", "name": "Nombre", @@ -1548,40 +1426,7 @@ "no-rulechains-matching": "No se encontraron cadenas de reglas que coincidan con '{{entity}}' .", "rulechain-required": "Cadena de reglas requerida", "management": "Gestión de reglas", - "debug-mode": "Modo Debug", - "assign-rulechains": "Asignar cadenas de reglas", - "assign-new-rulechain": "Asignar nueva cadena de reglas", - "delete-rulechains": "Eliminar cadenas de reglas", - "default": "Predeterminado", - "unassign-rulechain": "Anular asignación de cadena de reglas", - "unassign-rulechains": "Anular asignación de cadenas de reglas", - "unassign-rulechain-title": "¿Está seguro de que desea desasignar la cadena de reglas '{{ruleChainTitle}}'?", - "unassign-rulechains-title": "¿Está seguro de que desea desasignar {count, plural, 1 {1 cadena de reglas} other {# cadenas de reglas}}?", - "manage-assigned-edges": "Gestionar bordes asignados", - "unassign-rulechain-from-edge-text": "Después de la confirmación, la cadena de reglas quedará sin asignar y el borde no podrá acceder a ella", - "assigned-edges": "Bordes asignados", - "unassign-from-edge": "Anular asignación de borde", - "unassign-rulechains-from-edge-action-title": "Anular asignación {count, plural, 1 {1 cadena de reglas} other {# cadenas de reglas}} des bordes", - "unassign-rulechains-from-edge-text": "Después de la confirmación, todas las cadenas de reglas seleccionadas quedarán sin asignar y el borde no podrá acceder a ellas", - "assign-rulechains-to-edge-text": "Asignar {cuenta, plural, 1 {1 cadena de reglas} otras {# cadenas de reglas}} a las aristas", - "assign-rulechain-to-edge": "Asignar cadena (s) de reglas a borde", - "assign-rulechain-to-edge-text": "Seleccione las cadenas de reglas para asignar al borde", - "unassign-rulechains-from-edge-action-text": "Anular asignación {cuenta, plural, 1 {1 cadena de reglas} otro {# cadenas de reglas}} de los bordes", - "assign-to-edges": "Asignar cadena (s) de reglas a los bordes", - "assign-to-edges-text": "Seleccione los bordes para asignar las cadenas de reglas", - "unassign-from-edges": "Desasignar cadena (s) de reglas de los bordes", - "unassign-from-edges-text": "Seleccione los bordes para desasignar de la (s) cadena (s) de reglas", - "assigned-to-edges": "Asignado a bordes", - "set-default-root-edge": "Hacer que la cadena de reglas sea la raíz predeterminada", - "set-default-root-edge-rulechain-title": "¿Está seguro de que desea hacer que la cadena de reglas '{{ruleChainName}}' sea la raíz de borde predeterminada?", - "set-default-root-edge-rulechain-text": "Después de la confirmación, la cadena de reglas se convertirá en raíz raíz predeterminada y manejará todos los mensajes de transporte entrantes", - "invalid-rulechain-type-error": "No se puede importar la cadena de reglas: Tipo de cadena de reglas no válido. El tipo esperado es {{expectedRuleChainType}}", - "set-default-edge": "Hacer que la cadena de reglas de borde sea predeterminada", - "set-default-edge-title": "¿Está seguro de que desea que la cadena de reglas de borde '{{ruleChainName}}' sea predeterminada?", - "set-default-edge-text": "Después de la confirmación, la cadena de reglas de borde se agregará a la lista predeterminada y se asignará a los bordes recién creados", - "remove-default-edge": "Eliminar la cadena de regla de borde de los valores predeterminados", - "remove-default-edge-title": "¿Está seguro de que desea eliminar la cadena de reglas de borde '{{ruleChainName}}' de la lista predeterminada?", - "remove-default-edge-text": "Después de la confirmación, la cadena de reglas de borde no se asignará a los bordes recién creados" + "debug-mode": "Modo Debug" }, "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 c2e9adcb31..a5e16b23a0 100644 --- a/ui-ngx/src/assets/locale/locale.constant-fr_FR.json +++ b/ui-ngx/src/assets/locale/locale.constant-fr_FR.json @@ -176,7 +176,7 @@ "entity-filter": "Filtre d'entité", "entity-filter-no-entity-matched": "Aucune entité correspondant au filtre spécifié n'a été trouvée.", "filter-type": "Type de filtre", - "filter-type-asset-search-query": "Requête de recherche d'actifs", + "filter-type-asset-search-query": "requête de recherche d'actifs", "filter-type-asset-search-query-description": "Actifs de types {{assetTypes}} ayant {{relationType}} relation {{direction}} {{rootEntity}}", "filter-type-asset-type": "type d'actif", "filter-type-asset-type-and-name-description": "Actifs de type '{{assetType}}' et dont le nom commence par '{{prefix}}'", @@ -190,13 +190,9 @@ "filter-type-entity-name": "Nom d'entité", "filter-type-entity-view-search-query": "Requête de recherche vue d'entité", "filter-type-entity-view-search-query-description": "Vues d'entité avec les types {{entityViewTypes}} ayant {{relationType}} relation {{direction}} {{rootEntity}}", - "filter-type-edge-search-query": "Requête de recherche de bordure", - "filter-type-edge-search-query-description": "Bordures de types {{edgeTypes}} ayant {{relationType}} relation {{direction}} {{rootEntity}}", "filter-type-entity-view-type": "Type de vue d'entité", "filter-type-entity-view-type-and-name-description": "Vues d'entité de type '{{entityView}}' et dont le nom commence par '{{prefix}}'", "filter-type-entity-view-type-description": "Vues d'entité de type '{{entityView}}'", - "filter-type-edge-type": "Type de la bordure", - "filter-type-edge-type-description": "Dispositifs de type '{{edgeType}}'", "filter-type-relations-query": "Interrogation des relations", "filter-type-relations-query-description": "{{entities}} ayant {{relationType}} relation {{direction}} {{rootEntity}}", "filter-type-required": "Le type de filtre est requis.", @@ -260,17 +256,6 @@ "name": "Nom", "name-required": "Nom est requis.", "name-starts-with": "Le nom de l'actif commence par", - "assign-asset-to-edge": "Attribuer des actifs a la bordure", - "assign-asset-to-edge-text": "Veuillez sélectionner les actifs à attribuer a la bordure", - "unassign-from-edge": "Retirer de la bordure", - "assign-to-edge": "Attribuer a la bordure", - "assign-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les actifs", - "unassign-asset-from-edge": "Retirer de la bordure", - "unassign-asset-from-edge-title": "Êtes-vous sûr de vouloir retirer l'attribution de l'actif '{{assetName}}'?", - "unassign-asset-from-edge-text": "Après la confirmation, l'actif sera non attribué et ne sera pas accessible a la bordure.", - "unassign-assets-from-edge-action-title": "Retirer {count, plural, 1 {1 asset} other {# assets}} de la bordure", - "unassign-assets-from-edge-title": "Êtes-vous sûr de vouloir retirer l'attribution de {count, plural, 1 {1 asset} other {# assets}}?", - "unassign-assets-from-edge-text": "Après la confirmation, tous les actifs sélectionnés ne seront pas attribués et ne seront pas accessibles a la bordure.", "no-asset-types-matching": "Aucun type d'actif correspondant à {{entitySubtype}} n'a été trouvé. ", "no-assets-matching": "Aucun actif correspondant à {{entity}} n'a été trouvé. ", "no-assets-text": "Aucun actif trouvé", @@ -339,8 +324,6 @@ "type-alarm-ack": "Acquitté", "type-alarm-clear": "Effacé", "type-assigned-to-customer": "Attribué au client", - "type-assigned-to-edge": "Attribué a la bordure", - "type-unassigned-from-edge": "Non attribué de la bordure", "type-attributes-deleted": "Attributs supprimés", "type-attributes-read": "Attributs lus", "type-attributes-updated": "Attributs mis à jour", @@ -424,13 +407,11 @@ "description": "Description", "details": "Détails", "devices": "Dispositifs du client", - "edges": "Bordures du client", "entity-views": "Vues de l'entité client", "events": "Événements", "idCopiedMessage": "L'Id du client a été copié dans le presse-papier", "manage-assets": "Gérer les actifs", "manage-customer-assets": "Gérer les actifs du client", - "manage-customer-edges": "Gérer les bordures du client", "manage-customer-dashboards": "Gérer les tableaux de bord du client", "manage-customer-devices": "Gérer les dispositifs du client", "manage-customer-users": "Gérer les utilisateurs du client", @@ -439,7 +420,6 @@ "manage-public-assets": "Gérer les actifs publics", "manage-public-dashboards": "Gérer les tableaux de bord publics", "manage-public-devices": "Gérer les dispositifs publics", - "manage-public-edges": "Gérer les bordures publics", "manage-users": "Gérer les utilisateurs", "management": "Gestion des clients", "no-customers-matching": "Aucun client correspondant à '{{entity}} n'a été trouvé.", @@ -448,7 +428,6 @@ "public-dashboards": "Tableaux de bord publics", "public-devices": "Dispositifs publics", "public-entity-views": "Vues d'entités publiques", - "public-edges": "Bordures publics", "select-customer": "Sélectionner un client", "select-default-customer": "Sélectionnez le client par défaut", "title": "Titre", @@ -593,21 +572,7 @@ "view-dashboards": "Afficher les tableaux de bord", "widget-file": "Fichier du Widget", "widget-import-missing-aliases-title": "Configurer les alias utilisés par le widget importé", - "widgets-margins": "Marge entre les widgets", - "manage-assigned-edges": "Gérer les bordures affectés", - "unassign-dashboard-from-edge-text": "Après la confirmation, tableau de bord sera non attribué et ne sera pas accessible a la bordure.", - "assigned-edges": "Bordures affectés", - "unassign-from-edge": "Retirer de la bordure", - "unassign-dashboards-from-edge-action-title": "Annuler l'affectation {count, plural, 1 {1 tableau de bord} other {# tableaux de bord}} de la bordure", - "unassign-dashboards-from-edge-text": "Après la confirmation, tous les tableaux de bord sélectionnés ne seront pas attribués et ne seront pas accessibles a la bordure.", - "assign-dashboard-to-edge": "Attribuer des tableaux de bord a la bordure", - "assign-dashboard-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les tableaux de bord", - "assign-dashboards-to-edge-text": "Attribuer {count, plural, 1 {1 tableau de bord} other {# tableaux de bord}} aux bordures", - "unassign-dashboards-from-edge-action-text": "Annuler l'affectation {count, plural, 1 {1 tableau de bord} other {# tableaux de bord}} des bordures", - "assign-to-edges": "Attribuer des tableaux de bord a la bordures", - "assign-to-edges-text": "Veuillez sélectionner les bordures pour attribuer les tableaux de bord", - "unassign-from-edges": "Retirer de la bordure", - "unassign-from-edges-text": "Veuillez sélectionner les bordures à annuler l'affectation du ou des tableaux de bord" + "widgets-margins": "Marge entre les widgets" }, "datakey": { "advanced": "Avancé", @@ -745,92 +710,11 @@ "unassign-from-customer": "Retirer du client", "use-device-name-filter": "Utiliser le filtre", "view-credentials": "Afficher les informations d'identification", - "view-devices": "Afficher les dispositifs", - "assign-device-to-edge": "Attribuer a la bordure", - "assign-device-to-edge-text":"Veuillez sélectionner la bordure pour attribuer le ou les dispositifs", - "unassign-from-edge": "Retirer de la bordure", - "assign-to-edge": "Attribuer a la bordure", - "assign-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les dispositifs", - "unassign-device-from-edge-title": "Êtes-vous sûr de vouloir annuler l'affection du dispositif {{deviceName}} '?", - "unassign-device-from-edge-text": "Après la confirmation, dispositif sera non attribué et ne sera pas accessible a la bordure.", - "unassign-devices-from-edge-action-title": "Annuler l'affectation de {count, plural, 1 {1 device} other {#devices}} de la bordure", - "unassign-device-from-edge": "Retirer de la bordure", - "unassign-devices-from-edge-title": "Voulez-vous vraiment annuler l'affectation de {count, plural, 1 {1 device} other {# devices}}?", - "unassign-devices-from-edge-text": "Après la confirmation, tous les dispositifs sélectionnés ne seront pas attribues et ne seront pas accessibles par la bordure." + "view-devices": "Afficher les dispositifs" }, "dialog": { "close": "Fermer le dialogue" }, - "edge": { - "edge": "Bordure", - "edges": "Bordures", - "management": "Gestion des bordures", - "no-edges-matching": "Aucun bordure correspondant à {{entity}} n'a été trouvé.", - "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", - "delete": "Supprimer la bordure", - "delete-edges": "Supprimer les bordures", - "delete-edge-title": "Êtes-vous sûr de vouloir supprimer la bordure '{{edgeName}}'?", - "delete-edge-text": "Faites attention, après la confirmation, la bordure et toutes les données associées deviendront irrécupérables", - "delete-edges-title": "Êtes-vous sûr de vouloir supprimer {count, plural, 1 {1 bordure} other {# bordure}}?", - "delete-edges-action-title": "Supprimer {count, plural, 1 {1 bordure} other {# bordure}}", - "delete-edges-text": "Faites attention, après la confirmation, tous les bordures sélectionnés seront supprimés et toutes les données associées deviendront irrécupérables.", - "name": "Nom", - "name-required": "Le nom de la bordure est requis", - "description": "Dispositifs", - "events": "Événements", - "details": "Détails de l'entité", - "copy-id": "Copier borudre Id", - "id-copied-message": "Id de la bordure a été copié dans le presse-papier", - "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-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", - "assign-edge-to-customer-text": "Veuillez sélectionner la bordure pour attribuer le ou les dispositifs", - "assigned-to-customer": "Attribué au client", - "unassign-from-customer": "Retirer du client", - "assign-edges-text": "Attribuer {count, plural, 1 {1 bordure} other {# bordures}} au client", - "unassign-edge-title": "Êtes-vous sûr de vouloir annuler l'affection du dispositif {{edgeName}}", - "unassign-edge-text": "Après la confirmation, le dispositif ne sera pas attribué et ne sera pas accessible au client", - "make-public": "Make edge public", - "make-public-edge-title": "Are you sure you want to make the edge '{{edgeName}}' public?", - "make-public-edge-text": "After the confirmation the edge and all its data will be made public and accessible by others.", - "make-private": "Rendre public Edge", - "public": "Public", - "make-private-edge-title": "Are you sure you want to make the edge '{{edgeName}}' private?", - "make-private-edge-text": "Après la confirmation, la bordure et toutes ses données seront rendues privées et ne seront pas accessibles par d'autres", - "import": "Importer bordure", - "label": "Etiquette", - "assign-new-edge": "Attribuer un nouvel bordure", - "manage-edge-dashboards": "Gérer les tableaux de bord", - "unassign-from-edge": "Retirer de la bordure", - "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", - "edge-secret": "Secret de la bordure", - "copy-edge-secret": "Copier secret de la bordure", - "edge-secret-copied-message": "Secret de la bordure a été copié dans le presse-papier", - "manage-edge-assets": "Gérer les actifs de la bordure", - "manage-edge-devices": "Gérer les dispositifs de la bordure", - "manage-edge-entity-views": "Vues de l'entité vues de l'entité", - "assets": "Actifs de la bordure", - "devices": "Dispositifs de la bordure", - "entity-views": "Vues de l'entité bordure", - "set-root-rule-chain-text": "Veuillez sélectionner la chaîne de règles racine pour les bordure(s)", - "set-root-rule-chain-to-edges": "Définir la chaîne de règles racine pour bordure(s)", - "set-root-rule-chain-to-edges-text": "Définir la chaîne de règles racine pour {count, plural, 1 {1 bordure} other {# bordures} }" - }, "entity": { "add-alias": "Ajouter un alias d'entité", "alarm-name-starts-with": "Les actifs dont le nom commence par '{{prefix}}'", @@ -891,10 +775,6 @@ "rule-name-starts-with": "Régles dont les noms commencent par '{{prefix}}'", "rulechain-name-starts-with": "Chaînes de régles dont les noms commencent par '{{prefix}}'", "rulenode-name-starts-with": "Les noeuds de régles dont le nom commence par '{{prefix}}'", - "type-edge": "Bordure", - "type-edges": "Bordures", - "list-of-edges": "{ count, plural, 1 {Une bordure} other {List of # bordures} }", - "edge-name-starts-with": "Bordures dont les noms commencent par '{{prefix}}'", "search": "Recherche d'entités", "select-entities": "Sélectionner des entités", "selected-entities": "{count, plural, 1 {1 entité} other {# entités} } sélectionnées", @@ -1005,17 +885,6 @@ "make-public": "Rendre la vue d'entité publique", "make-public-entity-view-text": "Après la confirmation, la vue de l'entité et toutes ses données seront rendues publiques et accessibles à d'autres", "make-public-entity-view-title": "Voulez-vous vraiment que la vue de l'entité '{{entityViewName}}' soit publique?", - "assign-entity-view-to-edge": "Attribuer a la bordure", - "assign-entity-view-to-edge-text":"Veuillez sélectionner la bordure auquel attribuer la ou les vues d'entité.", - "unassign-from-edge": "Retirer de la bordure", - "assign-to-edge": "Attribuer a la bordure", - "assign-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les actifs", - "unassign-entity-view-from-edge-title": "Voulez-vous vraiment annuler l'attribution de la vue d'entité '{{entityViewName}}'?", - "unassign-entity-view-from-edge-text": "Après la confirmation, la vue de l'entité sera non attribuée et ne sera pas accessible par la bordure.", - "unassign-entity-views-from-edge-action-title": "Annuler l'attribution { count, plural, 1 {1 entityView} other {# entityViews} } de la bordure", - "unassign-entity-view-from-edge": "Annuler l'attribution des vues d'entité", - "unassign-entity-views-from-edge-title": "Êtes-vous sûr de vouloir annuler l'attribution { count, plural, 1 {1 entityView} other {# entityViews} }?", - "unassign-entity-views-from-edge-text": "Après la confirmation, toutes les vues des entités sélectionnées seront non attribuées et ne seront pas accessibles par la bordure.", "management": "Gestion de vue d'entité", "name": "Nom", "name-required": "Un nom est requis.", @@ -1430,45 +1299,10 @@ "rulechain-required": "Chaîne de règles requise", "rulechains": "Chaînes de règles", "select-rulechain": "Sélectionner la chaîne de règles", - "core-rulechains": "Chaînes de règles fondamentales", - "edge-rulechains": "Chaînes de règles de la bordure", "set-root": "Rend la chaîne de règles racine (root) ", "set-root-rulechain-text": "Après la confirmation, la chaîne de règles deviendra racine (root) et gérera tous les messages de transport entrants.", "set-root-rulechain-title": "Voulez-vous vraiment que la chaîne de règles '{{ruleChainName}} soit racine (root) ?", - "system": "Système", - "assign-rulechains": "Attribuer aux chaînes de règles", - "assign-new-rulechain": "Attribuer une nouvele chaînes de règles", - "delete-rulechains": "Supprimer une chaînes de règles", - "default": "Défaut", - "unassign-rulechain": "Retirer chaîne de règles", - "unassign-rulechains": "Retirer chaînes de règles", - "unassign-rulechain-title": "AÊtes-vous sûr de vouloir retirer l'attribution de chaînes de règles '{{ruleChainTitle}}'?", - "unassign-rulechains-title": "Êtes-vous sûr de vouloir retirer l'attribution de {count, plural, 1 {1 chaîne de règles} other {# chaînes de règles}}?", - "manage-assigned-edges": "Gérer les bordures affectés", - "unassign-rulechain-from-edge-text": "Après la confirmation, l'actif sera non attribué et ne sera pas accessible a la bordure.", - "assigned-edges": "Bordures affectés", - "unassign-from-edge": "Retirer de la bordure", - "unassign-rulechains-from-edge-action-title": "Retirer {count, plural, 1 {1 chaîne de règles} other {# chaînes de règles}} de la bordure", - "unassign-rulechains-from-edge-text": "Après la confirmation, tous les chaînes de règles sélectionnés ne seront pas attribués et ne seront pas accessibles a la bordure.", - "assign-rulechains-to-edge-text": "Attribuer {count, plural, 1 {1 chaîne de règles} other {# chaînes de règles}} aux bordures", - "assign-rulechain-to-edge": "Attribuer les chaînes de règles a la bordure", - "assign-rulechain-to-edge-text": "Veuillez sélectionner la bordure pour attribuer le ou les chaînes de règles", - "unassign-rulechains-from-edge-action-text": "Annuler l'affectation {count, plural, 1 {1 chaîne de règles} other {# chaînes de règles}} des bordures", - "assign-to-edges": "Attribuer des tableaux de bord a la bordures", - "assign-to-edges-text": "Please select the edges to assign the rulechain(s)", - "unassign-from-edges": "Retirer de la bordure", - "unassign-from-edges-text": "Veuillez sélectionner les bordures à annuler l'affectation du ou des chaînes de règles", - "assigned-to-edges": "Attribué chaînes de règles", - "set-default-root-edge": "Définir la racine par défaut de la chaîne de règles", - "set-default-root-edge-rulechain-title": "AVoulez-vous vraiment créer de chaînes de règles par défaut '{{ruleChainName}}'?", - "set-default-root-edge-rulechain-text": "Après la confirmation, la chaîne de règles deviendra la racine de la bordure par défaut et gérera tous les messages de transport entrants.", - "invalid-rulechain-type-error": "Impossible d'importer la chaîne de règles: type de chaîne de règles non valide. Le type attendu est {{attenduRuleChainType}}.", - "set-default-edge": "Définir la chaîne de règles de la bordure par défaut", - "set-default-edge-title": "Voulez-vous vraiment définir la chaîne de règles de la bordure '{{ruleChainName}}' par défaut?", - "set-default-edge-text": "Après la confirmation, la chaîne de règles d'arête sera ajoutée à la liste par défaut et affectée aux arêtes nouvellement créées.", - "remove-default-edge": "Supprimer la chaîne de règles de la bordure des valeurs par défaut", - "remove-default-edge-title": "Voulez-vous vraiment supprimer la chaîne de règles de la bordure '{{ruleChainName}}' de la liste par défaut", - "remove-default-edge-text": "Après la confirmation, la chaîne de règles d'arête ne sera pas affectée aux arêtes nouvellement créées." + "system": "Système" }, "rulenode": { "add": "Ajouter un noeud de règle",