Browse Source

Merged UI-NGX with develop/3.0-edge-fixed

pull/3811/head
deaflynx 6 years ago
parent
commit
5a07a7aca4
  1. 14
      ui-ngx/src/app/core/http/asset.service.ts
  2. 4
      ui-ngx/src/app/core/http/component-descriptor.service.ts
  3. 15
      ui-ngx/src/app/core/http/dashboard.service.ts
  4. 14
      ui-ngx/src/app/core/http/device.service.ts
  5. 94
      ui-ngx/src/app/core/http/edge.service.ts
  6. 15
      ui-ngx/src/app/core/http/entity-view.service.ts
  7. 54
      ui-ngx/src/app/core/http/entity.service.ts
  8. 1
      ui-ngx/src/app/core/http/public-api.ts
  9. 49
      ui-ngx/src/app/core/http/rule-chain.service.ts
  10. 40
      ui-ngx/src/app/core/services/menu.service.ts
  11. 8
      ui-ngx/src/app/modules/home/dialogs/add-entities-to-customer-dialog.component.ts
  12. 57
      ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.html
  13. 142
      ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.ts
  14. 7
      ui-ngx/src/app/modules/home/dialogs/home-dialogs.module.ts
  15. 120
      ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts
  16. 139
      ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts
  17. 23
      ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.html
  18. 49
      ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.scss
  19. 42
      ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.ts
  20. 51
      ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.html
  21. 38
      ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.ts
  22. 124
      ui-ngx/src/app/modules/home/pages/edge/edge.component.html
  23. 18
      ui-ngx/src/app/modules/home/pages/edge/edge.component.scss
  24. 138
      ui-ngx/src/app/modules/home/pages/edge/edge.component.ts
  25. 42
      ui-ngx/src/app/modules/home/pages/edge/edge.module.ts
  26. 509
      ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts
  27. 3
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts
  28. 4
      ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts
  29. 5
      ui-ngx/src/app/shared/components/entity/entity-autocomplete.component.ts
  30. 13
      ui-ngx/src/app/shared/components/entity/entity-subtype-autocomplete.component.ts
  31. 14
      ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts
  32. 13
      ui-ngx/src/app/shared/components/entity/entity-subtype-select.component.ts
  33. 15
      ui-ngx/src/app/shared/models/alias.models.ts
  34. 2
      ui-ngx/src/app/shared/models/asset.models.ts
  35. 8
      ui-ngx/src/app/shared/models/audit-log.models.ts
  36. 1
      ui-ngx/src/app/shared/models/constants.ts
  37. 42
      ui-ngx/src/app/shared/models/edge.models.ts
  38. 21
      ui-ngx/src/app/shared/models/entity-type.models.ts
  39. 26
      ui-ngx/src/app/shared/models/id/edge-id.ts
  40. 1
      ui-ngx/src/app/shared/models/public-api.ts
  41. 11
      ui-ngx/src/app/shared/models/rule-chain.models.ts
  42. 172
      ui-ngx/src/assets/locale/locale.constant-de_DE.json
  43. 251
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  44. 165
      ui-ngx/src/assets/locale/locale.constant-es_ES.json
  45. 174
      ui-ngx/src/assets/locale/locale.constant-fr_FR.json

14
ui-ngx/src/app/core/http/asset.service.ts

@ -89,4 +89,18 @@ export class AssetService {
return this.http.get<Asset>(`/api/tenant/assets?assetName=${assetName}`, defaultHttpOptionsFromConfig(config));
}
public assignAssetToEdge(edgeId: string, assetId: string, config?: RequestConfig): Observable<Asset> {
return this.http.post<Asset>(`/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<PageData<AssetInfo>> {
return this.http.get<PageData<AssetInfo>>(`/api/edge/${edgeId}/assets${pageLink.toQuery()}&type=${type}`,
defaultHttpOptionsFromConfig(config));
}
}

4
ui-ngx/src/app/core/http/component-descriptor.service.ts

@ -53,7 +53,7 @@ export class ComponentDescriptorService {
}
}
public getComponentDescriptorsByTypes(componentTypes: Array<ComponentType>,
public getComponentDescriptorsByTypes(componentTypes: Array<ComponentType>, type: string,
config?: RequestConfig): Observable<Array<ComponentDescriptor>> {
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<Array<ComponentDescriptor>>(`/api/components?componentTypes=${componentTypes.join(',')}`,
return this.http.get<Array<ComponentDescriptor>>(`/api/components/${type}?componentTypes=${componentTypes.join(',')}`,
defaultHttpOptionsFromConfig(config)).pipe(
map((componentDescriptors) => {
componentDescriptors.forEach((componentDescriptor) => {

15
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<PageData<DashboardInfo>> {
return this.http.get<PageData<DashboardInfo>>(`/api/edge/${edgeId}/dashboards${pageLink.toQuery()}&type=${type}`,
defaultHttpOptionsFromConfig(config))
}
public assignDashboardToEdge(edgeId: string, dashboardId: string, config?: RequestConfig): Observable<Dashboard> {
return this.http.post<Dashboard>(`/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));
}
}

14
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<Device> {
return this.http.post<Device>(`/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<PageData<DeviceInfo>> {
return this.http.get<PageData<DeviceInfo>>(`/api/edge/${edgeId}/devices${pageLink.toQuery()}&type=${type}`,
defaultHttpOptionsFromConfig(config))
}
}

94
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<string>, config?: RequestConfig): Observable<Array<Edge>> {
return this.http.get<Array<Edge>>(`/api/edges?edgeIds=${edgeIds.join(',')}`,
defaultHttpOptionsFromConfig(config));
}
public getEdge(edgeId: string, config?: RequestConfig): Observable<EdgeInfo> {
return this.http.get<EdgeInfo>(`/api/edge/${edgeId}`, defaultHttpOptionsFromConfig(config));
}
public saveEdge(edge: Edge, config?: RequestConfig): Observable<Edge> {
return this.http.post<Edge>('/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<Array<EntitySubtype>> {
return this.http.get<Array<EntitySubtype>>('/api/edge/types', defaultHttpOptionsFromConfig(config));
}
public getTenantEdges(pageLink: PageLink, type: string = '',
config?: RequestConfig): Observable<PageData<EdgeInfo>> {
return this.http.get<PageData<EdgeInfo>>(`/api/tenant/edges${pageLink.toQuery()}&type=${type}`,
defaultHttpOptionsFromConfig(config));
}
public getCustomerEdges(customerId: string, pageLink: PageLink, type: string = '',
config?: RequestConfig): Observable<PageData<EdgeInfo>> {
return this.http.get<PageData<EdgeInfo>>(`/api/customer/${customerId}/edges${pageLink.toQuery()}&type=${type}`,
defaultHttpOptionsFromConfig(config));
}
public assignEdgeToCustomer(customerId: string, edgeId: string, config?: RequestConfig): Observable<Edge> {
return this.http.post<Edge>(`/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<Edge> {
return this.http.post<Edge>(`/api/customer/public/edge/${edgeId}`, null, defaultHttpOptionsFromConfig(config));
}
public setRootRuleChain(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable<Edge> {
return this.http.post<Edge>(`/api/edge/${edgeId}/${ruleChainId}/root`, null, defaultHttpOptionsFromConfig(config));
}
public getTenantEdgeInfos(pageLink: PageLink, type: string = '',
config?: RequestConfig): Observable<PageData<EdgeInfo>> {
return this.http.get<PageData<EdgeInfo>>(`/api/tenant/edgeInfos${pageLink.toQuery()}&type=${type}`,
defaultHttpOptionsFromConfig(config));
}
public findByQuery(query: EdgeSearchQuery, config?: RequestConfig): Observable<Array<Edge>> {
return this.http.post<Array<Edge>>('/api/edges', query, defaultHttpOptionsFromConfig(config));
}
}

15
ui-ngx/src/app/core/http/entity-view.service.ts

@ -83,4 +83,19 @@ export class EntityViewService {
return this.http.post<Array<EntityView>>('/api/entityViews', query, defaultHttpOptionsFromConfig(config));
}
public assignEntityViewToEdge(edgeId: string, entityViewId: string, config?: RequestConfig): Observable<EntityView> {
return this.http.post<EntityView>(`/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<PageData<EntityViewInfo>> {
return this.http.get<PageData<EntityViewInfo>>(`/api/edge/${edgeId}/entityViews${pageLink.toQuery()}&type=${type}`,
defaultHttpOptionsFromConfig(config))
}
}

54
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<AppState>,
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;

1
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';

49
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<PageData<RuleChain>> {
return this.http.get<PageData<RuleChain>>(`/api/ruleChains${pageLink.toQuery()}`,
public getRuleChains(pageLink: PageLink, type: string, config?: RequestConfig): Observable<PageData<RuleChain>> {
return this.http.get<PageData<RuleChain>>(`/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<Array<RuleNodeComponentDescriptor>> {
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<Array<RuleNodeComponentDescriptor>> {
return this.componentDescriptorService.getComponentDescriptorsByTypes(ruleNodeTypeComponentTypes, config).pipe(
private loadRuleNodeComponents(type: string, config?: RequestConfig): Observable<Array<RuleNodeComponentDescriptor>> {
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<PageData<RuleChain>> {
return this.http.get<PageData<RuleChain>>(`/api/edge/${edgeId}/ruleChains${pageLink.toQuery()}`,
defaultHttpOptionsFromConfig(config) )
}
public getEdgesRuleChains(pageLink: PageLink, config?: RequestConfig): Observable<PageData<RuleChain>> {
return this.getRuleChains(pageLink, ruleChainType.edge, config);
}
public assignRuleChainToEdge(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable<RuleChain> {
return this.http.post<RuleChain>(`/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<RuleChain> {
return this.http.post<RuleChain>(`/api/ruleChain/${ruleChainId}/defaultRootEdge`, defaultHttpOptionsFromConfig(config));
}
public addDefaultEdgeRuleChain(ruleChainId: string, config?: RequestConfig): Observable<RuleChain> {
return this.http.post<RuleChain>(`/api/ruleChain/${ruleChainId}/defaultEdge`, defaultHttpOptionsFromConfig(config));
}
public removeDefaultEdgeRuleChain(ruleChainId: string, config?: RequestConfig): Observable<RuleChain> {
return this.http.delete<RuleChain>(`/api/ruleChain/${ruleChainId}/defaultEdge`, defaultHttpOptionsFromConfig(config));
}
public getDefaultEdgeRuleChains(pageLink: PageLink, config?: RequestConfig): Observable<PageData<RuleChain>> {
return this.http.get<PageData<RuleChain>>(`/api/ruleChain/defaultEdgeRuleChains${pageLink.toQuery()}`,
defaultHttpOptionsFromConfig(config));
}
}

40
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: [

8
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:

57
ui-ngx/src/app/modules/home/dialogs/add-entities-to-edge-dialog.component.html

@ -0,0 +1,57 @@
<!--
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.
-->
<form [formGroup]="addEntitiesToEdgeFormGroup" (ngSubmit)="assign()">
<mat-toolbar fxLayout="row" color="primary">
<h2>{{ assignToEdgeTitle | translate }}</h2>
<span fxFlex></span>
<button mat-button mat-icon-button
(click)="cancel()"
type="button">
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content>
<fieldset [disabled]="isLoading$ | async">
<span>{{ assignToEdgeText | translate }}</span>
<tb-entity-list
formControlName="entityIds"
required
[entityType]="entityType"
>
</tb-entity-list>
</fieldset>
</div>
<div mat-dialog-actions fxLayoutAlign="end center">
<button mat-raised-button color="primary"
type="submit"
[disabled]="(isLoading$ | async) || addEntitiesToEdgeFormGroup.invalid
|| !addEntitiesToEdgeFormGroup.dirty">
{{ 'action.assign' | translate }}
</button>
<button mat-button color="primary"
style="margin-right: 20px;"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }}
</button>
</div>
</form>

142
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<AddEntitiesToEdgeDialogComponent, boolean> implements OnInit, ErrorStateMatcher {
addEntitiesToEdgeFormGroup: FormGroup;
submitted = false;
entityType: EntityType;
assignToEdgeTitle: string;
assignToEdgeText: string;
constructor(protected store: Store<AppState>,
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<AddEntitiesToEdgeDialogComponent, boolean>,
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<string> = this.addEntitiesToEdgeFormGroup.get('entityIds').value;
const tasks: Observable<any>[] = [];
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<any> {
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);
}
}
}

7
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

120
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<EntityTableConfig<AssetInfo>> {
@ -65,11 +70,13 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse
private readonly config: EntityTableConfig<AssetInfo> = new EntityTableConfig<AssetInfo>();
private customerId: string;
private edgeId: string;
constructor(private store: Store<AppState>,
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<EntityTableConfig<Asse
assetType: ''
};
this.customerId = routeParams.customerId;
this.edgeId = routeParams.edgeId;
return this.store.pipe(select(selectAuthUser), take(1)).pipe(
tap((authUser) => {
if (authUser.authority === Authority.CUSTOMER_USER) {
@ -128,7 +136,13 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse
} else {
this.config.tableTitle = parentCustomer.title + ': ' + this.translate.instant('asset.assets');
}
} else {
} else if (this.edgeId) { // TODO: deaflynx: find better way - out of parentCustomer map
this.edgeService.getEdge(this.edgeId)
.pipe(map(edge =>
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<EntityTableConfig<Asse
this.config.entitiesFetchFunction = pageLink =>
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<EntityTableConfig<Asse
}
);
}
if (assetScope === 'edge') {
actions.push(
{
name: this.translate.instant('asset.unassign-from-edge'),
icon: 'portable_wifi_off',
isEnabled: (entity) => (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<EntityTableConfig<Asse
}
);
}
if (assetScope === 'edge') {
actions.push(
{
name: this.translate.instant('asset.unassign-assets-from-edge'),
icon: 'portable_wifi_off',
isEnabled: true,
onAction: ($event, entities) => this.unassignAssetsFromEdge($event, entities)
}
);
}
if (assetScope === 'customer') {
actions.push(
{
@ -277,6 +315,16 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse
}
);
}
if (assetScope === 'edge') {
actions.push(
{
name: this.translate.instant('asset.assign-new-asset'),
icon: 'add',
isEnabled: () => true,
onAction: ($event) => this.addAssetsToEdge($event)
}
);
}
return actions;
}
@ -309,6 +357,26 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse
});
}
addAssetsToEdge($event: Event) {
if ($event) {
$event.stopPropagation();
}
this.dialog.open<AddEntitiesToEdgeDialogComponent, AddEntitiesToEdgeDialogData,
boolean>(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<EntityTableConfig<Asse
return false;
}
unassignFromEdge($event: Event, asset: AssetInfo) {
if ($event) {
$event.stopPropagation();
}
this.dialogService.confirm(
this.translate.instant('asset.unassign-asset-from-edge-title', {assetName: asset.name}),
this.translate.instant('asset.unassign-asset-from-edge-text'),
this.translate.instant('action.no'),
this.translate.instant('action.yes'),
true
).subscribe((res) => {
if (res) {
this.assetService.unassignAssetFromEdge(asset.id.id).subscribe(
() => {
this.config.table.updateData();
}
);
}
}
);
}
unassignAssetsFromEdge($event: Event, assets: Array<AssetInfo>) {
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<any>[] = [];
assets.forEach(
(asset) => {
tasks.push(this.assetService.unassignAssetFromEdge(asset.id.id));
}
);
forkJoin(tasks).subscribe(
() => {
this.config.table.updateData();
}
);
}
}
);
}
}

139
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 { }

23
ui-ngx/src/app/modules/home/pages/edge/edge-table-header.component.html

@ -0,0 +1,23 @@
<!--
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.
-->
<tb-entity-subtype-select
[showLabel]="true"
[entityType]="entityType.EDGE"
[ngModel]="entitiesTableConfig.componentsData.edgeType"
(ngModelChange)="edgeTypeChanged($event)">
</tb-entity-subtype-select>

49
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;
}
}
}
}
}

42
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<EdgeInfo> {
entityType = EntityType;
constructor(protected store: Store<AppState>) {
super(store);
}
edgeTypeChanged(edgeType: string) {
this.entitiesTableConfig.componentsData.edgeType = edgeType;
this.entitiesTableConfig.table.resetSortAndFilter(true);
}
}

51
ui-ngx/src/app/modules/home/pages/edge/edge-tabs.component.html

@ -0,0 +1,51 @@
<!--
Copyright © 2016-2020 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<mat-tab *ngIf="entity"
label="{{ 'attribute.attributes' | translate }}" #attributesTab="matTab">
<tb-attribute-table [defaultAttributeScope]="attributeScopes.CLIENT_SCOPE"
[active]="attributesTab.isActive"
[entityId]="entity.id"
[entityName]="entity.name">
</tb-attribute-table>
</mat-tab>
<mat-tab *ngIf="entity"
label="{{ 'attribute.latest-telemetry' | translate }}" #telemetryTab="matTab">
<tb-attribute-table [defaultAttributeScope]="latestTelemetryTypes.LATEST_TELEMETRY"
disableAttributeScopeSelection
[active]="telemetryTab.isActive"
[entityId]="entity.id"
[entityName]="entity.name">
</tb-attribute-table>
</mat-tab>
<mat-tab *ngIf="entity"
label="{{ 'alarm.alarms' | translate }}" #alarmsTab="matTab">
<tb-alarm-table [active]="alarmsTab.isActive" [entityId]="entity.id"></tb-alarm-table>
</mat-tab>
<mat-tab *ngIf="entity"
label="{{ 'edge.events' | translate }}" #eventsTab="matTab">
<tb-event-table [defaultEventType]="eventTypes.ERROR" [active]="eventsTab.isActive" [tenantId]="entity.tenantId.id"
[entityId]="entity.id"></tb-event-table>
</mat-tab>
<mat-tab *ngIf="entity"
label="{{ 'relation.relations' | translate }}" #relationsTab="matTab">
<tb-relation-table [active]="relationsTab.isActive" [entityId]="entity.id"></tb-relation-table>
</mat-tab>
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
<tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id"></tb-audit-log-table>
</mat-tab>

38
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<EdgeInfo> {
constructor(protected store: Store<AppState>) {
super(store);
}
ngOnInit() {
super.ngOnInit();
}
}

124
ui-ngx/src/app/modules/home/pages/edge/edge.component.html

@ -0,0 +1,124 @@
<!--
Copyright © 2016-2020 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div class="tb-details-buttons" fxLayout.xs="column">
<button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'makePublic')"
[fxShow]="!isEdit && edgeScope === 'tenant' && !isAssignedToCustomer(entity) && !entity?.customerIsPublic">
{{'edge.make-public' | translate }}
</button>
<button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'assignToCustomer')"
[fxShow]="!isEdit && edgeScope === 'tenant' && !isAssignedToCustomer(entity)">
{{'edge.assign-to-customer' | translate }}
</button>
<button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'unassignFromCustomer')"
[fxShow]="!isEdit && (edgeScope === 'customer' || edgeScope === 'tenant') && isAssignedToCustomer(entity)">
{{ (entity?.customerIsPublic ? 'edge.make-private' : 'edge.unassign-from-customer') | translate }}
</button>
<button mat-raised-button color="primary" fxFlex.xs
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'delete')"
[fxShow]="!hideDelete() && !isEdit">
{{'edge.delete' | translate }}
</button>
<div fxLayout="row" fxLayout.xs="column">
<button mat-raised-button
ngxClipboard
(cbOnSuccess)="onEdgeIdCopied($event)"
[cbContent]="entity?.id?.id"
[fxShow]="!isEdit">
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon>
<span translate>edge.copy-id</span>
</button>
</div>
</div>
<div class="mat-padding" fxLayout="column">
<mat-form-field class="mat-block"
[fxShow]="!isEdit && isAssignedToCustomer(entity)
&& !entity?.customerIsPublic && edgeScope === 'tenant'">
<mat-label translate>edge.assigned-to-customer</mat-label>
<input matInput disabled [ngModel]="entity?.customerTitle">
</mat-form-field>
<div class="tb-small" style="padding-bottom: 10px; padding-left: 2px;"
[fxShow]="!isEdit && entity?.customerIsPublic && (edgeScope === 'customer' || edgeScope === 'tenant')">
{{ 'edge.public' | translate }}
</div>
<form [formGroup]="entityForm">
<fieldset [disabled]="(isLoading$ | async) || !isEdit">
<mat-form-field class="mat-block">
<mat-label translate>edge.name</mat-label>
<input matInput formControlName="name" required>
<mat-error *ngIf="entityForm.get('name').hasError('required')">
{{ 'edge.name-required' | translate }}
</mat-error>
</mat-form-field>
<tb-entity-subtype-autocomplete
formControlName="type"
[required]="true"
[entityType]="entityType.EDGE">
</tb-entity-subtype-autocomplete>
<mat-form-field class="mat-block">
<mat-label translate>edge.label</mat-label>
<input matInput formControlName="label">
</mat-form-field>
<div formGroupName="additionalInfo" fxLayout="column">
<mat-form-field class="mat-block">
<mat-label translate>edge.description</mat-label>
<textarea matInput formControlName="description" rows="2"></textarea>
</mat-form-field>
</div>
</fieldset>
<div fxLayout="row">
<fieldset fxFlex disabled>
<mat-form-field class="mat-block">
<mat-label translate>edge.edge-key</mat-label>
<input matInput formControlName="routingKey">
</mat-form-field>
</fieldset>
<button mat-button mat-icon-button
style="margin-top: 14px"
ngxClipboard
(cbOnSuccess)="onEdgeKeyCopied($event)"
[cbContent]="entity?.routingKey"
[fxShow]="!isEdit">
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon>
</button>
</div>
<div fxLayout="row">
<fieldset fxFlex disabled>
<mat-form-field class="mat-block">
<mat-label translate>edge.edge-secret</mat-label>
<input matInput formControlName="secret">
</mat-form-field>
</fieldset>
<button mat-button mat-icon-button
style="margin-top: 14px"
ngxClipboard
(cbOnSuccess)="onEdgeSecretCopied($event)"
[cbContent]="entity?.secret"
[fxShow]="!isEdit">
<mat-icon svgIcon="mdi:clipboard-arrow-left"></mat-icon>
</button>
</div>
</form>
</div>

18
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 {
}

138
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<EdgeInfo>{
entityType = EntityType;
edgeScope: 'tenant' | 'customer' | 'customer_user';
constructor(protected store: Store<AppState>,
protected translate: TranslateService,
@Inject('entity') protected entityValue: EdgeInfo,
@Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<EdgeInfo>,
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));
}
}

42
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 { }

509
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<EntityTableConfig<EdgeInfo>> {
private readonly config: EntityTableConfig<EdgeInfo> = new EntityTableConfig<EdgeInfo>();
private customerId: string;
constructor(private store: Store<AppState>,
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<EntityTableConfig<EdgeInfo>> {
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<EntityTableColumn<EdgeInfo>> {
const columns: Array<EntityTableColumn<EdgeInfo>> = [
new DateEntityTableColumn<EdgeInfo>('createdTime', 'common.created-time', this.datePipe, '150px'),
new EntityTableColumn<EdgeInfo>('name', 'edge.name', '25%'),
new EntityTableColumn<EdgeInfo>('type', 'edge.edge-type', '25%'),
new EntityTableColumn<EdgeInfo>('label', 'edge.label', '25%')
];
if (edgeScope === 'tenant') {
columns.push(
new EntityTableColumn<EdgeInfo>('customerTitle', 'customer.customer', '25%'),
new EntityTableColumn<EdgeInfo>('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<CellActionDescriptor<EdgeInfo>> {
const actions: Array<CellActionDescriptor<EdgeInfo>> = [];
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<GroupActionDescriptor<EdgeInfo>> {
const actions: Array<GroupActionDescriptor<EdgeInfo>> = [];
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<HeaderActionDescriptor> {
const actions: Array<HeaderActionDescriptor> = [];
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, AddEntitiesToCustomerDialogData,
boolean>(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<EdgeId>) {
if ($event) {
$event.stopPropagation();
}
this.dialog.open<AssignToCustomerDialogComponent, AssignToCustomerDialogData,
boolean>(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<EdgeInfo>) {
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<any>[] = [];
edges.forEach(
(edge) => {
tasks.push(this.edgeService.unassignEdgeFromCustomer(edge.id.id));
}
);
forkJoin(tasks).subscribe(
() => {
this.config.table.updateData();
}
);
}
}
);
}
onEdgeAction(action: EntityAction<EdgeInfo>): 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;
}
}
}

3
ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts

@ -109,7 +109,8 @@ export class RuleNodeComponentsResolver implements Resolve<Array<RuleNodeCompone
}
resolve(route: ActivatedRouteSnapshot): Observable<Array<RuleNodeComponentDescriptor>> {
return this.ruleChainService.getRuleNodeComponents(ruleNodeConfigResourcesModulesMap);
const type = route.data.type;
return this.ruleChainService.getRuleNodeComponents(ruleNodeConfigResourcesModulesMap, type);
}
}

4
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<EntityTableConfig<
this.config.deleteEntitiesTitle = count => 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);

5
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';

13
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;

14
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;

13
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;

15
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, string>(
[ 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 {

2
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<AssetId> {
tenantId?: TenantId;
customerId?: CustomerId;
edgeId?: EdgeId; //TODO: deaflynx: "edgeId?" ?
name: string;
type: string;
label: string;

8
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, string>(
[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']
]
);

1
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',

42
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<EdgeId> {
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<ShortCustomerInfo> //TODO: deaflynx check usage
}
export interface EdgeSearchQuery extends EntitySearchQuery {
edgeTypes: Array<string>;
}

21
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<EntityType | AliasEntityType, Enti
selectedEntities: 'asset.selected-assets'
}
],
[
EntityType.EDGE,
{
type: 'entity.type-edge',
typePlural: 'entity.type-edges',
list: 'entity.list-of-edges',
nameStartsWith: 'entity.edge-name-starts-with',
details: 'edge.edge-details',
add: 'edge.add',
noEntities: 'edge.no-edges-text',
search: 'edge.search',
selectedEntities: 'edge.selected-edges'
}
],
[
EntityType.ENTITY_VIEW,
{
@ -265,6 +280,12 @@ export const entityTypeResources = new Map<EntityType, EntityTypeResource<BaseDa
helpLinkId: 'assets'
}
],
[
EntityType.EDGE,
{
helpLinkId: 'edges'
}
],
[
EntityType.ENTITY_VIEW,
{

26
ui-ngx/src/app/shared/models/id/edge-id.ts

@ -0,0 +1,26 @@
///
/// Copyright © 2016-2020 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { EntityId } from './entity-id';
import { EntityType } from '@shared/models/entity-type.models';
export class EdgeId implements EntityId {
entityType = EntityType.EDGE;
id: string;
constructor(id: string) {
this.id = id;
}
}

1
ui-ngx/src/app/shared/models/public-api.ts

@ -29,6 +29,7 @@ export * from './contact-based.model';
export * from './customer.model';
export * from './dashboard.models';
export * from './device.models';
export * from './edge.models';
export * from './entity.models';
export * from './entity-type.models';
export * from './entity-view.models';

11
ui-ngx/src/app/shared/models/rule-chain.models.ts

@ -27,6 +27,7 @@ export interface RuleChain extends BaseData<RuleChainId> {
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'
}

172
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",

251
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",

165
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",

174
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",

Loading…
Cancel
Save