thingsboard-aplcache
Changes
application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java 4(+2 -2)
ui/src/app/api/dashboard.service.js 150(+104 -46)
ui/src/app/api/entity.service.js 43(+35 -8)
ui/src/app/api/user.service.js 4(+2 -2)
ui/src/app/common/types.constant.js 7(+7 -0)
ui/src/app/dashboard/dashboard.directive.js 29(+6 -23)
ui/src/app/dashboard/dashboard-card.scss 27(+27 -0)
ui/src/app/dashboard/dashboard-fieldset.tpl.html 27(+16 -11)
ui/src/app/dashboard/dashboards.controller.js 226(+122 -104)
ui/src/app/dashboard/index.js 4(+2 -2)
ui/src/app/locale/locale.constant.js 16(+14 -2)
Details
diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java
index a72f2f3..c78ad18 100644
--- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java
@@ -434,7 +434,6 @@ public abstract class BaseController {
try {
validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
DashboardInfo dashboardInfo = dashboardService.findDashboardInfoById(dashboardId);
- SecurityUser authUser = getCurrentUser();
checkDashboard(dashboardInfo);
return dashboardInfo;
} catch (Exception e) {
@@ -447,7 +446,7 @@ public abstract class BaseController {
checkTenantId(dashboard.getTenantId());
SecurityUser authUser = getCurrentUser();
if (authUser.getAuthority() == Authority.CUSTOMER_USER) {
- if (dashboard.getAssignedCustomers() == null || !dashboard.getAssignedCustomers().containsKey(authUser.getCustomerId().toString())) {
+ if (!dashboard.isAssignedToCustomer(authUser.getCustomerId())) {
throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
ThingsboardErrorCode.PERMISSION_DENIED);
}
diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java
index 30d57f3..a4664a5 100644
--- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java
@@ -18,10 +18,7 @@ package org.thingsboard.server.controller;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
-import org.thingsboard.server.common.data.Customer;
-import org.thingsboard.server.common.data.Dashboard;
-import org.thingsboard.server.common.data.DashboardInfo;
-import org.thingsboard.server.common.data.EntityType;
+import org.thingsboard.server.common.data.*;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
@@ -34,6 +31,9 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.exception.ThingsboardException;
+import java.util.HashSet;
+import java.util.Set;
+
@RestController
@RequestMapping("/api")
public class DashboardController extends BaseController {
@@ -182,6 +182,158 @@ public class DashboardController extends BaseController {
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
+ @RequestMapping(value = "/dashboard/{dashboardId}/customers", method = RequestMethod.POST)
+ @ResponseBody
+ public Dashboard updateDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
+ @RequestBody String[] strCustomerIds) throws ThingsboardException {
+ checkParameter(DASHBOARD_ID, strDashboardId);
+ try {
+ DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
+ Dashboard dashboard = checkDashboardId(dashboardId);
+
+ Set<CustomerId> customerIds = new HashSet<>();
+ if (strCustomerIds != null) {
+ for (String strCustomerId : strCustomerIds) {
+ customerIds.add(new CustomerId(toUUID(strCustomerId)));
+ }
+ }
+
+ Set<CustomerId> addedCustomerIds = new HashSet<>();
+ Set<CustomerId> removedCustomerIds = new HashSet<>();
+ for (CustomerId customerId : customerIds) {
+ if (!dashboard.isAssignedToCustomer(customerId)) {
+ addedCustomerIds.add(customerId);
+ }
+ }
+
+ Set<ShortCustomerInfo> assignedCustomers = dashboard.getAssignedCustomers();
+ if (assignedCustomers != null) {
+ for (ShortCustomerInfo customerInfo : assignedCustomers) {
+ if (!customerIds.contains(customerInfo.getCustomerId())) {
+ removedCustomerIds.add(customerInfo.getCustomerId());
+ }
+ }
+ }
+
+ if (addedCustomerIds.isEmpty() && removedCustomerIds.isEmpty()) {
+ return dashboard;
+ } else {
+ Dashboard savedDashboard = null;
+ for (CustomerId customerId : addedCustomerIds) {
+ savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId));
+ ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId);
+ logEntityAction(dashboardId, savedDashboard,
+ customerId,
+ ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
+ }
+ for (CustomerId customerId : removedCustomerIds) {
+ ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId);
+ savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, customerId));
+ logEntityAction(dashboardId, dashboard,
+ customerId,
+ ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
+
+ }
+ return savedDashboard;
+ }
+ } catch (Exception e) {
+
+ logEntityAction(emptyId(EntityType.DASHBOARD), null,
+ null,
+ ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId);
+
+ throw handleException(e);
+ }
+ }
+
+ @PreAuthorize("hasAuthority('TENANT_ADMIN')")
+ @RequestMapping(value = "/dashboard/{dashboardId}/customers/add", method = RequestMethod.POST)
+ @ResponseBody
+ public Dashboard addDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
+ @RequestBody String[] strCustomerIds) throws ThingsboardException {
+ checkParameter(DASHBOARD_ID, strDashboardId);
+ try {
+ DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
+ Dashboard dashboard = checkDashboardId(dashboardId);
+
+ Set<CustomerId> customerIds = new HashSet<>();
+ if (strCustomerIds != null) {
+ for (String strCustomerId : strCustomerIds) {
+ CustomerId customerId = new CustomerId(toUUID(strCustomerId));
+ if (!dashboard.isAssignedToCustomer(customerId)) {
+ customerIds.add(customerId);
+ }
+ }
+ }
+
+ if (customerIds.isEmpty()) {
+ return dashboard;
+ } else {
+ Dashboard savedDashboard = null;
+ for (CustomerId customerId : customerIds) {
+ savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId));
+ ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId);
+ logEntityAction(dashboardId, savedDashboard,
+ customerId,
+ ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
+ }
+ return savedDashboard;
+ }
+ } catch (Exception e) {
+
+ logEntityAction(emptyId(EntityType.DASHBOARD), null,
+ null,
+ ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId);
+
+ throw handleException(e);
+ }
+ }
+
+ @PreAuthorize("hasAuthority('TENANT_ADMIN')")
+ @RequestMapping(value = "/dashboard/{dashboardId}/customers/remove", method = RequestMethod.POST)
+ @ResponseBody
+ public Dashboard removeDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
+ @RequestBody String[] strCustomerIds) throws ThingsboardException {
+ checkParameter(DASHBOARD_ID, strDashboardId);
+ try {
+ DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
+ Dashboard dashboard = checkDashboardId(dashboardId);
+
+ Set<CustomerId> customerIds = new HashSet<>();
+ if (strCustomerIds != null) {
+ for (String strCustomerId : strCustomerIds) {
+ CustomerId customerId = new CustomerId(toUUID(strCustomerId));
+ if (dashboard.isAssignedToCustomer(customerId)) {
+ customerIds.add(customerId);
+ }
+ }
+ }
+
+ if (customerIds.isEmpty()) {
+ return dashboard;
+ } else {
+ Dashboard savedDashboard = null;
+ for (CustomerId customerId : customerIds) {
+ ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId);
+ savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, customerId));
+ logEntityAction(dashboardId, dashboard,
+ customerId,
+ ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
+
+ }
+ return savedDashboard;
+ }
+ } catch (Exception e) {
+
+ logEntityAction(emptyId(EntityType.DASHBOARD), null,
+ null,
+ ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDashboardId);
+
+ throw handleException(e);
+ }
+ }
+
+ @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.POST)
@ResponseBody
public Dashboard assignDashboardToPublicCustomer(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
diff --git a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java
index d26565f..fa0dd2f 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java
@@ -15,12 +15,13 @@
*/
package org.thingsboard.server.service.install;
+import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.lang3.StringUtils;
-import com.fasterxml.jackson.databind.JsonNode;
+import org.thingsboard.server.common.data.ShortCustomerInfo;
import org.thingsboard.server.common.data.UUIDConverter;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
@@ -54,7 +55,8 @@ public class DatabaseHelper {
public static final ObjectMapper objectMapper = new ObjectMapper();
public static void upgradeTo40_assignDashboards(Path dashboardsDump, DashboardService dashboardService, boolean sql) throws Exception {
- String[] columns = new String[]{ID, TENANT_ID, CUSTOMER_ID, TITLE, SEARCH_TEXT, ASSIGNED_CUSTOMERS, CONFIGURATION};
+ JavaType assignedCustomersType =
+ objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortCustomerInfo.class);
try (CSVParser csvParser = new CSVParser(Files.newBufferedReader(dashboardsDump), CSV_DUMP_FORMAT.withFirstRecordAsHeader())) {
csvParser.forEach(record -> {
String customerIdString = record.get(CUSTOMER_ID);
@@ -63,12 +65,11 @@ public class DatabaseHelper {
List<CustomerId> customerIds = new ArrayList<>();
if (!StringUtils.isEmpty(assignedCustomersString)) {
try {
- JsonNode assignedCustomersJson = objectMapper.readTree(assignedCustomersString);
- Map<String,String> assignedCustomers = objectMapper.treeToValue(assignedCustomersJson, HashMap.class);
- assignedCustomers.forEach((strCustomerId, title) -> {
- CustomerId customerId = new CustomerId(UUID.fromString(strCustomerId));
+ Set<ShortCustomerInfo> assignedCustomers = objectMapper.readValue(assignedCustomersString, assignedCustomersType);
+ assignedCustomers.forEach((customerInfo) -> {
+ CustomerId customerId = customerInfo.getCustomerId();
if (!customerId.isNullUid()) {
- customerIds.add(new CustomerId(UUID.fromString(strCustomerId)));
+ customerIds.add(customerId);
}
});
} catch (IOException e) {
@@ -78,7 +79,7 @@ public class DatabaseHelper {
if (!StringUtils.isEmpty(customerIdString)) {
CustomerId customerId = new CustomerId(toUUID(customerIdString, sql));
if (!customerId.isNullUid()) {
- customerIds.add(new CustomerId(toUUID(customerIdString, sql)));
+ customerIds.add(customerId);
}
}
for (CustomerId customerId : customerIds) {
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java
index 434862b..d73e7ba 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java
@@ -138,10 +138,10 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest
Dashboard assignedDashboard = doPost("/api/customer/" + savedCustomer.getId().getId().toString()
+ "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
- Assert.assertTrue(assignedDashboard.getAssignedCustomers().containsKey(savedCustomer.getId().toString()));
+ Assert.assertTrue(assignedDashboard.getAssignedCustomers().contains(savedCustomer.toShortCustomerInfo()));
Dashboard foundDashboard = doGet("/api/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
- Assert.assertTrue(foundDashboard.getAssignedCustomers().containsKey(savedCustomer.getId().toString()));
+ Assert.assertTrue(foundDashboard.getAssignedCustomers().contains(savedCustomer.toShortCustomerInfo()));
Dashboard unassignedDashboard =
doDelete("/api/customer/"+savedCustomer.getId().getId().toString()+"/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java b/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java
index 1ee9cab..59431f3 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java
@@ -69,6 +69,11 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
return false;
}
+ @JsonIgnore
+ public ShortCustomerInfo toShortCustomerInfo() {
+ return new ShortCustomerInfo(id, title, isPublic());
+ }
+
@Override
@JsonProperty(access = Access.READ_ONLY)
public String getName() {
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java
index 7e18dc6..65a467d 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java
@@ -20,16 +20,13 @@ import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.TenantId;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
public class DashboardInfo extends SearchTextBased<DashboardId> implements HasName {
private TenantId tenantId;
private String title;
- private Map<String, String> assignedCustomers;
+ private Set<ShortCustomerInfo> assignedCustomers;
public DashboardInfo() {
super();
@@ -62,38 +59,56 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa
this.title = title;
}
- public Map<String, String> getAssignedCustomers() {
+ public Set<ShortCustomerInfo> getAssignedCustomers() {
return assignedCustomers;
}
- public void setAssignedCustomers(Map<String, String> assignedCustomers) {
+ public void setAssignedCustomers(Set<ShortCustomerInfo> assignedCustomers) {
this.assignedCustomers = assignedCustomers;
}
- public boolean addAssignedCustomer(CustomerId customerId, String title) {
- if (this.assignedCustomers != null && this.assignedCustomers.containsKey(customerId.toString())) {
+ public boolean isAssignedToCustomer(CustomerId customerId) {
+ return this.assignedCustomers != null && this.assignedCustomers.contains(new ShortCustomerInfo(customerId, null, false));
+ }
+
+ public ShortCustomerInfo getAssignedCustomerInfo(CustomerId customerId) {
+ if (this.assignedCustomers != null) {
+ for (ShortCustomerInfo customerInfo : this.assignedCustomers) {
+ if (customerInfo.getCustomerId().equals(customerId)) {
+ return customerInfo;
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean addAssignedCustomer(Customer customer) {
+ ShortCustomerInfo customerInfo = customer.toShortCustomerInfo();
+ if (this.assignedCustomers != null && this.assignedCustomers.contains(customerInfo)) {
return false;
} else {
if (this.assignedCustomers == null) {
- this.assignedCustomers = new HashMap<>();
+ this.assignedCustomers = new HashSet<>();
}
- this.assignedCustomers.put(customerId.toString(), title);
+ this.assignedCustomers.add(customerInfo);
return true;
}
}
- public boolean updateAssignedCustomer(CustomerId customerId, String title) {
- if (this.assignedCustomers != null && this.assignedCustomers.containsKey(customerId.toString())) {
- this.assignedCustomers.put(customerId.toString(), title);
+ public boolean updateAssignedCustomer(Customer customer) {
+ ShortCustomerInfo customerInfo = customer.toShortCustomerInfo();
+ if (this.assignedCustomers != null && this.assignedCustomers.contains(customerInfo)) {
+ this.assignedCustomers.add(customerInfo);
return true;
} else {
return false;
}
}
- public boolean removeAssignedCustomer(CustomerId customerId) {
- if (this.assignedCustomers != null && this.assignedCustomers.containsKey(customerId.toString())) {
- this.assignedCustomers.remove(customerId.toString());
+ public boolean removeAssignedCustomer(Customer customer) {
+ ShortCustomerInfo customerInfo = customer.toShortCustomerInfo();
+ if (this.assignedCustomers != null && this.assignedCustomers.contains(customerInfo)) {
+ this.assignedCustomers.remove(customerInfo);
return true;
} else {
return false;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ShortCustomerInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/ShortCustomerInfo.java
new file mode 100644
index 0000000..68ca46a
--- /dev/null
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/ShortCustomerInfo.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright © 2016-2017 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.
+ */
+package org.thingsboard.server.common.data;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import org.thingsboard.server.common.data.id.CustomerId;
+
+/**
+ * Created by igor on 2/27/18.
+ */
+
+@AllArgsConstructor
+public class ShortCustomerInfo {
+
+ @Getter @Setter
+ private CustomerId customerId;
+
+ @Getter @Setter
+ private String title;
+
+ @Getter @Setter
+ private boolean isPublic;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ShortCustomerInfo that = (ShortCustomerInfo) o;
+
+ return customerId.equals(that.customerId);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return customerId.hashCode();
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java
index f118aff..657bfba 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java
@@ -98,7 +98,7 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
log.trace("Executing saveCustomer [{}]", customer);
customerValidator.validate(customer);
Customer savedCustomer = customerDao.save(customer);
- dashboardService.updateCustomerDashboards(savedCustomer.getTenantId(), savedCustomer.getId(), savedCustomer.getTitle());
+ dashboardService.updateCustomerDashboards(savedCustomer.getId());
return savedCustomer;
}
@@ -110,7 +110,7 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
if (customer == null) {
throw new IncorrectParameterException("Unable to delete non-existent customer.");
}
- dashboardService.unassignCustomerDashboards(customer.getTenantId(), customerId);
+ dashboardService.unassignCustomerDashboards(customerId);
assetService.unassignCustomerAssets(customer.getTenantId(), customerId);
deviceService.unassignCustomerDevices(customer.getTenantId(), customerId);
userService.deleteCustomerUsers(customer.getTenantId(), customerId);
diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java
index f4af29c..06426e7 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java
@@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
-import java.sql.Time;
+import java.util.Set;
public interface DashboardService {
@@ -52,8 +52,8 @@ public interface DashboardService {
ListenableFuture<TimePageData<DashboardInfo>> findDashboardsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TimePageLink pageLink);
- void unassignCustomerDashboards(TenantId tenantId, CustomerId customerId);
+ void unassignCustomerDashboards(CustomerId customerId);
- void updateCustomerDashboards(TenantId tenantId, CustomerId customerId, String customerTitle);
+ void updateCustomerDashboards(CustomerId customerId);
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java
index b9fa3ab..741d313 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java
@@ -117,7 +117,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
if (!customer.getTenantId().getId().equals(dashboard.getTenantId().getId())) {
throw new DataValidationException("Can't assign dashboard to customer from different tenant!");
}
- if (dashboard.addAssignedCustomer(customerId, customer.getTitle())) {
+ if (dashboard.addAssignedCustomer(customer)) {
try {
createRelation(new EntityRelation(customerId, dashboardId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.DASHBOARD));
} catch (ExecutionException | InterruptedException e) {
@@ -133,7 +133,11 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
@Override
public Dashboard unassignDashboardFromCustomer(DashboardId dashboardId, CustomerId customerId) {
Dashboard dashboard = findDashboardById(dashboardId);
- if (dashboard.removeAssignedCustomer(customerId)) {
+ Customer customer = customerDao.findById(customerId.getId());
+ if (customer == null) {
+ throw new DataValidationException("Can't unassign dashboard from non-existent customer!");
+ }
+ if (dashboard.removeAssignedCustomer(customer)) {
try {
deleteRelation(new EntityRelation(customerId, dashboardId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.DASHBOARD));
} catch (ExecutionException | InterruptedException e) {
@@ -146,9 +150,9 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
}
}
- private Dashboard updateAssignedCustomerTitle(DashboardId dashboardId, CustomerId customerId, String customerTitle) {
+ private Dashboard updateAssignedCustomer(DashboardId dashboardId, Customer customer) {
Dashboard dashboard = findDashboardById(dashboardId);
- if (dashboard.updateAssignedCustomer(customerId, customerTitle)) {
+ if (dashboard.updateAssignedCustomer(customer)) {
return saveDashboard(dashboard);
} else {
return dashboard;
@@ -207,20 +211,25 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
}
@Override
- public void unassignCustomerDashboards(TenantId tenantId, CustomerId customerId) {
- log.trace("Executing unassignCustomerDashboards, tenantId [{}], customerId [{}]", tenantId, customerId);
- Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
+ public void unassignCustomerDashboards(CustomerId customerId) {
+ log.trace("Executing unassignCustomerDashboards, customerId [{}]", customerId);
Validator.validateId(customerId, "Incorrect customerId " + customerId);
- new CustomerDashboardsUnassigner(tenantId, customerId).removeEntities(customerId);
+ Customer customer = customerDao.findById(customerId.getId());
+ if (customer == null) {
+ throw new DataValidationException("Can't unassign dashboards from non-existent customer!");
+ }
+ new CustomerDashboardsUnassigner(customer).removeEntities(customer);
}
@Override
- public void updateCustomerDashboards(TenantId tenantId, CustomerId customerId, String customerTitle) {
- log.trace("Executing updateCustomerDashboards, tenantId [{}], customerId [{}], customerTitle [{}]", tenantId, customerId, customerTitle);
- Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
+ public void updateCustomerDashboards(CustomerId customerId) {
+ log.trace("Executing updateCustomerDashboards, customerId [{}]", customerId);
Validator.validateId(customerId, "Incorrect customerId " + customerId);
- Validator.validateString(customerTitle, "Incorrect customerTitle " + customerTitle);
- new CustomerDashboardsUpdater(tenantId, customerId, customerTitle).removeEntities(customerId);
+ Customer customer = customerDao.findById(customerId.getId());
+ if (customer == null) {
+ throw new DataValidationException("Can't update dashboards for non-existent customer!");
+ }
+ new CustomerDashboardsUpdater(customer).removeEntities(customer);
}
private DataValidator<Dashboard> dashboardValidator =
@@ -255,58 +264,52 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
}
};
- private class CustomerDashboardsUnassigner extends TimePaginatedRemover<CustomerId, DashboardInfo> {
-
- private TenantId tenantId;
- private CustomerId customerId;
+ private class CustomerDashboardsUnassigner extends TimePaginatedRemover<Customer, DashboardInfo> {
- CustomerDashboardsUnassigner(TenantId tenantId, CustomerId customerId) {
- this.tenantId = tenantId;
- this.customerId = customerId;
+ private Customer customer;
+
+ CustomerDashboardsUnassigner(Customer customer) {
+ this.customer = customer;
}
@Override
- protected List<DashboardInfo> findEntities(CustomerId id, TimePageLink pageLink) {
+ protected List<DashboardInfo> findEntities(Customer customer, TimePageLink pageLink) {
try {
- return dashboardInfoDao.findDashboardsByTenantIdAndCustomerId(tenantId.getId(), id.getId(), pageLink).get();
+ return dashboardInfoDao.findDashboardsByTenantIdAndCustomerId(customer.getTenantId().getId(), customer.getId().getId(), pageLink).get();
} catch (InterruptedException | ExecutionException e) {
- log.warn("Failed to get dashboards by tenantId [{}] and customerId [{}].", tenantId, id);
+ log.warn("Failed to get dashboards by tenantId [{}] and customerId [{}].", customer.getTenantId().getId(), customer.getId().getId());
throw new RuntimeException(e);
}
}
@Override
protected void removeEntity(DashboardInfo entity) {
- unassignDashboardFromCustomer(new DashboardId(entity.getUuidId()), this.customerId);
+ unassignDashboardFromCustomer(new DashboardId(entity.getUuidId()), this.customer.getId());
}
}
- private class CustomerDashboardsUpdater extends TimePaginatedRemover<CustomerId, DashboardInfo> {
+ private class CustomerDashboardsUpdater extends TimePaginatedRemover<Customer, DashboardInfo> {
- private TenantId tenantId;
- private CustomerId customerId;
- private String customerTitle;
+ private Customer customer;
- CustomerDashboardsUpdater(TenantId tenantId, CustomerId customerId, String customerTitle) {
- this.tenantId = tenantId;
- this.customerId = customerId;
- this.customerTitle = customerTitle;
+ CustomerDashboardsUpdater(Customer customer) {
+ this.customer = customer;
}
@Override
- protected List<DashboardInfo> findEntities(CustomerId id, TimePageLink pageLink) {
+ protected List<DashboardInfo> findEntities(Customer customer, TimePageLink pageLink) {
try {
- return dashboardInfoDao.findDashboardsByTenantIdAndCustomerId(tenantId.getId(), id.getId(), pageLink).get();
+ return dashboardInfoDao.findDashboardsByTenantIdAndCustomerId(customer.getTenantId().getId(), customer.getId().getId(), pageLink).get();
} catch (InterruptedException | ExecutionException e) {
- log.warn("Failed to get dashboards by tenantId [{}] and customerId [{}].", tenantId, id);
+ log.warn("Failed to get dashboards by tenantId [{}] and customerId [{}].", customer.getTenantId().getId(), customer.getId().getId());
throw new RuntimeException(e);
}
}
@Override
protected void removeEntity(DashboardInfo entity) {
- updateAssignedCustomerTitle(new DashboardId(entity.getUuidId()), this.customerId, this.customerTitle);
+ updateAssignedCustomer(new DashboardId(entity.getUuidId()), this.customer);
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/DashboardEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/DashboardEntity.java
index 8590c2a..0327232 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/DashboardEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/DashboardEntity.java
@@ -20,18 +20,22 @@ import com.datastax.driver.mapping.annotations.Column;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.Dashboard;
+import org.thingsboard.server.common.data.ShortCustomerInfo;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.SearchTextEntity;
import org.thingsboard.server.dao.model.type.JsonCodec;
-import java.util.HashMap;
+import java.io.IOException;
+import java.util.HashSet;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.*;
@@ -43,6 +47,8 @@ import static org.thingsboard.server.dao.model.ModelConstants.*;
public final class DashboardEntity implements SearchTextEntity<Dashboard> {
private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final JavaType assignedCustomersType =
+ objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortCustomerInfo.class);
@PartitionKey(value = 0)
@Column(name = ID_PROPERTY)
@@ -58,8 +64,8 @@ public final class DashboardEntity implements SearchTextEntity<Dashboard> {
@Column(name = SEARCH_TEXT_PROPERTY)
private String searchText;
- @Column(name = DASHBOARD_ASSIGNED_CUSTOMERS_PROPERTY, codec = JsonCodec.class)
- private JsonNode assignedCustomers;
+ @Column(name = DASHBOARD_ASSIGNED_CUSTOMERS_PROPERTY)
+ private String assignedCustomers;
@Column(name = DASHBOARD_CONFIGURATION_PROPERTY, codec = JsonCodec.class)
private JsonNode configuration;
@@ -77,7 +83,11 @@ public final class DashboardEntity implements SearchTextEntity<Dashboard> {
}
this.title = dashboard.getTitle();
if (dashboard.getAssignedCustomers() != null) {
- this.assignedCustomers = objectMapper.valueToTree(dashboard.getAssignedCustomers());
+ try {
+ this.assignedCustomers = objectMapper.writeValueAsString(dashboard.getAssignedCustomers());
+ } catch (JsonProcessingException e) {
+ log.error("Unable to serialize assigned customers to string!", e);
+ }
}
this.configuration = dashboard.getConfiguration();
}
@@ -106,11 +116,11 @@ public final class DashboardEntity implements SearchTextEntity<Dashboard> {
this.title = title;
}
- public JsonNode getAssignedCustomers() {
+ public String getAssignedCustomers() {
return assignedCustomers;
}
- public void setAssignedCustomers(JsonNode assignedCustomers) {
+ public void setAssignedCustomers(String assignedCustomers) {
this.assignedCustomers = assignedCustomers;
}
@@ -144,10 +154,10 @@ public final class DashboardEntity implements SearchTextEntity<Dashboard> {
dashboard.setTenantId(new TenantId(tenantId));
}
dashboard.setTitle(title);
- if (assignedCustomers != null) {
+ if (!StringUtils.isEmpty(assignedCustomers)) {
try {
- dashboard.setAssignedCustomers(objectMapper.treeToValue(assignedCustomers, HashMap.class));
- } catch (JsonProcessingException e) {
+ dashboard.setAssignedCustomers(objectMapper.readValue(assignedCustomers, assignedCustomersType));
+ } catch (IOException e) {
log.warn("Unable to parse assigned customers!", e);
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/DashboardInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/DashboardInfoEntity.java
index 609f3bb..f64bc44 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/DashboardInfoEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/DashboardInfoEntity.java
@@ -20,20 +20,20 @@ import com.datastax.driver.mapping.annotations.Column;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.DashboardInfo;
-import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.ShortCustomerInfo;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.SearchTextEntity;
-import org.thingsboard.server.dao.model.type.JsonCodec;
-import java.util.HashMap;
-import java.util.Set;
+import java.io.IOException;
+import java.util.HashSet;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.*;
@@ -45,6 +45,8 @@ import static org.thingsboard.server.dao.model.ModelConstants.*;
public class DashboardInfoEntity implements SearchTextEntity<DashboardInfo> {
private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final JavaType assignedCustomersType =
+ objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortCustomerInfo.class);
@PartitionKey(value = 0)
@Column(name = ID_PROPERTY)
@@ -60,8 +62,8 @@ public class DashboardInfoEntity implements SearchTextEntity<DashboardInfo> {
@Column(name = SEARCH_TEXT_PROPERTY)
private String searchText;
- @Column(name = DASHBOARD_ASSIGNED_CUSTOMERS_PROPERTY, codec = JsonCodec.class)
- private JsonNode assignedCustomers;
+ @Column(name = DASHBOARD_ASSIGNED_CUSTOMERS_PROPERTY)
+ private String assignedCustomers;
public DashboardInfoEntity() {
super();
@@ -76,7 +78,11 @@ public class DashboardInfoEntity implements SearchTextEntity<DashboardInfo> {
}
this.title = dashboardInfo.getTitle();
if (dashboardInfo.getAssignedCustomers() != null) {
- this.assignedCustomers = objectMapper.valueToTree(dashboardInfo.getAssignedCustomers());
+ try {
+ this.assignedCustomers = objectMapper.writeValueAsString(dashboardInfo.getAssignedCustomers());
+ } catch (JsonProcessingException e) {
+ log.error("Unable to serialize assigned customers to string!", e);
+ }
}
}
@@ -104,11 +110,11 @@ public class DashboardInfoEntity implements SearchTextEntity<DashboardInfo> {
this.title = title;
}
- public JsonNode getAssignedCustomers() {
+ public String getAssignedCustomers() {
return assignedCustomers;
}
- public void setAssignedCustomers(JsonNode assignedCustomers) {
+ public void setAssignedCustomers(String assignedCustomers) {
this.assignedCustomers = assignedCustomers;
}
@@ -134,10 +140,10 @@ public class DashboardInfoEntity implements SearchTextEntity<DashboardInfo> {
dashboardInfo.setTenantId(new TenantId(tenantId));
}
dashboardInfo.setTitle(title);
- if (assignedCustomers != null) {
+ if (!StringUtils.isEmpty(assignedCustomers)) {
try {
- dashboardInfo.setAssignedCustomers(objectMapper.treeToValue(assignedCustomers, HashMap.class));
- } catch (JsonProcessingException e) {
+ dashboardInfo.setAssignedCustomers(objectMapper.readValue(assignedCustomers, assignedCustomersType));
+ } catch (IOException e) {
log.warn("Unable to parse assigned customers!", e);
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java
index 6f7810b..99f65f0 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java
@@ -17,6 +17,7 @@ package org.thingsboard.server.dao.model.sql;
import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
@@ -24,8 +25,9 @@ import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
+import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.Dashboard;
-import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.ShortCustomerInfo;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
@@ -36,9 +38,8 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
+import java.io.IOException;
+import java.util.HashSet;
@Data
@Slf4j
@@ -49,6 +50,8 @@ import java.util.Set;
public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements SearchTextEntity<Dashboard> {
private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final JavaType assignedCustomersType =
+ objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortCustomerInfo.class);
@Column(name = ModelConstants.DASHBOARD_TENANT_ID_PROPERTY)
private String tenantId;
@@ -59,9 +62,8 @@ public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements S
@Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
private String searchText;
- @Type(type = "json")
@Column(name = ModelConstants.DASHBOARD_ASSIGNED_CUSTOMERS_PROPERTY)
- private JsonNode assignedCustomers;
+ private String assignedCustomers;
@Type(type = "json")
@Column(name = ModelConstants.DASHBOARD_CONFIGURATION_PROPERTY)
@@ -80,7 +82,11 @@ public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements S
}
this.title = dashboard.getTitle();
if (dashboard.getAssignedCustomers() != null) {
- this.assignedCustomers = objectMapper.valueToTree(dashboard.getAssignedCustomers());
+ try {
+ this.assignedCustomers = objectMapper.writeValueAsString(dashboard.getAssignedCustomers());
+ } catch (JsonProcessingException e) {
+ log.error("Unable to serialize assigned customers to string!", e);
+ }
}
this.configuration = dashboard.getConfiguration();
}
@@ -103,10 +109,10 @@ public final class DashboardEntity extends BaseSqlEntity<Dashboard> implements S
dashboard.setTenantId(new TenantId(toUUID(tenantId)));
}
dashboard.setTitle(title);
- if (assignedCustomers != null) {
+ if (!StringUtils.isEmpty(assignedCustomers)) {
try {
- dashboard.setAssignedCustomers(objectMapper.treeToValue(assignedCustomers, HashMap.class));
- } catch (JsonProcessingException e) {
+ dashboard.setAssignedCustomers(objectMapper.readValue(assignedCustomers, assignedCustomersType));
+ } catch (IOException e) {
log.warn("Unable to parse assigned customers!", e);
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java
index d9b8efe..7c295d1 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java
@@ -17,14 +17,14 @@ package org.thingsboard.server.dao.model.sql;
import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
-import org.hibernate.annotations.Type;
+import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.DashboardInfo;
-import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.ShortCustomerInfo;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
@@ -34,8 +34,8 @@ import org.thingsboard.server.dao.model.SearchTextEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
-import java.util.HashMap;
-import java.util.Set;
+import java.io.IOException;
+import java.util.HashSet;
@Data
@Slf4j
@@ -45,6 +45,8 @@ import java.util.Set;
public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements SearchTextEntity<DashboardInfo> {
private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final JavaType assignedCustomersType =
+ objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortCustomerInfo.class);
@Column(name = ModelConstants.DASHBOARD_TENANT_ID_PROPERTY)
private String tenantId;
@@ -55,9 +57,8 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements
@Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
private String searchText;
- @Type(type = "json")
@Column(name = ModelConstants.DASHBOARD_ASSIGNED_CUSTOMERS_PROPERTY)
- private JsonNode assignedCustomers;
+ private String assignedCustomers;
public DashboardInfoEntity() {
super();
@@ -72,7 +73,11 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements
}
this.title = dashboardInfo.getTitle();
if (dashboardInfo.getAssignedCustomers() != null) {
- this.assignedCustomers = objectMapper.valueToTree(dashboardInfo.getAssignedCustomers());
+ try {
+ this.assignedCustomers = objectMapper.writeValueAsString(dashboardInfo.getAssignedCustomers());
+ } catch (JsonProcessingException e) {
+ log.error("Unable to serialize assigned customers to string!", e);
+ }
}
}
@@ -98,10 +103,10 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements
dashboardInfo.setTenantId(new TenantId(toUUID(tenantId)));
}
dashboardInfo.setTitle(title);
- if (assignedCustomers != null) {
+ if (!StringUtils.isEmpty(assignedCustomers)) {
try {
- dashboardInfo.setAssignedCustomers(objectMapper.treeToValue(assignedCustomers, HashMap.class));
- } catch (JsonProcessingException e) {
+ dashboardInfo.setAssignedCustomers(objectMapper.readValue(assignedCustomers, assignedCustomersType));
+ } catch (IOException e) {
log.warn("Unable to parse assigned customers!", e);
}
}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java
index 0427fb4..380c65e 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java
@@ -320,7 +320,7 @@ public abstract class BaseDashboardServiceTest extends AbstractServiceTest {
Assert.assertEquals(dashboards, loadedDashboards);
- dashboardService.unassignCustomerDashboards(tenantId, customerId);
+ dashboardService.unassignCustomerDashboards(customerId);
pageLink = new TimePageLink(42);
pageData = dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink).get();
ui/src/app/api/dashboard.service.js 150(+104 -46)
diff --git a/ui/src/app/api/dashboard.service.js b/ui/src/app/api/dashboard.service.js
index 3082bd3..ae11f84 100644
--- a/ui/src/app/api/dashboard.service.js
+++ b/ui/src/app/api/dashboard.service.js
@@ -17,7 +17,7 @@ export default angular.module('thingsboard.api.dashboard', [])
.factory('dashboardService', DashboardService).name;
/*@ngInject*/
-function DashboardService($rootScope, $http, $q, $location, customerService) {
+function DashboardService($rootScope, $http, $q, $location, $filter) {
var stDiffPromise;
@@ -37,7 +37,11 @@ function DashboardService($rootScope, $http, $q, $location, customerService) {
deleteDashboard: deleteDashboard,
saveDashboard: saveDashboard,
unassignDashboardFromCustomer: unassignDashboardFromCustomer,
+ updateDashboardCustomers: updateDashboardCustomers,
+ addDashboardCustomers: addDashboardCustomers,
+ removeDashboardCustomers: removeDashboardCustomers,
makeDashboardPublic: makeDashboardPublic,
+ makeDashboardPrivate: makeDashboardPrivate,
getPublicDashboardLink: getPublicDashboardLink
}
@@ -56,14 +60,14 @@ function DashboardService($rootScope, $http, $q, $location, customerService) {
url += '&textOffset=' + pageLink.textOffset;
}
$http.get(url, config).then(function success(response) {
- deferred.resolve(response.data);
+ deferred.resolve(prepareDashboards(response.data));
}, function fail() {
deferred.reject();
});
return deferred.promise;
}
- function getTenantDashboards(pageLink, applyCustomersInfo, config) {
+ function getTenantDashboards(pageLink, config) {
var deferred = $q.defer();
var url = '/api/tenant/dashboards?limit=' + pageLink.limit;
if (angular.isDefined(pageLink.textSearch)) {
@@ -76,51 +80,25 @@ function DashboardService($rootScope, $http, $q, $location, customerService) {
url += '&textOffset=' + pageLink.textOffset;
}
$http.get(url, config).then(function success(response) {
- if (applyCustomersInfo) {
- customerService.applyAssignedCustomersInfo(response.data.data).then(
- function success(data) {
- response.data.data = data;
- deferred.resolve(response.data);
- },
- function fail() {
- deferred.reject();
- }
- );
- } else {
- deferred.resolve(response.data);
- }
+ deferred.resolve(prepareDashboards(response.data));
}, function fail() {
deferred.reject();
});
return deferred.promise;
}
- function getCustomerDashboards(customerId, pageLink, applyCustomersInfo, config) {
+ function getCustomerDashboards(customerId, pageLink, config) {
var deferred = $q.defer();
var url = '/api/customer/' + customerId + '/dashboards?limit=' + pageLink.limit;
- if (angular.isDefined(pageLink.textSearch)) {
- url += '&textSearch=' + pageLink.textSearch;
- }
if (angular.isDefined(pageLink.idOffset)) {
- url += '&idOffset=' + pageLink.idOffset;
- }
- if (angular.isDefined(pageLink.textOffset)) {
- url += '&textOffset=' + pageLink.textOffset;
+ url += '&offset=' + pageLink.idOffset;
}
$http.get(url, config).then(function success(response) {
- if (applyCustomersInfo) {
- customerService.applyAssignedCustomerInfo(response.data.data, customerId).then(
- function success(data) {
- response.data.data = data;
- deferred.resolve(response.data);
- },
- function fail() {
- deferred.reject();
- }
- );
- } else {
- deferred.resolve(response.data);
+ response.data = prepareDashboards(response.data);
+ if (pageLink.textSearch) {
+ response.data.data = $filter('filter')(response.data.data, {title: pageLink.textSearch});
}
+ deferred.resolve(response.data);
}, function fail() {
deferred.reject();
});
@@ -151,7 +129,7 @@ function DashboardService($rootScope, $http, $q, $location, customerService) {
var deferred = $q.defer();
var url = '/api/dashboard/' + dashboardId;
$http.get(url, null).then(function success(response) {
- deferred.resolve(response.data);
+ deferred.resolve(prepareDashboard(response.data));
}, function fail() {
deferred.reject();
});
@@ -162,7 +140,7 @@ function DashboardService($rootScope, $http, $q, $location, customerService) {
var deferred = $q.defer();
var url = '/api/dashboard/info/' + dashboardId;
$http.get(url, config).then(function success(response) {
- deferred.resolve(response.data);
+ deferred.resolve(prepareDashboard(response.data));
}, function fail() {
deferred.reject();
});
@@ -172,8 +150,8 @@ function DashboardService($rootScope, $http, $q, $location, customerService) {
function saveDashboard(dashboard) {
var deferred = $q.defer();
var url = '/api/dashboard';
- $http.post(url, dashboard).then(function success(response) {
- deferred.resolve(response.data);
+ $http.post(url, cleanDashboard(dashboard)).then(function success(response) {
+ deferred.resolve(prepareDashboard(response.data));
}, function fail() {
deferred.reject();
});
@@ -195,18 +173,51 @@ function DashboardService($rootScope, $http, $q, $location, customerService) {
var deferred = $q.defer();
var url = '/api/customer/' + customerId + '/dashboard/' + dashboardId;
$http.post(url, null).then(function success(response) {
- deferred.resolve(response.data);
+ deferred.resolve(prepareDashboard(response.data));
}, function fail() {
deferred.reject();
});
return deferred.promise;
}
- function unassignDashboardFromCustomer(dashboardId) {
+ function unassignDashboardFromCustomer(customerId, dashboardId) {
var deferred = $q.defer();
- var url = '/api/customer/dashboard/' + dashboardId;
+ var url = '/api/customer/' + customerId + '/dashboard/' + dashboardId;
$http.delete(url).then(function success(response) {
- deferred.resolve(response.data);
+ deferred.resolve(prepareDashboard(response.data));
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
+ function updateDashboardCustomers(dashboardId, customerIds) {
+ var deferred = $q.defer();
+ var url = '/api/dashboard/' + dashboardId + '/customers';
+ $http.post(url, customerIds).then(function success(response) {
+ deferred.resolve(prepareDashboard(response.data));
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
+ function addDashboardCustomers(dashboardId, customerIds) {
+ var deferred = $q.defer();
+ var url = '/api/dashboard/' + dashboardId + '/customers/add';
+ $http.post(url, customerIds).then(function success(response) {
+ deferred.resolve(prepareDashboard(response.data));
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
+ function removeDashboardCustomers(dashboardId, customerIds) {
+ var deferred = $q.defer();
+ var url = '/api/dashboard/' + dashboardId + '/customers/remove';
+ $http.post(url, customerIds).then(function success(response) {
+ deferred.resolve(prepareDashboard(response.data));
}, function fail() {
deferred.reject();
});
@@ -217,7 +228,18 @@ function DashboardService($rootScope, $http, $q, $location, customerService) {
var deferred = $q.defer();
var url = '/api/customer/public/dashboard/' + dashboardId;
$http.post(url, null).then(function success(response) {
- deferred.resolve(response.data);
+ deferred.resolve(prepareDashboard(response.data));
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
+ function makeDashboardPrivate(dashboardId) {
+ var deferred = $q.defer();
+ var url = '/api/customer/public/dashboard/' + dashboardId;
+ $http.delete(url).then(function success(response) {
+ deferred.resolve(prepareDashboard(response.data));
}, function fail() {
deferred.reject();
});
@@ -230,8 +252,44 @@ function DashboardService($rootScope, $http, $q, $location, customerService) {
if (port != 80 && port != 443) {
url += ":" + port;
}
- url += "/dashboards/" + dashboard.id.id + "?publicId=" + dashboard.customerId.id;
+ url += "/dashboards/" + dashboard.id.id + "?publicId=" + dashboard.publicCustomerId;
return url;
}
+ function prepareDashboards(dashboardsData) {
+ if (dashboardsData.data) {
+ for (var i = 0; i < dashboardsData.data.length; i++) {
+ dashboardsData.data[i] = prepareDashboard(dashboardsData.data[i]);
+ }
+ }
+ return dashboardsData;
+ }
+
+ function prepareDashboard(dashboard) {
+ dashboard.publicCustomerId = null;
+ dashboard.assignedCustomersText = "";
+ dashboard.assignedCustomersIds = [];
+ if (dashboard.assignedCustomers && dashboard.assignedCustomers.length) {
+ var assignedCustomersTitles = [];
+ for (var i = 0; i < dashboard.assignedCustomers.length; i++) {
+ var assignedCustomer = dashboard.assignedCustomers[i];
+ dashboard.assignedCustomersIds.push(assignedCustomer.customerId.id);
+ if (assignedCustomer.public) {
+ dashboard.publicCustomerId = assignedCustomer.customerId.id;
+ } else {
+ assignedCustomersTitles.push(assignedCustomer.title);
+ }
+ }
+ dashboard.assignedCustomersText = assignedCustomersTitles.join(', ');
+ }
+ return dashboard;
+ }
+
+ function cleanDashboard(dashboard) {
+ delete dashboard.publicCustomerId;
+ delete dashboard.assignedCustomersText;
+ delete dashboard.assignedCustomersIds;
+ return dashboard;
+ }
+
}
ui/src/app/api/entity.service.js 43(+35 -8)
diff --git a/ui/src/app/api/entity.service.js b/ui/src/app/api/entity.service.js
index df1c3e0..d30c10c 100644
--- a/ui/src/app/api/entity.service.js
+++ b/ui/src/app/api/entity.service.js
@@ -273,9 +273,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
break;
case types.entityType.dashboard:
if (user.authority === 'CUSTOMER_USER') {
- promise = dashboardService.getCustomerDashboards(customerId, pageLink, false, config);
+ promise = dashboardService.getCustomerDashboards(customerId, pageLink, config);
} else {
- promise = dashboardService.getTenantDashboards(pageLink, false, config);
+ promise = dashboardService.getTenantDashboards(pageLink, config);
}
break;
case types.entityType.user:
@@ -403,6 +403,21 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return deferred.promise;
}
+ function resolveAliasEntityId(entityType, id) {
+ var entityId = {
+ entityType: entityType,
+ id: id
+ };
+ if (entityType == types.aliasEntityType.current_customer) {
+ var user = userService.getCurrentUser();
+ entityId.entityType = types.entityType.customer;
+ if (user.authority === 'CUSTOMER_USER') {
+ entityId.id = user.customerId;
+ }
+ }
+ return entityId;
+ }
+
function getStateEntityId(filter, stateParams) {
var entityId = null;
if (stateParams) {
@@ -417,6 +432,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
if (!entityId) {
entityId = filter.defaultStateEntity;
}
+ if (entityId) {
+ entityId = resolveAliasEntityId(entityId.entityType, entityId.id);
+ }
return entityId;
}
@@ -432,7 +450,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
var stateEntityId = getStateEntityId(filter, stateParams);
switch (filter.type) {
case types.aliasFilterType.singleEntity.value:
- getEntity(filter.singleEntity.entityType, filter.singleEntity.id, {ignoreLoading: true}).then(
+ var aliasEntityId = resolveAliasEntityId(filter.singleEntity.entityType, filter.singleEntity.id);
+ getEntity(aliasEntityId.entityType, aliasEntityId.id, {ignoreLoading: true}).then(
function success(entity) {
result.entities = entitiesToEntitiesInfo([entity]);
deferred.resolve(result);
@@ -530,10 +549,11 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
rootEntityId = filter.rootEntity.id;
}
if (rootEntityType && rootEntityId) {
+ var relationQueryRootEntityId = resolveAliasEntityId(rootEntityType, rootEntityId);
var searchQuery = {
parameters: {
- rootId: rootEntityId,
- rootType: rootEntityType,
+ rootId: relationQueryRootEntityId.id,
+ rootType: relationQueryRootEntityId.entityType,
direction: filter.direction
},
filters: filter.filters
@@ -571,10 +591,11 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
rootEntityId = filter.rootEntity.id;
}
if (rootEntityType && rootEntityId) {
+ var searchQueryRootEntityId = resolveAliasEntityId(rootEntityType, rootEntityId);
searchQuery = {
parameters: {
- rootId: rootEntityId,
- rootType: rootEntityType,
+ rootId: searchQueryRootEntityId.id,
+ rootType: searchQueryRootEntityId.entityType,
direction: filter.direction
},
relationType: filter.relationType
@@ -709,7 +730,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
return result;
}
- function prepareAllowedEntityTypesList(allowedEntityTypes) {
+ function prepareAllowedEntityTypesList(allowedEntityTypes, useAliasEntityTypes) {
var authority = userService.getAuthority();
var entityTypes = {};
switch(authority) {
@@ -726,12 +747,18 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
entityTypes.rule = types.entityType.rule;
entityTypes.plugin = types.entityType.plugin;
entityTypes.dashboard = types.entityType.dashboard;
+ if (useAliasEntityTypes) {
+ entityTypes.current_customer = types.aliasEntityType.current_customer;
+ }
break;
case 'CUSTOMER_USER':
entityTypes.device = types.entityType.device;
entityTypes.asset = types.entityType.asset;
entityTypes.customer = types.entityType.customer;
entityTypes.dashboard = types.entityType.dashboard;
+ if (useAliasEntityTypes) {
+ entityTypes.current_customer = types.aliasEntityType.current_customer;
+ }
break;
}
ui/src/app/api/user.service.js 4(+2 -2)
diff --git a/ui/src/app/api/user.service.js b/ui/src/app/api/user.service.js
index ce5e673..c969c2f 100644
--- a/ui/src/app/api/user.service.js
+++ b/ui/src/app/api/user.service.js
@@ -266,9 +266,9 @@ function UserService($http, $q, $rootScope, adminService, dashboardService, logi
var pageLink = {limit: 100};
var fetchDashboardsPromise;
if (currentUser.authority === 'TENANT_ADMIN') {
- fetchDashboardsPromise = dashboardService.getTenantDashboards(pageLink, false);
+ fetchDashboardsPromise = dashboardService.getTenantDashboards(pageLink);
} else {
- fetchDashboardsPromise = dashboardService.getCustomerDashboards(currentUser.customerId, pageLink, false);
+ fetchDashboardsPromise = dashboardService.getCustomerDashboards(currentUser.customerId, pageLink);
}
fetchDashboardsPromise.then(
function success(result) {
ui/src/app/common/types.constant.js 7(+7 -0)
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index d82add1..6f09f34 100644
--- a/ui/src/app/common/types.constant.js
+++ b/ui/src/app/common/types.constant.js
@@ -296,6 +296,9 @@ export default angular.module('thingsboard.types', [])
dashboard: "DASHBOARD",
alarm: "ALARM"
},
+ aliasEntityType: {
+ current_customer: "CURRENT_CUSTOMER"
+ },
entityTypeTranslations: {
"DEVICE": {
type: 'entity.type-device',
@@ -350,6 +353,10 @@ export default angular.module('thingsboard.types', [])
typePlural: 'entity.type-alarms',
list: 'entity.list-of-alarms',
nameStartsWith: 'entity.alarm-name-starts-with'
+ },
+ "CURRENT_CUSTOMER": {
+ type: 'entity.type-current-customer',
+ list: 'entity.type-current-customer'
}
},
entitySearchDirection: {
diff --git a/ui/src/app/components/dashboard-autocomplete.directive.js b/ui/src/app/components/dashboard-autocomplete.directive.js
index 2235b82..6af5585 100644
--- a/ui/src/app/components/dashboard-autocomplete.directive.js
+++ b/ui/src/app/components/dashboard-autocomplete.directive.js
@@ -48,7 +48,7 @@ function DashboardAutocomplete($compile, $templateCache, $q, dashboardService, u
var promise;
if (scope.dashboardsScope === 'customer' || userService.getAuthority() === 'CUSTOMER_USER') {
if (scope.customerId) {
- promise = dashboardService.getCustomerDashboards(scope.customerId, pageLink, false, {ignoreLoading: true});
+ promise = dashboardService.getCustomerDashboards(scope.customerId, pageLink, {ignoreLoading: true});
} else {
promise = $q.when({data: []});
}
@@ -60,7 +60,7 @@ function DashboardAutocomplete($compile, $templateCache, $q, dashboardService, u
promise = $q.when({data: []});
}
} else {
- promise = dashboardService.getTenantDashboards(pageLink, false, {ignoreLoading: true});
+ promise = dashboardService.getTenantDashboards(pageLink, {ignoreLoading: true});
}
}
diff --git a/ui/src/app/components/dashboard-select.directive.js b/ui/src/app/components/dashboard-select.directive.js
index ac5cd3d..b172168 100644
--- a/ui/src/app/components/dashboard-select.directive.js
+++ b/ui/src/app/components/dashboard-select.directive.js
@@ -48,12 +48,12 @@ function DashboardSelect($compile, $templateCache, $q, $mdMedia, $mdPanel, $docu
var promise;
if (scope.dashboardsScope === 'customer' || userService.getAuthority() === 'CUSTOMER_USER') {
if (scope.customerId && scope.customerId != types.id.nullUid) {
- promise = dashboardService.getCustomerDashboards(scope.customerId, pageLink, false, {ignoreLoading: true});
+ promise = dashboardService.getCustomerDashboards(scope.customerId, pageLink, {ignoreLoading: true});
} else {
promise = $q.when({data: []});
}
} else {
- promise = dashboardService.getTenantDashboards(pageLink, false, {ignoreLoading: true});
+ promise = dashboardService.getTenantDashboards(pageLink, {ignoreLoading: true});
}
promise.then(function success(result) {
diff --git a/ui/src/app/dashboard/add-dashboards-to-customer.controller.js b/ui/src/app/dashboard/add-dashboards-to-customer.controller.js
index 6fe6e79..b0bbef1 100644
--- a/ui/src/app/dashboard/add-dashboards-to-customer.controller.js
+++ b/ui/src/app/dashboard/add-dashboards-to-customer.controller.js
@@ -52,7 +52,7 @@ export default function AddDashboardsToCustomerController(dashboardService, $mdD
fetchMoreItems_: function () {
if (vm.dashboards.hasNext && !vm.dashboards.pending) {
vm.dashboards.pending = true;
- dashboardService.getTenantDashboards(vm.dashboards.nextPageLink, false).then(
+ dashboardService.getTenantDashboards(vm.dashboards.nextPageLink).then(
function success(dashboards) {
vm.dashboards.data = vm.dashboards.data.concat(dashboards.data);
vm.dashboards.nextPageLink = dashboards.nextPageLink;
ui/src/app/dashboard/dashboard.directive.js 29(+6 -23)
diff --git a/ui/src/app/dashboard/dashboard.directive.js b/ui/src/app/dashboard/dashboard.directive.js
index b2f3117..39b1c02 100644
--- a/ui/src/app/dashboard/dashboard.directive.js
+++ b/ui/src/app/dashboard/dashboard.directive.js
@@ -20,36 +20,17 @@ import dashboardFieldsetTemplate from './dashboard-fieldset.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
-export default function DashboardDirective($compile, $templateCache, $translate, types, toast, customerService, dashboardService) {
+export default function DashboardDirective($compile, $templateCache, $translate, types, toast, dashboardService) {
var linker = function (scope, element) {
var template = $templateCache.get(dashboardFieldsetTemplate);
element.html(template);
-
- scope.isAssignedToCustomer = false;
- scope.isPublic = false;
- scope.assignedCustomer = null;
scope.publicLink = null;
-
scope.$watch('dashboard', function(newVal) {
if (newVal) {
- if (scope.dashboard.customerId && scope.dashboard.customerId.id !== types.id.nullUid) {
- scope.isAssignedToCustomer = true;
- customerService.getShortCustomerInfo(scope.dashboard.customerId.id).then(
- function success(customer) {
- scope.assignedCustomer = customer;
- scope.isPublic = customer.isPublic;
- if (scope.isPublic) {
- scope.publicLink = dashboardService.getPublicDashboardLink(scope.dashboard);
- } else {
- scope.publicLink = null;
- }
- }
- );
+ if (scope.dashboard.publicCustomerId) {
+ scope.publicLink = dashboardService.getPublicDashboardLink(scope.dashboard);
} else {
- scope.isAssignedToCustomer = false;
- scope.isPublic = false;
scope.publicLink = null;
- scope.assignedCustomer = null;
}
}
});
@@ -66,10 +47,12 @@ export default function DashboardDirective($compile, $templateCache, $translate,
scope: {
dashboard: '=',
isEdit: '=',
+ customerId: '=',
dashboardScope: '=',
theForm: '=',
- onAssignToCustomer: '&',
onMakePublic: '&',
+ onMakePrivate: '&',
+ onManageAssignedCustomers: '&',
onUnassignFromCustomer: '&',
onExportDashboard: '&',
onDeleteDashboard: '&'
ui/src/app/dashboard/dashboard-card.scss 27(+27 -0)
diff --git a/ui/src/app/dashboard/dashboard-card.scss b/ui/src/app/dashboard/dashboard-card.scss
new file mode 100644
index 0000000..32f25c7
--- /dev/null
+++ b/ui/src/app/dashboard/dashboard-card.scss
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2016-2017 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-dashboard-assigned-customers {
+ display: block;
+ display: -webkit-box;
+ height: 34px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ margin-bottom: 4px;
+}
+
diff --git a/ui/src/app/dashboard/dashboard-card.tpl.html b/ui/src/app/dashboard/dashboard-card.tpl.html
index 6367867..ed19fda 100644
--- a/ui/src/app/dashboard/dashboard-card.tpl.html
+++ b/ui/src/app/dashboard/dashboard-card.tpl.html
@@ -15,6 +15,6 @@
limitations under the License.
-->
-<div class="tb-small" ng-show="vm.isAssignedToCustomer()">{{'dashboard.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'</div>
-<div class="tb-small" ng-show="vm.isPublic()">{{'dashboard.public' | translate}}</div>
+<div class="tb-small tb-dashboard-assigned-customers" ng-show="vm.parentCtl.dashboardsScope === 'tenant' && vm.item.assignedCustomersText">{{'dashboard.assignedToCustomers' | translate}}: '{{vm.item.assignedCustomersText}}'</div>
+<div class="tb-small" ng-show="vm.parentCtl.dashboardsScope === 'tenant' && vm.item.publicCustomerId">{{'dashboard.public' | translate}}</div>
ui/src/app/dashboard/dashboard-fieldset.tpl.html 27(+16 -11)
diff --git a/ui/src/app/dashboard/dashboard-fieldset.tpl.html b/ui/src/app/dashboard/dashboard-fieldset.tpl.html
index a54f477..00ee554 100644
--- a/ui/src/app/dashboard/dashboard-fieldset.tpl.html
+++ b/ui/src/app/dashboard/dashboard-fieldset.tpl.html
@@ -19,24 +19,29 @@
ng-show="!isEdit && dashboardScope === 'tenant'"
class="md-raised md-primary">{{ 'dashboard.export' | translate }}</md-button>
<md-button ng-click="onMakePublic({event: $event})"
- ng-show="!isEdit && dashboardScope === 'tenant' && !isAssignedToCustomer && !isPublic"
+ ng-show="!isEdit && dashboardScope === 'tenant' && !dashboard.publicCustomerId"
class="md-raised md-primary">{{ 'dashboard.make-public' | translate }}</md-button>
-<md-button ng-click="onAssignToCustomer({event: $event})"
- ng-show="!isEdit && dashboardScope === 'tenant' && !isAssignedToCustomer"
- class="md-raised md-primary">{{ 'dashboard.assign-to-customer' | translate }}</md-button>
-<md-button ng-click="onUnassignFromCustomer({event: $event, isPublic: isPublic})"
- ng-show="!isEdit && (dashboardScope === 'customer' || dashboardScope === 'tenant') && isAssignedToCustomer"
- class="md-raised md-primary">{{ isPublic ? 'dashboard.make-private' : 'dashboard.unassign-from-customer' | translate }}</md-button>
+<md-button ng-click="onMakePrivate({event: $event})"
+ ng-show="!isEdit && ((dashboardScope === 'tenant' && dashboard.publicCustomerId ||
+ dashboardScope === 'customer' && customerId == dashboard.publicCustomerId))"
+ class="md-raised md-primary">{{ 'dashboard.make-private' | translate }}</md-button>
+<md-button ng-click="onManageAssignedCustomers({event: $event})"
+ ng-show="!isEdit && dashboardScope === 'tenant'"
+ class="md-raised md-primary">{{ 'dashboard.manage-assigned-customers' | translate }}</md-button>
+<md-button ng-click="onUnassignFromCustomer({event: $event})"
+ ng-show="!isEdit && dashboardScope === 'customer' && customerId != dashboard.publicCustomerId"
+ class="md-raised md-primary">{{ 'dashboard.unassign-from-customer' | translate }}</md-button>
<md-button ng-click="onDeleteDashboard({event: $event})"
ng-show="!isEdit && dashboardScope === 'tenant'"
class="md-raised md-primary">{{ 'dashboard.delete' | translate }}</md-button>
<md-content class="md-padding" layout="column">
<md-input-container class="md-block"
- ng-show="!isEdit && isAssignedToCustomer && !isPublic && dashboardScope === 'tenant'">
- <label translate>dashboard.assignedToCustomer</label>
- <input ng-model="assignedCustomer.title" disabled>
+ ng-show="!isEdit && dashboard.assignedCustomersText && dashboardScope === 'tenant'">
+ <label translate>dashboard.assignedToCustomers</label>
+ <input ng-model="dashboard.assignedCustomersText" disabled>
</md-input-container>
- <div layout="column" ng-show="!isEdit && isPublic && (dashboardScope === 'customer' || dashboardScope === 'tenant')">
+ <div layout="column" ng-show="!isEdit && ((dashboardScope === 'tenant' && dashboard.publicCustomerId ||
+ dashboardScope === 'customer' && customerId == dashboard.publicCustomerId))">
<tb-social-share-panel style="padding-bottom: 10px;"
share-title="{{ 'dashboard.socialshare-title' | translate:{dashboardTitle: dashboard.title} }}"
share-text="{{ 'dashboard.socialshare-text' | translate:{dashboardTitle: dashboard.title} }}"
ui/src/app/dashboard/dashboards.controller.js 226(+122 -104)
diff --git a/ui/src/app/dashboard/dashboards.controller.js b/ui/src/app/dashboard/dashboards.controller.js
index d2887f8..af76b67 100644
--- a/ui/src/app/dashboard/dashboards.controller.js
+++ b/ui/src/app/dashboard/dashboards.controller.js
@@ -17,12 +17,14 @@
import addDashboardTemplate from './add-dashboard.tpl.html';
import dashboardCard from './dashboard-card.tpl.html';
-import assignToCustomerTemplate from './assign-to-customer.tpl.html';
import addDashboardsToCustomerTemplate from './add-dashboards-to-customer.tpl.html';
import makeDashboardPublicDialogTemplate from './make-dashboard-public-dialog.tpl.html';
+import manageAssignedCustomersTemplate from './manage-assigned-customers.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
+import './dashboard-card.scss';
+
/*@ngInject*/
export function MakeDashboardPublicDialogController($mdDialog, $translate, toast, dashboardService, dashboard) {
@@ -48,23 +50,8 @@ export function MakeDashboardPublicDialogController($mdDialog, $translate, toast
export function DashboardCardController(types) {
var vm = this;
-
vm.types = types;
- vm.isAssignedToCustomer = function() {
- if (vm.item && vm.item.customerId && vm.parentCtl.dashboardsScope === '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.dashboardsScope === 'tenant' && vm.item.assignedCustomer.isPublic) {
- return true;
- }
- return false;
- }
}
/*@ngInject*/
@@ -135,8 +122,9 @@ export function DashboardsController(userService, dashboardService, customerServ
vm.dashboardsScope = $state.$current.data.dashboardsType;
- vm.assignToCustomer = assignToCustomer;
vm.makePublic = makePublic;
+ vm.makePrivate = makePrivate;
+ vm.manageAssignedCustomers = manageAssignedCustomers;
vm.unassignFromCustomer = unassignFromCustomer;
vm.exportDashboard = exportDashboard;
@@ -155,6 +143,7 @@ export function DashboardsController(userService, dashboardService, customerServ
}
if (customerId) {
+ vm.customerId = customerId;
vm.customerDashboardsTitle = $translate.instant('customer.dashboards');
customerService.getShortCustomerInfo(customerId).then(
function success(info) {
@@ -167,7 +156,7 @@ export function DashboardsController(userService, dashboardService, customerServ
if (vm.dashboardsScope === 'tenant') {
fetchDashboardsFunction = function (pageLink) {
- return dashboardService.getTenantDashboards(pageLink, true);
+ return dashboardService.getTenantDashboards(pageLink);
};
deleteDashboardFunction = function (dashboardId) {
return dashboardService.deleteDashboard(dashboardId);
@@ -194,11 +183,33 @@ export function DashboardsController(userService, dashboardService, customerServ
details: function() { return $translate.instant('dashboard.make-public') },
icon: "share",
isEnabled: function(dashboard) {
- return dashboard && (!dashboard.customerId || dashboard.customerId.id === types.id.nullUid);
+ return dashboard && !dashboard.publicCustomerId;
}
});
-
dashboardActionsList.push({
+ onAction: function ($event, item) {
+ makePrivate($event, item);
+ },
+ name: function() { return $translate.instant('action.make-private') },
+ details: function() { return $translate.instant('dashboard.make-private') },
+ icon: "reply",
+ isEnabled: function(dashboard) {
+ return dashboard && dashboard.publicCustomerId;
+ }
+ });
+ dashboardActionsList.push({
+ onAction: function ($event, item) {
+ manageAssignedCustomers($event, item);
+ },
+ name: function() { return $translate.instant('action.assign') },
+ details: function() { return $translate.instant('dashboard.manage-assigned-customers') },
+ icon: "assignment_ind",
+ isEnabled: function(dashboard) {
+ return dashboard;
+ }
+ });
+
+ /*dashboardActionsList.push({
onAction: function ($event, item) {
assignToCustomer($event, [ item.id.id ]);
},
@@ -208,8 +219,8 @@ export function DashboardsController(userService, dashboardService, customerServ
isEnabled: function(dashboard) {
return dashboard && (!dashboard.customerId || dashboard.customerId.id === types.id.nullUid);
}
- });
- dashboardActionsList.push({
+ });*/
+ /*dashboardActionsList.push({
onAction: function ($event, item) {
unassignFromCustomer($event, item, false);
},
@@ -219,18 +230,7 @@ export function DashboardsController(userService, dashboardService, customerServ
isEnabled: function(dashboard) {
return dashboard && dashboard.customerId && dashboard.customerId.id !== types.id.nullUid && !dashboard.assignedCustomer.isPublic;
}
- });
- dashboardActionsList.push({
- onAction: function ($event, item) {
- unassignFromCustomer($event, item, true);
- },
- name: function() { return $translate.instant('action.make-private') },
- details: function() { return $translate.instant('dashboard.make-private') },
- icon: "reply",
- isEnabled: function(dashboard) {
- return dashboard && dashboard.customerId && dashboard.customerId.id !== types.id.nullUid && dashboard.assignedCustomer.isPublic;
- }
- });
+ });*/
dashboardActionsList.push(
{
@@ -246,7 +246,7 @@ export function DashboardsController(userService, dashboardService, customerServ
dashboardGroupActionsList.push(
{
onAction: function ($event, items) {
- assignDashboardsToCustomer($event, items);
+ assignDashboardsToCustomers($event, items);
},
name: function() { return $translate.instant('dashboard.assign-dashboards') },
details: function(selectedCount) {
@@ -255,6 +255,17 @@ export function DashboardsController(userService, dashboardService, customerServ
icon: "assignment_ind"
}
);
+ dashboardGroupActionsList.push(
+ {
+ onAction: function ($event, items) {
+ unassignDashboardsFromCustomers($event, items);
+ },
+ name: function() { return $translate.instant('dashboard.unassign-dashboards') },
+ details: function(selectedCount) {
+ return $translate.instant('dashboard.unassign-dashboards-action-text', {count: selectedCount}, "messageformat");
+ },
+ icon: "assignment_return" }
+ );
dashboardGroupActionsList.push(
{
@@ -290,10 +301,10 @@ export function DashboardsController(userService, dashboardService, customerServ
});
} else if (vm.dashboardsScope === 'customer' || vm.dashboardsScope === 'customer_user') {
fetchDashboardsFunction = function (pageLink) {
- return dashboardService.getCustomerDashboards(customerId, pageLink, true);
+ return dashboardService.getCustomerDashboards(customerId, pageLink);
};
deleteDashboardFunction = function (dashboardId) {
- return dashboardService.unassignDashboardFromCustomer(dashboardId);
+ return dashboardService.unassignDashboardFromCustomer(customerId, dashboardId);
};
refreshDashboardsParamsFunction = function () {
return {"customerId": customerId, "topIndex": vm.topIndex};
@@ -314,26 +325,27 @@ export function DashboardsController(userService, dashboardService, customerServ
dashboardActionsList.push(
{
onAction: function ($event, item) {
- unassignFromCustomer($event, item, false);
+ makePrivate($event, item);
},
- name: function() { return $translate.instant('action.unassign') },
- details: function() { return $translate.instant('dashboard.unassign-from-customer') },
- icon: "assignment_return",
+ name: function() { return $translate.instant('action.make-private') },
+ details: function() { return $translate.instant('dashboard.make-private') },
+ icon: "reply",
isEnabled: function(dashboard) {
- return dashboard && !dashboard.assignedCustomer.isPublic;
+ return dashboard && customerId == dashboard.publicCustomerId;
}
}
);
+
dashboardActionsList.push(
{
onAction: function ($event, item) {
- unassignFromCustomer($event, item, true);
+ unassignFromCustomer($event, item, customerId);
},
- name: function() { return $translate.instant('action.make-private') },
- details: function() { return $translate.instant('dashboard.make-private') },
- icon: "reply",
+ name: function() { return $translate.instant('action.unassign') },
+ details: function() { return $translate.instant('dashboard.unassign-from-customer') },
+ icon: "assignment_return",
isEnabled: function(dashboard) {
- return dashboard && dashboard.assignedCustomer.isPublic;
+ return dashboard && customerId != dashboard.publicCustomerId;
}
}
);
@@ -341,7 +353,7 @@ export function DashboardsController(userService, dashboardService, customerServ
dashboardGroupActionsList.push(
{
onAction: function ($event, items) {
- unassignDashboardsFromCustomer($event, items);
+ unassignDashboardsFromCustomer($event, items, customerId);
},
name: function() { return $translate.instant('dashboard.unassign-dashboards') },
details: function(selectedCount) {
@@ -351,7 +363,6 @@ export function DashboardsController(userService, dashboardService, customerServ
}
);
-
vm.dashboardGridConfig.addItemAction = {
onAction: function ($event) {
addDashboardsToCustomer($event);
@@ -428,39 +439,42 @@ export function DashboardsController(userService, dashboardService, customerServ
return deferred.promise;
}
- function assignToCustomer($event, dashboardIds) {
+ function manageAssignedCustomers($event, dashboard) {
+ showManageAssignedCustomersDialog($event, [dashboard.id.id], 'manage', dashboard.assignedCustomersIds);
+ }
+
+ function assignDashboardsToCustomers($event, items) {
+ var dashboardIds = [];
+ for (var id in items.selections) {
+ dashboardIds.push(id);
+ }
+ showManageAssignedCustomersDialog($event, dashboardIds, 'assign');
+ }
+
+ function unassignDashboardsFromCustomers($event, items) {
+ var dashboardIds = [];
+ for (var id in items.selections) {
+ dashboardIds.push(id);
+ }
+ showManageAssignedCustomersDialog($event, dashboardIds, 'unassign');
+ }
+
+ function showManageAssignedCustomersDialog($event, dashboardIds, actionType, assignedCustomers) {
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: 'AssignDashboardToCustomerController',
- controllerAs: 'vm',
- templateUrl: assignToCustomerTemplate,
- locals: {dashboardIds: dashboardIds, customers: customers},
- parent: angular.element($document[0].body),
- fullscreen: true,
- targetEvent: $event
- }).then(function () {
- vm.grid.refreshList();
- }, function () {
- });
- },
- function fail() {
- });
+ $mdDialog.show({
+ controller: 'ManageAssignedCustomersController',
+ controllerAs: 'vm',
+ templateUrl: manageAssignedCustomersTemplate,
+ locals: {actionType: actionType, dashboardIds: dashboardIds, assignedCustomers: assignedCustomers},
+ parent: angular.element($document[0].body),
+ fullscreen: true,
+ targetEvent: $event
+ }).then(function () {
+ vm.grid.refreshList();
+ }, function () {
+ });
}
function addDashboardsToCustomer($event) {
@@ -468,7 +482,7 @@ export function DashboardsController(userService, dashboardService, customerServ
$event.stopPropagation();
}
var pageSize = 10;
- dashboardService.getTenantDashboards({limit: pageSize, textSearch: ''}, false).then(
+ dashboardService.getTenantDashboards({limit: pageSize, textSearch: ''}).then(
function success(_dashboards) {
var dashboards = {
pageSize: pageSize,
@@ -499,30 +513,13 @@ export function DashboardsController(userService, dashboardService, customerServ
});
}
- function assignDashboardsToCustomer($event, items) {
- var dashboardIds = [];
- for (var id in items.selections) {
- dashboardIds.push(id);
- }
- assignToCustomer($event, dashboardIds);
- }
-
- function unassignFromCustomer($event, dashboard, isPublic) {
+ function unassignFromCustomer($event, dashboard, customerId) {
if ($event) {
$event.stopPropagation();
}
- var title;
- var content;
- var label;
- if (isPublic) {
- title = $translate.instant('dashboard.make-private-dashboard-title', {dashboardTitle: dashboard.title});
- content = $translate.instant('dashboard.make-private-dashboard-text');
- label = $translate.instant('dashboard.make-private-dashboard');
- } else {
- title = $translate.instant('dashboard.unassign-dashboard-title', {dashboardTitle: dashboard.title});
- content = $translate.instant('dashboard.unassign-dashboard-text');
- label = $translate.instant('dashboard.unassign-dashboard');
- }
+ var title = $translate.instant('dashboard.unassign-dashboard-title', {dashboardTitle: dashboard.title});
+ var content = $translate.instant('dashboard.unassign-dashboard-text');
+ var label = $translate.instant('dashboard.unassign-dashboard');
var confirm = $mdDialog.confirm()
.targetEvent($event)
.title(title)
@@ -531,7 +528,7 @@ export function DashboardsController(userService, dashboardService, customerServ
.cancel($translate.instant('action.no'))
.ok($translate.instant('action.yes'));
$mdDialog.show(confirm).then(function () {
- dashboardService.unassignDashboardFromCustomer(dashboard.id.id).then(function success() {
+ dashboardService.unassignDashboardFromCustomer(customerId, dashboard.id.id).then(function success() {
vm.grid.refreshList();
});
});
@@ -556,12 +553,33 @@ export function DashboardsController(userService, dashboardService, customerServ
});
}
+ function makePrivate($event, dashboard) {
+ if ($event) {
+ $event.stopPropagation();
+ }
+ var title = $translate.instant('dashboard.make-private-dashboard-title', {dashboardTitle: dashboard.title});
+ var content = $translate.instant('dashboard.make-private-dashboard-text');
+ var label = $translate.instant('dashboard.make-private-dashboard');
+ 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 () {
+ dashboardService.makeDashboardPrivate(dashboard.id.id).then(function success() {
+ vm.grid.refreshList();
+ });
+ });
+ }
+
function exportDashboard($event, dashboard) {
$event.stopPropagation();
importExport.exportDashboard(dashboard.id.id);
}
- function unassignDashboardsFromCustomer($event, items) {
+ function unassignDashboardsFromCustomer($event, items, customerId) {
var confirm = $mdDialog.confirm()
.targetEvent($event)
.title($translate.instant('dashboard.unassign-dashboards-title', {count: items.selectedCount}, 'messageformat'))
@@ -572,7 +590,7 @@ export function DashboardsController(userService, dashboardService, customerServ
$mdDialog.show(confirm).then(function () {
var tasks = [];
for (var id in items.selections) {
- tasks.push(dashboardService.unassignDashboardFromCustomer(id));
+ tasks.push(dashboardService.unassignDashboardFromCustomer(customerId, id));
}
$q.all(tasks).then(function () {
vm.grid.refreshList();
diff --git a/ui/src/app/dashboard/dashboards.tpl.html b/ui/src/app/dashboard/dashboards.tpl.html
index 8149821..0528eaf 100644
--- a/ui/src/app/dashboard/dashboards.tpl.html
+++ b/ui/src/app/dashboard/dashboards.tpl.html
@@ -25,10 +25,12 @@
<tb-dashboard-details dashboard="vm.grid.operatingItem()"
is-edit="vm.grid.detailsConfig.isDetailsEditMode"
dashboard-scope="vm.dashboardsScope"
+ customer-id="vm.customerId"
the-form="vm.grid.detailsForm"
- on-assign-to-customer="vm.assignToCustomer(event, [ vm.grid.detailsConfig.currentItem.id.id ])"
on-make-public="vm.makePublic(event, vm.grid.detailsConfig.currentItem)"
- on-unassign-from-customer="vm.unassignFromCustomer(event, vm.grid.detailsConfig.currentItem, isPublic)"
+ on-make-private="vm.makePrivate(event, vm.grid.detailsConfig.currentItem)"
+ on-manage-assigned-customers="vm.manageAssignedCustomers(event, vm.grid.detailsConfig.currentItem)"
+ on-unassign-from-customer="vm.unassignFromCustomer(event, vm.grid.detailsConfig.currentItem, vm.customerId)"
on-export-dashboard="vm.exportDashboard(event, vm.grid.detailsConfig.currentItem)"
on-delete-dashboard="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-dashboard-details>
</md-tab>
ui/src/app/dashboard/index.js 4(+2 -2)
diff --git a/ui/src/app/dashboard/index.js b/ui/src/app/dashboard/index.js
index 4089716..ac63dc5 100644
--- a/ui/src/app/dashboard/index.js
+++ b/ui/src/app/dashboard/index.js
@@ -40,8 +40,8 @@ import DashboardRoutes from './dashboard.routes';
import {DashboardsController, DashboardCardController, MakeDashboardPublicDialogController} from './dashboards.controller';
import DashboardController from './dashboard.controller';
import DashboardSettingsController from './dashboard-settings.controller';
-import AssignDashboardToCustomerController from './assign-to-customer.controller';
import AddDashboardsToCustomerController from './add-dashboards-to-customer.controller';
+import ManageAssignedCustomersController from './manage-assigned-customers.controller';
import AddWidgetController from './add-widget.controller';
import DashboardDirective from './dashboard.directive';
import EditWidgetDirective from './edit-widget.directive';
@@ -74,8 +74,8 @@ export default angular.module('thingsboard.dashboard', [
.controller('MakeDashboardPublicDialogController', MakeDashboardPublicDialogController)
.controller('DashboardController', DashboardController)
.controller('DashboardSettingsController', DashboardSettingsController)
- .controller('AssignDashboardToCustomerController', AssignDashboardToCustomerController)
.controller('AddDashboardsToCustomerController', AddDashboardsToCustomerController)
+ .controller('ManageAssignedCustomersController', ManageAssignedCustomersController)
.controller('AddWidgetController', AddWidgetController)
.directive('tbDashboardDetails', DashboardDirective)
.directive('tbEditWidget', EditWidgetDirective)
diff --git a/ui/src/app/dashboard/manage-assigned-customers.controller.js b/ui/src/app/dashboard/manage-assigned-customers.controller.js
new file mode 100644
index 0000000..90d3e6d
--- /dev/null
+++ b/ui/src/app/dashboard/manage-assigned-customers.controller.js
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2016-2017 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 ManageAssignedCustomersController($mdDialog, $q, types, dashboardService, actionType, dashboardIds, assignedCustomers) {
+
+ var vm = this;
+
+ vm.types = types;
+ vm.actionType = actionType;
+ vm.dashboardIds = dashboardIds;
+ vm.assignedCustomers = assignedCustomers;
+ if (actionType != 'manage') {
+ vm.assignedCustomers = [];
+ }
+
+ if (actionType == 'manage') {
+ vm.titleText = 'dashboard.manage-assigned-customers';
+ vm.labelText = 'dashboard.assigned-customers';
+ vm.actionName = 'action.update';
+ } else if (actionType == 'assign') {
+ vm.titleText = 'dashboard.assign-to-customers';
+ vm.labelText = 'dashboard.assign-to-customers-text';
+ vm.actionName = 'action.assign';
+ } else if (actionType == 'unassign') {
+ vm.titleText = 'dashboard.unassign-from-customers';
+ vm.labelText = 'dashboard.unassign-from-customers-text';
+ vm.actionName = 'action.unassign';
+ }
+
+ vm.submit = submit;
+ vm.cancel = cancel;
+
+ function cancel () {
+ $mdDialog.cancel();
+ }
+
+ function submit () {
+ var tasks = [];
+ for (var i=0;i<vm.dashboardIds.length;i++) {
+ var dashboardId = vm.dashboardIds[i];
+ var promise;
+ if (vm.actionType == 'manage') {
+ promise = dashboardService.updateDashboardCustomers(dashboardId, vm.assignedCustomers);
+ } else if (vm.actionType == 'assign') {
+ promise = dashboardService.addDashboardCustomers(dashboardId, vm.assignedCustomers);
+ } else if (vm.actionType == 'unassign') {
+ promise = dashboardService.removeDashboardCustomers(dashboardId, vm.assignedCustomers);
+ }
+ tasks.push(promise);
+ }
+ $q.all(tasks).then(function () {
+ $mdDialog.hide();
+ });
+ }
+
+}
diff --git a/ui/src/app/entity/entity-autocomplete.directive.js b/ui/src/app/entity/entity-autocomplete.directive.js
index 62f3d6d..2d114db 100644
--- a/ui/src/app/entity/entity-autocomplete.directive.js
+++ b/ui/src/app/entity/entity-autocomplete.directive.js
@@ -38,7 +38,12 @@ export default function EntityAutocomplete($compile, $templateCache, $q, $filter
if (scope.excludeEntityIds && scope.excludeEntityIds.length) {
limit += scope.excludeEntityIds.length;
}
- entityService.getEntitiesByNameFilter(scope.entityType, searchText, limit, {ignoreLoading: true}, scope.entitySubtype).then(function success(result) {
+ var targetType = scope.entityType;
+ if (targetType == types.aliasEntityType.current_customer) {
+ targetType = types.entityType.customer;
+ }
+
+ entityService.getEntitiesByNameFilter(targetType, searchText, limit, {ignoreLoading: true}, scope.entitySubtype).then(function success(result) {
if (result) {
if (scope.excludeEntityIds && scope.excludeEntityIds.length) {
var entities = [];
@@ -71,7 +76,11 @@ export default function EntityAutocomplete($compile, $templateCache, $q, $filter
ngModelCtrl.$render = function () {
if (ngModelCtrl.$viewValue) {
- entityService.getEntity(scope.entityType, ngModelCtrl.$viewValue).then(
+ var targetType = scope.entityType;
+ if (targetType == types.aliasEntityType.current_customer) {
+ targetType = types.entityType.customer;
+ }
+ entityService.getEntity(targetType, ngModelCtrl.$viewValue).then(
function success(entity) {
scope.entity = entity;
},
@@ -114,55 +123,61 @@ export default function EntityAutocomplete($compile, $templateCache, $q, $filter
scope.selectEntityText = 'asset.select-asset';
scope.entityText = 'asset.asset';
scope.noEntitiesMatchingText = 'asset.no-assets-matching';
- scope.entityRequiredText = 'asset.asset-required'
+ scope.entityRequiredText = 'asset.asset-required';
break;
case types.entityType.device:
scope.selectEntityText = 'device.select-device';
scope.entityText = 'device.device';
scope.noEntitiesMatchingText = 'device.no-devices-matching';
- scope.entityRequiredText = 'device.device-required'
+ scope.entityRequiredText = 'device.device-required';
break;
case types.entityType.rule:
scope.selectEntityText = 'rule.select-rule';
scope.entityText = 'rule.rule';
scope.noEntitiesMatchingText = 'rule.no-rules-matching';
- scope.entityRequiredText = 'rule.rule-required'
+ scope.entityRequiredText = 'rule.rule-required';
break;
case types.entityType.plugin:
scope.selectEntityText = 'plugin.select-plugin';
scope.entityText = 'plugin.plugin';
scope.noEntitiesMatchingText = 'plugin.no-plugins-matching';
- scope.entityRequiredText = 'plugin.plugin-required'
+ scope.entityRequiredText = 'plugin.plugin-required';
break;
case types.entityType.tenant:
scope.selectEntityText = 'tenant.select-tenant';
scope.entityText = 'tenant.tenant';
scope.noEntitiesMatchingText = 'tenant.no-tenants-matching';
- scope.entityRequiredText = 'tenant.tenant-required'
+ scope.entityRequiredText = 'tenant.tenant-required';
break;
case types.entityType.customer:
scope.selectEntityText = 'customer.select-customer';
scope.entityText = 'customer.customer';
scope.noEntitiesMatchingText = 'customer.no-customers-matching';
- scope.entityRequiredText = 'customer.customer-required'
+ scope.entityRequiredText = 'customer.customer-required';
break;
case types.entityType.user:
scope.selectEntityText = 'user.select-user';
scope.entityText = 'user.user';
scope.noEntitiesMatchingText = 'user.no-users-matching';
- scope.entityRequiredText = 'user.user-required'
+ scope.entityRequiredText = 'user.user-required';
break;
case types.entityType.dashboard:
scope.selectEntityText = 'dashboard.select-dashboard';
scope.entityText = 'dashboard.dashboard';
scope.noEntitiesMatchingText = 'dashboard.no-dashboards-matching';
- scope.entityRequiredText = 'dashboard.dashboard-required'
+ scope.entityRequiredText = 'dashboard.dashboard-required';
break;
case types.entityType.alarm:
scope.selectEntityText = 'alarm.select-alarm';
scope.entityText = 'alarm.alarm';
scope.noEntitiesMatchingText = 'alarm.no-alarms-matching';
- scope.entityRequiredText = 'alarm.alarm-required'
+ scope.entityRequiredText = 'alarm.alarm-required';
+ break;
+ case types.aliasEntityType.current_customer:
+ scope.selectEntityText = 'customer.select-default-customer';
+ scope.entityText = 'customer.default-customer';
+ scope.noEntitiesMatchingText = 'customer.no-customers-matching';
+ scope.entityRequiredText = 'customer.default-customer-required';
break;
}
if (scope.entity && scope.entity.id.entityType != scope.entityType) {
diff --git a/ui/src/app/entity/entity-filter.tpl.html b/ui/src/app/entity/entity-filter.tpl.html
index 9f62454..0e8ee11 100644
--- a/ui/src/app/entity/entity-filter.tpl.html
+++ b/ui/src/app/entity/entity-filter.tpl.html
@@ -32,6 +32,7 @@
<tb-entity-select flex
the-form="theForm"
tb-required="true"
+ use-alias-entity-types="true"
ng-model="filter.singleEntity">
</tb-entity-select>
</section>
@@ -78,6 +79,7 @@
<tb-entity-select flex
the-form="theForm"
tb-required="false"
+ use-alias-entity-types="true"
ng-model="filter.defaultStateEntity">
</tb-entity-select>
</div>
@@ -123,6 +125,7 @@
the-form="theForm"
tb-required="!filter.rootStateEntity"
ng-disabled="filter.rootStateEntity"
+ use-alias-entity-types="true"
ng-model="filter.rootEntity">
</tb-entity-select>
</div>
@@ -139,6 +142,7 @@
<tb-entity-select flex
the-form="theForm"
tb-required="false"
+ use-alias-entity-types="true"
ng-model="filter.defaultStateEntity">
</tb-entity-select>
</div>
@@ -182,6 +186,7 @@
the-form="theForm"
tb-required="!filter.rootStateEntity"
ng-disabled="filter.rootStateEntity"
+ use-alias-entity-types="true"
ng-model="filter.rootEntity">
</tb-entity-select>
</div>
@@ -198,6 +203,7 @@
<tb-entity-select flex
the-form="theForm"
tb-required="false"
+ use-alias-entity-types="true"
ng-model="filter.defaultStateEntity">
</tb-entity-select>
</div>
@@ -249,6 +255,7 @@
the-form="theForm"
tb-required="!filter.rootStateEntity"
ng-disabled="filter.rootStateEntity"
+ use-alias-entity-types="true"
ng-model="filter.rootEntity">
</tb-entity-select>
</div>
@@ -265,6 +272,7 @@
<tb-entity-select flex
the-form="theForm"
tb-required="false"
+ use-alias-entity-types="true"
ng-model="filter.defaultStateEntity">
</tb-entity-select>
</div>
diff --git a/ui/src/app/entity/entity-select.directive.js b/ui/src/app/entity/entity-select.directive.js
index 2778a79..8e2fbf9 100644
--- a/ui/src/app/entity/entity-select.directive.js
+++ b/ui/src/app/entity/entity-select.directive.js
@@ -105,7 +105,8 @@ export default function EntitySelect($compile, $templateCache) {
scope: {
theForm: '=?',
tbRequired: '=?',
- disabled:'=ngDisabled'
+ disabled:'=ngDisabled',
+ useAliasEntityTypes: "=?"
}
};
}
diff --git a/ui/src/app/entity/entity-select.tpl.html b/ui/src/app/entity/entity-select.tpl.html
index 13e17e7..d370202 100644
--- a/ui/src/app/entity/entity-select.tpl.html
+++ b/ui/src/app/entity/entity-select.tpl.html
@@ -20,6 +20,7 @@
the-form="theForm"
ng-disabled="disabled"
tb-required="tbRequired"
+ use-alias-entity-types="useAliasEntityTypes"
ng-model="model.entityType">
</tb-entity-type-select>
<tb-entity-autocomplete flex ng-if="model.entityType"
diff --git a/ui/src/app/entity/entity-type-select.directive.js b/ui/src/app/entity/entity-type-select.directive.js
index 068c141..fd694c9 100644
--- a/ui/src/app/entity/entity-type-select.directive.js
+++ b/ui/src/app/entity/entity-type-select.directive.js
@@ -39,7 +39,7 @@ export default function EntityTypeSelect($compile, $templateCache, utils, entity
scope.ngModelCtrl = ngModelCtrl;
- scope.entityTypes = entityService.prepareAllowedEntityTypesList(scope.allowedEntityTypes);
+ scope.entityTypes = entityService.prepareAllowedEntityTypesList(scope.allowedEntityTypes, scope.useAliasEntityTypes);
scope.typeName = function(type) {
return type ? types.entityTypeTranslations[type].type : '';
@@ -79,7 +79,8 @@ export default function EntityTypeSelect($compile, $templateCache, utils, entity
theForm: '=?',
tbRequired: '=?',
disabled:'=ngDisabled',
- allowedEntityTypes: "=?"
+ allowedEntityTypes: "=?",
+ useAliasEntityTypes: "=?"
}
};
}
diff --git a/ui/src/app/import-export/import-export.service.js b/ui/src/app/import-export/import-export.service.js
index 62e1bb3..8a5948c 100644
--- a/ui/src/app/import-export/import-export.service.js
+++ b/ui/src/app/import-export/import-export.service.js
@@ -540,7 +540,7 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
function success(dashboard) {
var name = dashboard.title;
name = name.toLowerCase().replace(/\W/g,"_");
- exportToPc(prepareExport(dashboard), name + '.json');
+ exportToPc(prepareDashboardExport(dashboard), name + '.json');
},
function fail(rejection) {
var message = rejection;
@@ -552,6 +552,15 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
);
}
+ function prepareDashboardExport(dashboard) {
+ dashboard = prepareExport(dashboard);
+ delete dashboard.assignedCustomers;
+ delete dashboard.publicCustomerId;
+ delete dashboard.assignedCustomersText;
+ delete dashboard.assignedCustomersIds;
+ return dashboard;
+ }
+
function importDashboard($event) {
var deferred = $q.defer();
openImportDialog($event, 'dashboard.import', 'dashboard.dashboard-file').then(
ui/src/app/locale/locale.constant.js 16(+14 -2)
diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js
index 96dc152..f66347c 100644
--- a/ui/src/app/locale/locale.constant.js
+++ b/ui/src/app/locale/locale.constant.js
@@ -383,7 +383,10 @@ export default angular.module('thingsboard.locale', [])
"idCopiedMessage": "Customer Id has been copied to clipboard",
"select-customer": "Select customer",
"no-customers-matching": "No customers matching '{{entity}}' were found.",
- "customer-required": "Customer is required"
+ "customer-required": "Customer is required",
+ "select-default-customer": "Select default customer",
+ "default-customer": "Default customer",
+ "default-customer-required": "Default customer is required in order to debug dashboard on Tenant level"
},
"datetime": {
"date-from": "Date from",
@@ -404,6 +407,12 @@ export default angular.module('thingsboard.locale', [])
"unassign-from-customer": "Unassign from customer",
"make-public": "Make dashboard public",
"make-private": "Make dashboard private",
+ "manage-assigned-customers": "Manage assigned customers",
+ "assigned-customers": "Assigned customers",
+ "assign-to-customers": "Assign Dashboard(s) To Customers",
+ "assign-to-customers-text": "Please select the customers to assign the dashboard(s)",
+ "unassign-from-customers": "Unassign Dashboard(s) From Customers",
+ "unassign-from-customers-text": "Please select the customers to unassign from the dashboard(s)",
"no-dashboards-text": "No dashboards found",
"no-widgets": "No widgets configured",
"add-widget": "Add new widget",
@@ -418,7 +427,8 @@ export default angular.module('thingsboard.locale', [])
"add-dashboard-text": "Add new dashboard",
"assign-dashboards": "Assign dashboards",
"assign-new-dashboard": "Assign new dashboard",
- "assign-dashboards-text": "Assign { count, select, 1 {1 dashboard} other {# dashboards} } to customer",
+ "assign-dashboards-text": "Assign { count, select, 1 {1 dashboard} other {# dashboards} } to customers",
+ "unassign-dashboards-action-text": "Unassign { count, select, 1 {1 dashboard} other {# dashboards} } from customers",
"delete-dashboards": "Delete dashboards",
"unassign-dashboards": "Unassign dashboards",
"unassign-dashboards-action-title": "Unassign { count, select, 1 {1 dashboard} other {# dashboards} } from customer",
@@ -500,6 +510,7 @@ export default angular.module('thingsboard.locale', [])
"Please contact your administrator in order to resolve this issue.",
"select-devices": "Select devices",
"assignedToCustomer": "Assigned to customer",
+ "assignedToCustomers": "Assigned to customers",
"public": "Public",
"public-link": "Public link",
"copy-public-link": "Copy public link",
@@ -735,6 +746,7 @@ export default angular.module('thingsboard.locale', [])
"type-alarms": "Alarms",
"list-of-alarms": "{ count, select, 1 {One alarms} other {List of # alarms} }",
"alarm-name-starts-with": "Alarms whose names start with '{{prefix}}'",
+ "type-current-customer": "Current Customer",
"search": "Search entities",
"selected-entities": "{ count, select, 1 {1 entity} other {# entities} } selected",
"entity-name": "Entity name",