Browse Source

Added edge_id and assinged_edges to the TB entities

pull/2818/head
Volodymyr Babak 7 years ago
parent
commit
b03cf28a1a
  1. 37
      application/src/main/data/upgrade/2.4.x/schema_update.cql
  2. 10
      application/src/main/data/upgrade/2.4.x/schema_update.sql
  3. 1
      common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java
  4. 1
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  5. 9
      dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java
  6. 9
      dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java
  7. 35
      dao/src/main/resources/cassandra/schema-entities.cql
  8. 8
      dao/src/main/resources/sql/schema-entities.sql
  9. 123
      ui/src/app/edge/add-edges-to-customer.controller.js
  10. 77
      ui/src/app/edge/add-edges-to-customer.tpl.html
  11. 123
      ui/src/app/edge/assign-to-customer.controller.js
  12. 76
      ui/src/app/edge/assign-to-customer.tpl.html
  13. 438
      ui/src/app/edge/edge.controller.js

37
application/src/main/data/upgrade/2.4.x/schema_update.cql

@ -17,16 +17,45 @@
CREATE TABLE IF NOT EXISTS thingsboard.edge (
id timeuuid,
tenant_id timeuuid,
customer_id timeuuid,
name text,
search_text text,
configuration text,
additional_info text,
PRIMARY KEY (id, tenant_id)
);
);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_name AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( tenant_id, name, id, customer_id, type)
WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_search_text AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( tenant_id, search_text, id )
WITH CLUSTERING ORDER BY ( search_text ASC, id DESC );
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( tenant_id, search_text, id, customer_id, type)
WITH CLUSTERING ORDER BY ( search_text ASC, id DESC, customer_id DESC);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_by_type_and_search_text AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( tenant_id, type, search_text, id, customer_id)
WITH CLUSTERING ORDER BY ( type ASC, search_text ASC, id DESC, customer_id DESC);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_customer_and_search_text AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( customer_id, tenant_id, search_text, id, type )
WITH CLUSTERING ORDER BY ( tenant_id DESC, search_text ASC, id DESC );
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_customer_by_type_and_search_text AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );

10
application/src/main/data/upgrade/2.4.x/schema_update.sql

@ -17,8 +17,16 @@
CREATE TABLE IF NOT EXISTS edge (
id varchar(31) NOT NULL CONSTRAINT edge_pkey PRIMARY KEY,
additional_info varchar,
customer_id varchar(31),
configuration varchar(10000000),
name varchar(255),
search_text varchar(255),
tenant_id varchar(31)
);
);
ALTER TABLE asset ADD edge_id varchar(31);
ALTER TABLE device ADD edge_id varchar(31);
ALTER TABLE entity_view ADD edge_id varchar(31);
ALTER TABLE dashboard ADD assigned_edges varchar(1000000);
ALTER TABLE rule_chain ADD assigned_edges varchar(1000000);

1
common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java

@ -53,6 +53,7 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H
public Edge(Edge edge) {
super(edge);
this.tenantId = edge.getTenantId();
this.customerId = edge.getCustomerId();
this.name = edge.getName();
this.configuration = edge.getConfiguration();
this.additionalInfo = edge.getAdditionalInfo();

1
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -352,6 +352,7 @@ public class ModelConstants {
*/
public static final String EDGE_COLUMN_FAMILY_NAME = "edge";
public static final String EDGE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
public static final String EDGE_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
public static final String EDGE_NAME_PROPERTY = "name";
public static final String EDGE_CONFIGURATION_PROPERTY = "configuration";
public static final String EDGE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;

9
dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEntity.java

@ -23,6 +23,7 @@ import com.datastax.driver.mapping.annotations.Table;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.SearchTextEntity;
@ -33,6 +34,7 @@ import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ADDITIONAL_INFO_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CONFIGURATION_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
@ -50,6 +52,10 @@ public class EdgeEntity implements SearchTextEntity<Edge> {
@Column(name = EDGE_TENANT_ID_PROPERTY)
private UUID tenantId;
@ClusteringColumn
@Column(name = EDGE_CUSTOMER_ID_PROPERTY)
private UUID customerId;
@Column(name = EDGE_NAME_PROPERTY)
private String name;
@ -90,6 +96,9 @@ public class EdgeEntity implements SearchTextEntity<Edge> {
if (tenantId != null) {
edge.setTenantId(new TenantId(tenantId));
}
if (customerId != null) {
edge.setCustomerId(new CustomerId(customerId));
}
edge.setName(name);
edge.setConfiguration(configuration);
edge.setAdditionalInfo(additionalInfo);

9
dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java

@ -23,6 +23,7 @@ import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.UUIDConverter;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
@ -34,7 +35,9 @@ import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import static org.thingsboard.server.dao.model.ModelConstants.ASSET_CUSTOMER_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY;
@ -49,6 +52,9 @@ public class EdgeEntity extends BaseSqlEntity<Edge> implements SearchTextEntity<
@Column(name = EDGE_TENANT_ID_PROPERTY)
private String tenantId;
@Column(name = EDGE_CUSTOMER_ID_PROPERTY)
private String customerId;
@Column(name = EDGE_NAME_PROPERTY)
private String name;
@ -100,6 +106,9 @@ public class EdgeEntity extends BaseSqlEntity<Edge> implements SearchTextEntity<
if (tenantId != null) {
edge.setTenantId(new TenantId(UUIDConverter.fromString(tenantId)));
}
if (customerId != null) {
edge.setCustomerId(new CustomerId(UUIDConverter.fromString(customerId)));
}
edge.setName(name);
edge.setConfiguration(configuration);
edge.setAdditionalInfo(additionalInfo);

35
dao/src/main/resources/cassandra/schema-entities.cql

@ -716,6 +716,7 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.entity_view_by_tenant_and_ent
CREATE TABLE IF NOT EXISTS thingsboard.edge (
id timeuuid,
tenant_id timeuuid,
customer_id timeuuid,
name text,
search_text text,
configuration text,
@ -723,9 +724,37 @@ CREATE TABLE IF NOT EXISTS thingsboard.edge (
PRIMARY KEY (id, tenant_id)
);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_name AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( tenant_id, name, id, customer_id, type)
WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_search_text AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( tenant_id, search_text, id )
WITH CLUSTERING ORDER BY ( search_text ASC, id DESC );
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( tenant_id, search_text, id, customer_id, type)
WITH CLUSTERING ORDER BY ( search_text ASC, id DESC, customer_id DESC);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_by_type_and_search_text AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( tenant_id, type, search_text, id, customer_id)
WITH CLUSTERING ORDER BY ( type ASC, search_text ASC, id DESC, customer_id DESC);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_customer_and_search_text AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( customer_id, tenant_id, search_text, id, type )
WITH CLUSTERING ORDER BY ( tenant_id DESC, search_text ASC, id DESC );
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_customer_by_type_and_search_text AS
SELECT *
from thingsboard.edge
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );

8
dao/src/main/resources/sql/schema-entities.sql

@ -41,6 +41,7 @@ CREATE TABLE IF NOT EXISTS asset (
id varchar(31) NOT NULL CONSTRAINT asset_pkey PRIMARY KEY,
additional_info varchar,
customer_id varchar(31),
edge_id varchar(31),
name varchar(255),
search_text varchar(255),
tenant_id varchar(31),
@ -106,6 +107,7 @@ CREATE TABLE IF NOT EXISTS dashboard (
id varchar(31) NOT NULL CONSTRAINT dashboard_pkey PRIMARY KEY,
configuration varchar(10000000),
assigned_customers varchar(1000000),
assigned_edges varchar(1000000),
search_text varchar(255),
tenant_id varchar(31),
title varchar(255)
@ -115,6 +117,7 @@ CREATE TABLE IF NOT EXISTS device (
id varchar(31) NOT NULL CONSTRAINT device_pkey PRIMARY KEY,
additional_info varchar,
customer_id varchar(31),
edge_id varchar(31),
type varchar(255),
name varchar(255),
label varchar(255),
@ -215,7 +218,8 @@ CREATE TABLE IF NOT EXISTS rule_chain (
root boolean,
debug_mode boolean,
search_text varchar(255),
tenant_id varchar(31)
tenant_id varchar(31),
assigned_edges varchar(1000000)
);
CREATE TABLE IF NOT EXISTS rule_node (
@ -235,6 +239,7 @@ CREATE TABLE IF NOT EXISTS entity_view (
entity_type varchar(255),
tenant_id varchar(31),
customer_id varchar(31),
edge_id varchar(31),
type varchar(255),
name varchar(255),
keys varchar(10000000),
@ -247,6 +252,7 @@ CREATE TABLE IF NOT EXISTS entity_view (
CREATE TABLE IF NOT EXISTS edge (
id varchar(31) NOT NULL CONSTRAINT edge_pkey PRIMARY KEY,
additional_info varchar,
customer_id varchar(31),
configuration varchar(10000000),
name varchar(255),
search_text varchar(255),

123
ui/src/app/edge/add-edges-to-customer.controller.js

@ -0,0 +1,123 @@
/*
* Copyright © 2016-2019 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.
*/
/*@ngInject*/
export default function AddEdgesToCustomerController(edgeService, $mdDialog, $q, customerId, edges) {
var vm = this;
vm.edges = edges;
vm.searchText = '';
vm.assign = assign;
vm.cancel = cancel;
vm.hasData = hasData;
vm.noData = noData;
vm.searchEdgeTextUpdated = searchEdgeTextUpdated;
vm.toggleEdgeSelection = toggleEdgeSelection;
vm.theEdges = {
getItemAtIndex: function (index) {
if (index > vm.edges.data.length) {
vm.theEdges.fetchMoreItems_(index);
return null;
}
var item = vm.edges.data[index];
if (item) {
item.indexNumber = index + 1;
}
return item;
},
getLength: function () {
if (vm.edges.hasNext) {
return vm.edges.data.length + vm.edges.nextPageLink.limit;
} else {
return vm.edges.data.length;
}
},
fetchMoreItems_: function () {
if (vm.edges.hasNext && !vm.edges.pending) {
vm.edges.pending = true;
edgeService.getTenantEdges(vm.edges.nextPageLink, false).then(
function success(edges) {
vm.edges.data = vm.edges.data.concat(edges.data);
vm.edges.nextPageLink = edges.nextPageLink;
vm.edges.hasNext = edges.hasNext;
if (vm.edges.hasNext) {
vm.edges.nextPageLink.limit = vm.edges.pageSize;
}
vm.edges.pending = false;
},
function fail() {
vm.edges.hasNext = false;
vm.edges.pending = false;
});
}
}
};
function cancel () {
$mdDialog.cancel();
}
function assign() {
var tasks = [];
for (var edgeId in vm.edges.selections) {
tasks.push(edgeService.assignEdgeToCustomer(customerId, edgeId));
}
$q.all(tasks).then(function () {
$mdDialog.hide();
});
}
function noData() {
return vm.edges.data.length == 0 && !vm.edges.hasNext;
}
function hasData() {
return vm.edges.data.length > 0;
}
function toggleEdgeSelection($event, edge) {
$event.stopPropagation();
var selected = angular.isDefined(edge.selected) && edge.selected;
edge.selected = !selected;
if (edge.selected) {
vm.edges.selections[edge.id.id] = true;
vm.edges.selectedCount++;
} else {
delete vm.edges.selections[edge.id.id];
vm.edges.selectedCount--;
}
}
function searchEdgeTextUpdated() {
vm.edges = {
pageSize: vm.edges.pageSize,
data: [],
nextPageLink: {
limit: vm.edges.pageSize,
textSearch: vm.searchText
},
selections: {},
selectedCount: 0,
hasNext: true,
pending: false
};
}
}

77
ui/src/app/edge/add-edges-to-customer.tpl.html

@ -0,0 +1,77 @@
<!--
Copyright © 2016-2019 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.
-->
<md-dialog aria-label="{{ 'edge.assign-to-customer' | translate }}">
<form name="theForm" ng-submit="vm.assign()">
<md-toolbar>
<div class="md-toolbar-tools">
<h2 translate>edge.assign-edge-to-customer</h2>
<span flex></span>
<md-button class="md-icon-button" ng-click="vm.cancel()">
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon>
</md-button>
</div>
</md-toolbar>
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear>
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span>
<md-dialog-content>
<div class="md-dialog-content">
<fieldset>
<span translate>edge.assign-edge-to-customer-text</span>
<md-input-container class="md-block" style='margin-bottom: 0px;'>
<label>&nbsp;</label>
<md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">
search
</md-icon>
<input id="edge-search" autofocus ng-model="vm.searchText"
ng-change="vm.searchEdgeTextUpdated()"
placeholder="{{ 'common.enter-search' | translate }}"/>
</md-input-container>
<div style='min-height: 150px;'>
<span translate layout-align="center center"
style="text-transform: uppercase; display: flex; height: 150px;"
class="md-subhead"
ng-show="vm.noData()">edge.no-edges-text</span>
<md-virtual-repeat-container ng-show="vm.hasData()"
tb-scope-element="repeatContainer" md-top-index="vm.topIndex" flex
style='min-height: 150px; width: 100%;'>
<md-list>
<md-list-item md-virtual-repeat="edge in vm.theEdges" md-on-demand
class="repeated-item" flex>
<md-checkbox ng-click="vm.toggleEdgeSelection($event, edge)"
aria-label="{{ 'item.selected' | translate }}"
ng-checked="edge.selected"></md-checkbox>
<span> {{ edge.name }} </span>
</md-list-item>
</md-list>
</md-virtual-repeat-container>
</div>
</fieldset>
</div>
</md-dialog-content>
<md-dialog-actions layout="row">
<span flex></span>
<md-button ng-disabled="$root.loading || vm.edges.selectedCount == 0" type="submit"
class="md-raised md-primary">
{{ 'action.assign' | translate }}
</md-button>
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' |
translate }}
</md-button>
</md-dialog-actions>
</form>
</md-dialog>

123
ui/src/app/edge/assign-to-customer.controller.js

@ -0,0 +1,123 @@
/*
* Copyright © 2016-2019 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.
*/
/*@ngInject*/
export default function AssignEdgeToCustomerController(customerService, edgeService, $mdDialog, $q, edgeIds, customers) {
var vm = this;
vm.customers = customers;
vm.searchText = '';
vm.assign = assign;
vm.cancel = cancel;
vm.isCustomerSelected = isCustomerSelected;
vm.hasData = hasData;
vm.noData = noData;
vm.searchCustomerTextUpdated = searchCustomerTextUpdated;
vm.toggleCustomerSelection = toggleCustomerSelection;
vm.theCustomers = {
getItemAtIndex: function (index) {
if (index > vm.customers.data.length) {
vm.theCustomers.fetchMoreItems_(index);
return null;
}
var item = vm.customers.data[index];
if (item) {
item.indexNumber = index + 1;
}
return item;
},
getLength: function () {
if (vm.customers.hasNext) {
return vm.customers.data.length + vm.customers.nextPageLink.limit;
} else {
return vm.customers.data.length;
}
},
fetchMoreItems_: function () {
if (vm.customers.hasNext && !vm.customers.pending) {
vm.customers.pending = true;
customerService.getCustomers(vm.customers.nextPageLink).then(
function success(customers) {
vm.customers.data = vm.customers.data.concat(customers.data);
vm.customers.nextPageLink = customers.nextPageLink;
vm.customers.hasNext = customers.hasNext;
if (vm.customers.hasNext) {
vm.customers.nextPageLink.limit = vm.customers.pageSize;
}
vm.customers.pending = false;
},
function fail() {
vm.customers.hasNext = false;
vm.customers.pending = false;
});
}
}
};
function cancel() {
$mdDialog.cancel();
}
function assign() {
var tasks = [];
for (var i=0;i<edgeIds.length;i++) {
tasks.push(edgeService.assignEdgeToCustomer(vm.customers.selection.id.id, edgeIds[i]));
}
$q.all(tasks).then(function () {
$mdDialog.hide();
});
}
function noData() {
return vm.customers.data.length == 0 && !vm.customers.hasNext;
}
function hasData() {
return vm.customers.data.length > 0;
}
function toggleCustomerSelection($event, customer) {
$event.stopPropagation();
if (vm.isCustomerSelected(customer)) {
vm.customers.selection = null;
} else {
vm.customers.selection = customer;
}
}
function isCustomerSelected(customer) {
return vm.customers.selection != null && customer &&
customer.id.id === vm.customers.selection.id.id;
}
function searchCustomerTextUpdated() {
vm.customers = {
pageSize: vm.customers.pageSize,
data: [],
nextPageLink: {
limit: vm.customers.pageSize,
textSearch: vm.searchText
},
selection: null,
hasNext: true,
pending: false
};
}
}

76
ui/src/app/edge/assign-to-customer.tpl.html

@ -0,0 +1,76 @@
<!--
Copyright © 2016-2019 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.
-->
<md-dialog aria-label="{{ 'edge.assign-edge-to-customer' | translate }}">
<form name="theForm" ng-submit="vm.assign()">
<md-toolbar>
<div class="md-toolbar-tools">
<h2 translate>edge.assign-edge-to-customer</h2>
<span flex></span>
<md-button class="md-icon-button" ng-click="vm.cancel()">
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon>
</md-button>
</div>
</md-toolbar>
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear>
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span>
<md-dialog-content>
<div class="md-dialog-content">
<fieldset>
<span translate>edge.assign-to-customer-text</span>
<md-input-container class="md-block" style='margin-bottom: 0px;'>
<label>&nbsp;</label>
<md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">
search
</md-icon>
<input id="customer-search" autofocus ng-model="vm.searchText"
ng-change="vm.searchCustomerTextUpdated()"
placeholder="{{ 'common.enter-search' | translate }}"/>
</md-input-container>
<div style='min-height: 150px;'>
<span translate layout-align="center center"
style="text-transform: uppercase; display: flex; height: 150px;"
class="md-subhead"
ng-show="vm.noData()">customer.no-customers-text</span>
<md-virtual-repeat-container ng-show="vm.hasData()"
tb-scope-element="repeatContainer" md-top-index="vm.topIndex" flex
style='min-height: 150px; width: 100%;'>
<md-list>
<md-list-item md-virtual-repeat="customer in vm.theCustomers" md-on-demand
class="repeated-item" flex>
<md-checkbox ng-click="vm.toggleCustomerSelection($event, customer)"
aria-label="{{ 'item.selected' | translate }}"
ng-checked="vm.isCustomerSelected(customer)"></md-checkbox>
<span> {{ customer.title }} </span>
</md-list-item>
</md-list>
</md-virtual-repeat-container>
</div>
</fieldset>
</div>
</md-dialog-content>
<md-dialog-actions layout="row">
<span flex></span>
<md-button ng-disabled="$root.loading || vm.customers.selection==null" type="submit" class="md-raised md-primary">
{{ 'action.assign' | translate }}
</md-button>
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' |
translate }}
</md-button>
</md-dialog-actions>
</form>
</md-dialog>

438
ui/src/app/edge/edge.controller.js

@ -17,6 +17,8 @@
import addEdgeTemplate from './add-edge.tpl.html';
import edgeCard from './edge-card.tpl.html';
import assignToCustomerTemplate from './assign-to-customer.tpl.html';
import addEdgesToCustomerTemplate from './add-edges-to-customer.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
@ -26,25 +28,62 @@ export function EdgeCardController(types) {
var vm = this;
vm.types = types;
vm.isAssignedToCustomer = function() {
if (vm.item && vm.item.customerId && vm.parentCtl.edgesScope === 'tenant' &&
vm.item.customerId.id != vm.types.id.nullUid && !vm.item.assignedCustomer.isPublic) {
return true;
}
return false;
}
vm.isPublic = function() {
if (vm.item && vm.item.assignedCustomer && vm.parentCtl.edgesScope === 'tenant' && vm.item.assignedCustomer.isPublic) {
return true;
}
return false;
}
}
/*@ngInject*/
export function EdgeController($rootScope, userService, edgeService, $state, $stateParams,
$document, $mdDialog, $q, $translate, types, securityTypes, userPermissionsService) {
export function EdgeController($rootScope, userService, edgeService, customerService, $state, $stateParams,
$document, $mdDialog, $q, $translate, types, importExport) {
var customerId = $stateParams.customerId;
var edgeActionsList = [];
var edgeGroupActionsList = [];
var edgeAddItemActionsList = [
{
onAction: function ($event) {
vm.grid.addItem($event);
},
name: function() { return $translate.instant('action.add') },
details: function() { return $translate.instant('edge.add-edge-text') },
icon: "insert_drive_file"
},
{
onAction: function ($event) {
importExport.importEntities($event, types.entityType.edge).then(
function() {
vm.grid.refreshList();
}
);
},
name: function() { return $translate.instant('action.import') },
details: function() { return $translate.instant('edge.import') },
icon: "file_upload"
}
];
var vm = this;
vm.types = types;
vm.edgeGridConfig = {
resource: securityTypes.resource.edge,
deleteItemTitleFunc: deleteEdgeTitle,
deleteItemContentFunc: deleteEdgeText,
deleteItemsTitleFunc: deleteEdgesTitle,
@ -61,6 +100,7 @@ export function EdgeController($rootScope, userService, edgeService, $state, $st
actionsList: edgeActionsList,
groupActionsList: edgeGroupActionsList,
addItemActions: edgeAddItemActionsList,
onGridInited: gridInited,
@ -68,7 +108,11 @@ export function EdgeController($rootScope, userService, edgeService, $state, $st
addItemText: function() { return $translate.instant('edge.add-edge-text') },
noItemsText: function() { return $translate.instant('edge.no-edges-text') },
itemDetailsText: function() { return $translate.instant('edge.edge-details') }
itemDetailsText: function() { return $translate.instant('edge.edge-details') },
isDetailsReadOnly: isCustomerUser,
isSelectionEnabled: function () {
return !isCustomerUser();
}
};
if (angular.isDefined($stateParams.items) && $stateParams.items !== null) {
@ -79,43 +123,205 @@ export function EdgeController($rootScope, userService, edgeService, $state, $st
vm.edgeGridConfig.topIndex = $stateParams.topIndex;
}
vm.edgesScope = $state.$current.data.edgesType;
vm.assignToCustomer = assignToCustomer;
vm.makePublic = makePublic;
vm.unassignFromCustomer = unassignFromCustomer;
initController();
function initController() {
var fetchEdgesFunction = function (pageLink, edgeType) {
return edgeService.getEdges(pageLink, true, edgeType);
};
var deleteEdgeFunction = function (edgeId) {
return edgeService.deleteEdge(edgeId);
};
var refreshEdgesParamsFunction = function() {
return {"topIndex": vm.topIndex};
};
edgeActionsList.push(
{
var fetchEdgesFunction = null;
var deleteEdgeFunction = null;
var refreshEdgesParamsFunction = null;
var user = userService.getCurrentUser();
if (user.authority === 'CUSTOMER_USER') {
vm.edgesScope = 'customer_user';
customerId = user.customerId;
}
if (customerId) {
vm.customerEdgesTitle = $translate.instant('customer.edges');
customerService.getShortCustomerInfo(customerId).then(
function success(info) {
if (info.isPublic) {
vm.customerEdgesTitle = $translate.instant('customer.public-edges');
}
}
);
}
if (vm.edgesScope === 'tenant') {
fetchEdgesFunction = function (pageLink, edgeType) {
return edgeService.getTenantEdges(pageLink, true, null, edgeType);
};
deleteEdgeFunction = function (edgeId) {
return edgeService.deleteEdge(edgeId);
};
refreshEdgesParamsFunction = function() {
return {"topIndex": vm.topIndex};
};
edgeActionsList.push({
onAction: function ($event, item) {
vm.grid.deleteItem($event, item);
makePublic($event, item);
},
name: function() { return $translate.instant('action.delete') },
details: function() { return $translate.instant('edge.delete') },
icon: "delete",
isEnabled: function() {
return userPermissionsService.hasGenericPermission(securityTypes.resource.edge, securityTypes.operation.delete);
name: function() { return $translate.instant('action.share') },
details: function() { return $translate.instant('edge.make-public') },
icon: "share",
isEnabled: function(edge) {
return edge && (!edge.customerId || edge.customerId.id === types.id.nullUid);
}
}
);
});
edgeActionsList.push(
{
onAction: function ($event, item) {
assignToCustomer($event, [ item.id.id ]);
},
name: function() { return $translate.instant('action.assign') },
details: function() { return $translate.instant('edge.assign-to-customer') },
icon: "assignment_ind",
isEnabled: function(edge) {
return edge && (!edge.customerId || edge.customerId.id === types.id.nullUid);
}
}
);
edgeActionsList.push(
{
onAction: function ($event, item) {
unassignFromCustomer($event, item, false);
},
name: function() { return $translate.instant('action.unassign') },
details: function() { return $translate.instant('edge.unassign-from-customer') },
icon: "assignment_return",
isEnabled: function(edge) {
return edge && edge.customerId && edge.customerId.id !== types.id.nullUid && !edge.assignedCustomer.isPublic;
}
}
);
edgeGroupActionsList.push(
{
onAction: function ($event) {
vm.grid.deleteItems($event);
edgeActionsList.push({
onAction: function ($event, item) {
unassignFromCustomer($event, item, true);
},
name: function() { return $translate.instant('edge.delete-edges') },
details: deleteEdgesActionTitle,
icon: "delete"
name: function() { return $translate.instant('action.make-private') },
details: function() { return $translate.instant('edge.make-private') },
icon: "reply",
isEnabled: function(edge) {
return edge && edge.customerId && edge.customerId.id !== types.id.nullUid && edge.assignedCustomer.isPublic;
}
});
edgeActionsList.push(
{
onAction: function ($event, item) {
vm.grid.deleteItem($event, item);
},
name: function() { return $translate.instant('action.delete') },
details: function() { return $translate.instant('edge.delete') },
icon: "delete"
}
);
edgeGroupActionsList.push(
{
onAction: function ($event, items) {
assignEdgesToCustomer($event, items);
},
name: function() { return $translate.instant('edge.assign-edges') },
details: function(selectedCount) {
return $translate.instant('edge.assign-edges-text', {count: selectedCount}, "messageformat");
},
icon: "assignment_ind"
}
);
edgeGroupActionsList.push(
{
onAction: function ($event) {
vm.grid.deleteItems($event);
},
name: function() { return $translate.instant('edge.delete-edges') },
details: deleteEdgesActionTitle,
icon: "delete"
}
);
} else if (vm.edgesScope === 'customer' || vm.edgesScope === 'customer_user') {
fetchEdgesFunction = function (pageLink, edgeType) {
return edgeService.getCustomerEdges(customerId, pageLink, true, null, edgeType);
};
deleteEdgeFunction = function (edgeId) {
return edgeService.unassignEdgeFromCustomer(edgeId);
};
refreshEdgesParamsFunction = function () {
return {"customerId": customerId, "topIndex": vm.topIndex};
};
if (vm.edgesScope === 'customer') {
edgeActionsList.push(
{
onAction: function ($event, item) {
unassignFromCustomer($event, item, false);
},
name: function() { return $translate.instant('action.unassign') },
details: function() { return $translate.instant('edge.unassign-from-customer') },
icon: "assignment_return",
isEnabled: function(edge) {
return edge && !edge.assignedCustomer.isPublic;
}
}
);
edgeActionsList.push(
{
onAction: function ($event, item) {
unassignFromCustomer($event, item, true);
},
name: function() { return $translate.instant('action.make-private') },
details: function() { return $translate.instant('edge.make-private') },
icon: "reply",
isEnabled: function(edge) {
return edge && edge.assignedCustomer.isPublic;
}
}
);
edgeGroupActionsList.push(
{
onAction: function ($event, items) {
unassignEdgesFromCustomer($event, items);
},
name: function() { return $translate.instant('edge.unassign-edges') },
details: function(selectedCount) {
return $translate.instant('edge.unassign-edges-action-title', {count: selectedCount}, "messageformat");
},
icon: "assignment_return"
}
);
vm.edgeGridConfig.addItemAction = {
onAction: function ($event) {
addEdgesToCustomer($event);
},
name: function() { return $translate.instant('edge.assign-edges') },
details: function() { return $translate.instant('edge.assign-new-edge') },
icon: "add"
};
} else if (vm.edgesScope === 'customer_user') {
vm.edgeGridConfig.addItemAction = {};
}
);
vm.edgeGridConfig.addItemActions = [];
}
vm.edgeGridConfig.refreshParamsFunc = refreshEdgesParamsFunction;
vm.edgeGridConfig.fetchItemsFunc = fetchEdgesFunction;
vm.edgeGridConfig.deleteItemFunc = deleteEdgeFunction;
@ -155,7 +361,19 @@ export function EdgeController($rootScope, userService, edgeService, $state, $st
edgeService.saveEdge(edge).then(
function success(savedEdge) {
$rootScope.$broadcast('edgeSaved');
deferred.resolve(savedEdge);
var edges = [ savedEdge ];
customerService.applyAssignedCustomersInfo(edges).then(
function success(items) {
if (items && items.length == 1) {
deferred.resolve(items[0]);
} else {
deferred.reject();
}
},
function fail() {
deferred.reject();
}
);
},
function fail() {
deferred.reject();
@ -163,4 +381,154 @@ export function EdgeController($rootScope, userService, edgeService, $state, $st
);
return deferred.promise;
}
function isCustomerUser() {
return vm.edgesScope === 'customer_user';
}
function assignToCustomer($event, edgeIds) {
if ($event) {
$event.stopPropagation();
}
var pageSize = 10;
customerService.getCustomers({limit: pageSize, textSearch: ''}).then(
function success(_customers) {
var customers = {
pageSize: pageSize,
data: _customers.data,
nextPageLink: _customers.nextPageLink,
selection: null,
hasNext: _customers.hasNext,
pending: false
};
if (customers.hasNext) {
customers.nextPageLink.limit = pageSize;
}
$mdDialog.show({
controller: 'AssignEdgeToCustomerController',
controllerAs: 'vm',
templateUrl: assignToCustomerTemplate,
locals: {edgeIds: edgeIds, customers: customers},
parent: angular.element($document[0].body),
fullscreen: true,
targetEvent: $event
}).then(function () {
vm.grid.refreshList();
}, function () {
});
},
function fail() {
});
}
function addEdgesToCustomer($event) {
if ($event) {
$event.stopPropagation();
}
var pageSize = 10;
edgeService.getTenantEdges({limit: pageSize, textSearch: ''}, false).then(
function success(_edges) {
var edges = {
pageSize: pageSize,
data: _edges.data,
nextPageLink: _edges.nextPageLink,
selections: {},
selectedCount: 0,
hasNext: _edges.hasNext,
pending: false
};
if (edges.hasNext) {
edges.nextPageLink.limit = pageSize;
}
$mdDialog.show({
controller: 'AddEdgesToCustomerController',
controllerAs: 'vm',
templateUrl: addEdgesToCustomerTemplate,
locals: {customerId: customerId, edges: edges},
parent: angular.element($document[0].body),
fullscreen: true,
targetEvent: $event
}).then(function () {
vm.grid.refreshList();
}, function () {
});
},
function fail() {
});
}
function assignEdgesToCustomer($event, items) {
var edgeIds = [];
for (var id in items.selections) {
edgeIds.push(id);
}
assignToCustomer($event, edgeIds);
}
function unassignFromCustomer($event, edge, isPublic) {
if ($event) {
$event.stopPropagation();
}
var title;
var content;
var label;
if (isPublic) {
title = $translate.instant('edge.make-private-edge-title', {edgeName: edge.name});
content = $translate.instant('edge.make-private-edge-text');
label = $translate.instant('edge.make-private');
} else {
title = $translate.instant('edge.unassign-edge-title', {edgeName: edge.name});
content = $translate.instant('edge.unassign-edge-text');
label = $translate.instant('edge.unassign-edge');
}
var confirm = $mdDialog.confirm()
.targetEvent($event)
.title(title)
.htmlContent(content)
.ariaLabel(label)
.cancel($translate.instant('action.no'))
.ok($translate.instant('action.yes'));
$mdDialog.show(confirm).then(function () {
edgeService.unassignEdgeFromCustomer(edge.id.id).then(function success() {
vm.grid.refreshList();
});
});
}
function unassignEdgesFromCustomer($event, items) {
var confirm = $mdDialog.confirm()
.targetEvent($event)
.title($translate.instant('edge.unassign-edges-title', {count: items.selectedCount}, 'messageformat'))
.htmlContent($translate.instant('edge.unassign-edges-text'))
.ariaLabel($translate.instant('edge.unassign-edge'))
.cancel($translate.instant('action.no'))
.ok($translate.instant('action.yes'));
$mdDialog.show(confirm).then(function () {
var tasks = [];
for (var id in items.selections) {
tasks.push(edgeService.unassignEdgeFromCustomer(id));
}
$q.all(tasks).then(function () {
vm.grid.refreshList();
});
});
}
function makePublic($event, edge) {
if ($event) {
$event.stopPropagation();
}
var confirm = $mdDialog.confirm()
.targetEvent($event)
.title($translate.instant('edge.make-public-edge-title', {edgeName: edge.name}))
.htmlContent($translate.instant('edge.make-public-edge-text'))
.ariaLabel($translate.instant('edge.make-public'))
.cancel($translate.instant('action.no'))
.ok($translate.instant('action.yes'));
$mdDialog.show(confirm).then(function () {
edgeService.makeEdgePublic(edge.id.id).then(function success() {
vm.grid.refreshList();
});
});
}
}

Loading…
Cancel
Save