44 changed files with 1983 additions and 7 deletions
@ -0,0 +1,32 @@ |
|||
-- |
|||
-- Copyright © 2016-2019 The Thingsboard Authors |
|||
-- |
|||
-- Licensed under the Apache License, Version 2.0 (the "License"); |
|||
-- you may not use this file except in compliance with the License. |
|||
-- You may obtain a copy of the License at |
|||
-- |
|||
-- http://www.apache.org/licenses/LICENSE-2.0 |
|||
-- |
|||
-- Unless required by applicable law or agreed to in writing, software |
|||
-- distributed under the License is distributed on an "AS IS" BASIS, |
|||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
-- See the License for the specific language governing permissions and |
|||
-- limitations under the License. |
|||
-- |
|||
|
|||
CREATE TABLE IF NOT EXISTS thingsboard.edge ( |
|||
id timeuuid, |
|||
tenant_id timeuuid, |
|||
name text, |
|||
search_text text, |
|||
configuration text, |
|||
additional_info text, |
|||
PRIMARY KEY (id, tenant_id) |
|||
); |
|||
|
|||
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.edge_by_tenant_and_search_text AS |
|||
SELECT * |
|||
from thingsboard.edge |
|||
WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL |
|||
PRIMARY KEY ( tenant_id, search_text, id ) |
|||
WITH CLUSTERING ORDER BY ( search_text ASC, id DESC ); |
|||
@ -0,0 +1,24 @@ |
|||
-- |
|||
-- Copyright © 2016-2019 The Thingsboard Authors |
|||
-- |
|||
-- Licensed under the Apache License, Version 2.0 (the "License"); |
|||
-- you may not use this file except in compliance with the License. |
|||
-- You may obtain a copy of the License at |
|||
-- |
|||
-- http://www.apache.org/licenses/LICENSE-2.0 |
|||
-- |
|||
-- Unless required by applicable law or agreed to in writing, software |
|||
-- distributed under the License is distributed on an "AS IS" BASIS, |
|||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
-- See the License for the specific language governing permissions and |
|||
-- limitations under the License. |
|||
-- |
|||
|
|||
CREATE TABLE IF NOT EXISTS edge ( |
|||
id varchar(31) NOT NULL CONSTRAINT edge_pkey PRIMARY KEY, |
|||
additional_info varchar, |
|||
configuration varchar(10000000), |
|||
name varchar(255), |
|||
search_text varchar(255), |
|||
tenant_id varchar(31) |
|||
); |
|||
@ -0,0 +1,163 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.controller; |
|||
|
|||
import org.springframework.http.HttpStatus; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.web.bind.annotation.PathVariable; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestMethod; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
import org.springframework.web.bind.annotation.ResponseStatus; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.TextPageData; |
|||
import org.thingsboard.server.common.data.page.TextPageLink; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
import org.thingsboard.server.service.security.permission.Operation; |
|||
import org.thingsboard.server.service.security.permission.Resource; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@RestController |
|||
@RequestMapping("/api") |
|||
public class EdgeController extends BaseController { |
|||
|
|||
private static final String EDGE_ID = "edgeId"; |
|||
|
|||
@PreAuthorize("hasAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.GET) |
|||
@ResponseBody |
|||
public Edge getEdgeById(@PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { |
|||
checkParameter(EDGE_ID, strEdgeId); |
|||
try { |
|||
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); |
|||
return checkEdgeId(edgeId, Operation.READ); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/edge", method = RequestMethod.POST) |
|||
@ResponseBody |
|||
public Edge saveEdge(@RequestBody Edge edge) throws ThingsboardException { |
|||
try { |
|||
edge.setTenantId(getCurrentUser().getTenantId()); |
|||
boolean created = edge.getId() == null; |
|||
|
|||
Operation operation = created ? Operation.CREATE : Operation.WRITE; |
|||
|
|||
accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, operation, |
|||
edge.getId(), edge); |
|||
|
|||
Edge result = checkNotNull(edgeService.saveEdge(edge)); |
|||
|
|||
logEntityAction(result.getId(), result, null, created ? ActionType.ADDED : ActionType.UPDATED, null); |
|||
return result; |
|||
} catch (Exception e) { |
|||
logEntityAction(emptyId(EntityType.EDGE), edge, |
|||
null, edge.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
|
|||
@PreAuthorize("hasAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/edges", params = {"limit"}, method = RequestMethod.GET) |
|||
@ResponseBody |
|||
public TextPageData<Edge> getEdges( |
|||
@RequestParam int limit, |
|||
@RequestParam(required = false) String textSearch, |
|||
@RequestParam(required = false) String idOffset, |
|||
@RequestParam(required = false) String textOffset) throws ThingsboardException { |
|||
try { |
|||
accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, Operation.READ); |
|||
TenantId tenantId = getCurrentUser().getTenantId(); |
|||
TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); |
|||
return checkNotNull(edgeService.findTenantEdges(tenantId, pageLink)); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.DELETE) |
|||
@ResponseStatus(value = HttpStatus.OK) |
|||
public void deleteEdge(@PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { |
|||
checkParameter(EDGE_ID, strEdgeId); |
|||
try { |
|||
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); |
|||
Edge edge = checkEdgeId(edgeId, Operation.DELETE); |
|||
edgeService.deleteEdge(getTenantId(), edgeId); |
|||
|
|||
logEntityAction(edgeId, edge, |
|||
null, |
|||
ActionType.DELETED, null, strEdgeId); |
|||
|
|||
} catch (Exception e) { |
|||
|
|||
logEntityAction(emptyId(EntityType.EDGE), |
|||
null, |
|||
null, |
|||
ActionType.DELETED, e, strEdgeId); |
|||
|
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/edges", params = {"edgeIds"}, method = RequestMethod.GET) |
|||
@ResponseBody |
|||
public List<Edge> getEdgesByIds( |
|||
@RequestParam("edgeIds") String[] strEdgeIds) throws ThingsboardException { |
|||
checkArrayParameter("edgeIds", strEdgeIds); |
|||
try { |
|||
accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, Operation.READ); |
|||
SecurityUser user = getCurrentUser(); |
|||
TenantId tenantId = user.getTenantId(); |
|||
List<EdgeId> edgeIds = new ArrayList<>(); |
|||
for (String strEdgeId : strEdgeIds) { |
|||
edgeIds.add(new EdgeId(toUUID(strEdgeId))); |
|||
} |
|||
List<Edge> edges = checkNotNull(edgeService.findEdgesByIdsAsync(tenantId, edgeIds).get()); |
|||
return filterEdgesByReadPermission(edges); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
private List<Edge> filterEdgesByReadPermission(List<Edge> edges) { |
|||
return edges.stream().filter(edge -> { |
|||
try { |
|||
accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, Operation.READ, edge.getId(), edge); |
|||
return true; |
|||
} catch (ThingsboardException e) { |
|||
return false; |
|||
} |
|||
}).collect(Collectors.toList()); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,206 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.controller; |
|||
|
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import org.apache.commons.lang3.RandomStringUtils; |
|||
import org.junit.After; |
|||
import org.junit.Assert; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.User; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.page.TextPageData; |
|||
import org.thingsboard.server.common.data.page.TextPageLink; |
|||
import org.thingsboard.server.common.data.security.Authority; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
|
|||
import static org.hamcrest.Matchers.containsString; |
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
public abstract class BaseEdgeControllerTest extends AbstractControllerTest { |
|||
|
|||
private IdComparator<Edge> idComparator; |
|||
private Tenant savedTenant; |
|||
private User tenantAdmin; |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
loginSysAdmin(); |
|||
idComparator = new IdComparator<>(); |
|||
|
|||
savedTenant = doPost("/api/tenant", getNewTenant("My tenant"), Tenant.class); |
|||
Assert.assertNotNull(savedTenant); |
|||
|
|||
tenantAdmin = new User(); |
|||
tenantAdmin.setAuthority(Authority.TENANT_ADMIN); |
|||
tenantAdmin.setTenantId(savedTenant.getId()); |
|||
tenantAdmin.setEmail("tenant2@thingsboard.org"); |
|||
tenantAdmin.setFirstName("Joe"); |
|||
tenantAdmin.setLastName("Downs"); |
|||
tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); |
|||
|
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
loginSysAdmin(); |
|||
doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) |
|||
.andExpect(status().isOk()); |
|||
} |
|||
|
|||
@Test |
|||
public void testFindEdgeById() throws Exception { |
|||
Edge savedEdge = getNewSavedEdge("Test edge"); |
|||
Edge foundEdge = doGet("/api/edge/" + savedEdge.getId().getId().toString(), Edge.class); |
|||
Assert.assertNotNull(foundEdge); |
|||
assertEquals(savedEdge, foundEdge); |
|||
} |
|||
|
|||
@Test |
|||
public void testSaveEdge() throws Exception { |
|||
Edge savedEdge = getNewSavedEdge("Test edge"); |
|||
|
|||
Assert.assertNotNull(savedEdge); |
|||
Assert.assertNotNull(savedEdge.getId()); |
|||
Assert.assertTrue(savedEdge.getCreatedTime() > 0); |
|||
assertEquals(savedTenant.getId(), savedEdge.getTenantId()); |
|||
|
|||
savedEdge.setName("New test edge"); |
|||
doPost("/api/edge", savedEdge, Edge.class); |
|||
Edge foundEdge = doGet("/api/edge/" + savedEdge.getId().getId().toString(), Edge.class); |
|||
|
|||
assertEquals(foundEdge.getName(), savedEdge.getName()); |
|||
} |
|||
|
|||
@Test |
|||
public void testDeleteEdge() throws Exception { |
|||
Edge edge = getNewSavedEdge("Test edge"); |
|||
Edge savedEdge = doPost("/api/edge", edge, Edge.class); |
|||
|
|||
doDelete("/api/edge/" + savedEdge.getId().getId().toString()) |
|||
.andExpect(status().isOk()); |
|||
|
|||
doGet("/api/edge/" + savedEdge.getId().getId().toString()) |
|||
.andExpect(status().isNotFound()); |
|||
} |
|||
|
|||
@Test |
|||
public void testSaveEdgeWithEmptyName() throws Exception { |
|||
Edge edge = new Edge(); |
|||
doPost("/api/edge", edge) |
|||
.andExpect(status().isBadRequest()) |
|||
.andExpect(statusReason(containsString("Edge name should be specified!"))); |
|||
} |
|||
|
|||
@Test |
|||
public void testGetEdges() throws Exception { |
|||
|
|||
List<Edge> edges = new ArrayList<>(); |
|||
for (int i = 0; i < 178; i++) { |
|||
edges.add(getNewSavedEdge("Test edge " + i)); |
|||
} |
|||
List<Edge> loadedEdges = loadListOf(new TextPageLink(23), "/api/edges?"); |
|||
|
|||
Collections.sort(edges, idComparator); |
|||
Collections.sort(loadedEdges, idComparator); |
|||
|
|||
assertEquals(edges, loadedEdges); |
|||
} |
|||
|
|||
@Test |
|||
public void testGetEdgesByName() throws Exception { |
|||
String name1 = "Entity edge1"; |
|||
List<Edge> namesOfEdge1 = fillListOf(143, name1); |
|||
List<Edge> loadedNamesOfEdge1 = loadListOf(new TextPageLink(15, name1), "/api/edges?"); |
|||
Collections.sort(namesOfEdge1, idComparator); |
|||
Collections.sort(loadedNamesOfEdge1, idComparator); |
|||
assertEquals(namesOfEdge1, loadedNamesOfEdge1); |
|||
|
|||
String name2 = "Entity edge2"; |
|||
List<Edge> namesOfEdge2 = fillListOf(75, name2); |
|||
List<Edge> loadedNamesOfEdge2 = loadListOf(new TextPageLink(4, name2), "/api/edges?"); |
|||
Collections.sort(namesOfEdge2, idComparator); |
|||
Collections.sort(loadedNamesOfEdge2, idComparator); |
|||
assertEquals(namesOfEdge2, loadedNamesOfEdge2); |
|||
|
|||
for (Edge edge : loadedNamesOfEdge1) { |
|||
doDelete("/api/edge/" + edge.getId().getId().toString()).andExpect(status().isOk()); |
|||
} |
|||
TextPageData<Edge> pageData = doGetTypedWithPageLink("/api/edges?", |
|||
new TypeReference<TextPageData<Edge>>() { |
|||
}, new TextPageLink(4, name1)); |
|||
Assert.assertFalse(pageData.hasNext()); |
|||
assertEquals(0, pageData.getData().size()); |
|||
|
|||
for (Edge edge : loadedNamesOfEdge2) { |
|||
doDelete("/api/edge/" + edge.getId().getId().toString()).andExpect(status().isOk()); |
|||
} |
|||
pageData = doGetTypedWithPageLink("/api/edges?", new TypeReference<TextPageData<Edge>>() { |
|||
}, new TextPageLink(4, name2)); |
|||
Assert.assertFalse(pageData.hasNext()); |
|||
assertEquals(0, pageData.getData().size()); |
|||
} |
|||
|
|||
private Edge getNewSavedEdge(String name) throws Exception { |
|||
Edge edge = createEdge(name); |
|||
return doPost("/api/edge", edge, Edge.class); |
|||
} |
|||
|
|||
private Edge createEdge(String name) { |
|||
Edge edge = new Edge(); |
|||
edge.setTenantId(savedTenant.getId()); |
|||
edge.setName(name); |
|||
return edge; |
|||
} |
|||
|
|||
private Tenant getNewTenant(String title) { |
|||
Tenant tenant = new Tenant(); |
|||
tenant.setTitle(title); |
|||
return tenant; |
|||
} |
|||
|
|||
private List<Edge> fillListOf(int limit, String partOfName) throws Exception { |
|||
List<Edge> edgeNames = new ArrayList<>(); |
|||
for (int i = 0; i < limit; i++) { |
|||
String fullName = partOfName + ' ' + RandomStringUtils.randomAlphanumeric(15); |
|||
fullName = i % 2 == 0 ? fullName.toLowerCase() : fullName.toUpperCase(); |
|||
Edge edge = getNewSavedEdge(fullName); |
|||
edgeNames.add(doPost("/api/edge", edge, Edge.class)); |
|||
} |
|||
return edgeNames; |
|||
} |
|||
|
|||
private List<Edge> loadListOf(TextPageLink pageLink, String urlTemplate) throws Exception { |
|||
List<Edge> loadedItems = new ArrayList<>(); |
|||
TextPageData<Edge> pageData; |
|||
do { |
|||
pageData = doGetTypedWithPageLink(urlTemplate, new TypeReference<TextPageData<Edge>>() { |
|||
}, pageLink); |
|||
loadedItems.addAll(pageData.getData()); |
|||
if (pageData.hasNext()) { |
|||
pageLink = pageData.getNextPageLink(); |
|||
} |
|||
} while (pageData.hasNext()); |
|||
|
|||
return loadedItems; |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.controller.nosql; |
|||
|
|||
import org.thingsboard.server.controller.BaseEdgeControllerTest; |
|||
import org.thingsboard.server.dao.service.DaoNoSqlTest; |
|||
|
|||
@DaoNoSqlTest |
|||
public class EdgeControllerNoSqlTest extends BaseEdgeControllerTest { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.controller.sql; |
|||
|
|||
import org.thingsboard.server.controller.BaseEdgeControllerTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class EdgeControllerSqlTest extends BaseEdgeControllerTest { |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.edge; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.TextPageData; |
|||
import org.thingsboard.server.common.data.page.TextPageLink; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface EdgeService { |
|||
|
|||
Edge saveEdge(Edge edge); |
|||
|
|||
Edge findEdgeById(TenantId tenantId, EdgeId edgeId); |
|||
|
|||
ListenableFuture<Edge> findEdgeByIdAsync(TenantId tenantId, EdgeId edgeId); |
|||
|
|||
ListenableFuture<List<Edge>> findEdgesByIdsAsync(TenantId tenantId, List<EdgeId> edgeIds); |
|||
|
|||
List<Edge> findAllEdges(TenantId tenantId); |
|||
|
|||
TextPageData<Edge> findTenantEdges(TenantId tenantId, TextPageLink pageLink); |
|||
|
|||
void deleteEdge(TenantId tenantId, EdgeId edgeId); |
|||
|
|||
void deleteEdgesByTenantId(TenantId tenantId); |
|||
|
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.common.data.edge; |
|||
|
|||
import com.fasterxml.jackson.databind.JsonNode; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
import lombok.ToString; |
|||
import org.thingsboard.server.common.data.HasCustomerId; |
|||
import org.thingsboard.server.common.data.HasName; |
|||
import org.thingsboard.server.common.data.HasTenantId; |
|||
import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
@EqualsAndHashCode(callSuper = true) |
|||
@ToString |
|||
@Getter |
|||
@Setter |
|||
public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements HasName, HasTenantId, HasCustomerId { |
|||
|
|||
private static final long serialVersionUID = 4934987555236873728L; |
|||
|
|||
private TenantId tenantId; |
|||
private CustomerId customerId; |
|||
private String name; |
|||
private transient JsonNode configuration; |
|||
private transient JsonNode additionalInfo; |
|||
|
|||
public Edge() { |
|||
super(); |
|||
} |
|||
|
|||
public Edge(EdgeId id) { |
|||
super(id); |
|||
} |
|||
|
|||
public Edge(Edge edge) { |
|||
super(edge); |
|||
this.tenantId = edge.getTenantId(); |
|||
this.name = edge.getName(); |
|||
this.configuration = edge.getConfiguration(); |
|||
this.additionalInfo = edge.getAdditionalInfo(); |
|||
} |
|||
|
|||
@Override |
|||
public String getSearchText() { |
|||
return getName(); |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.common.data.id; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonCreator; |
|||
import com.fasterxml.jackson.annotation.JsonIgnore; |
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
public class EdgeId extends UUIDBased implements EntityId { |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
@JsonCreator |
|||
public EdgeId(@JsonProperty("id") UUID id) { |
|||
super(id); |
|||
} |
|||
|
|||
public static EdgeId fromString(String integrationId) { |
|||
return new EdgeId(UUID.fromString(integrationId)); |
|||
} |
|||
|
|||
@JsonIgnore |
|||
@Override |
|||
public EntityType getEntityType() { |
|||
return EntityType.EDGE; |
|||
} |
|||
} |
|||
@ -0,0 +1,156 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.edge; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.util.StringUtils; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.TextPageData; |
|||
import org.thingsboard.server.common.data.page.TextPageLink; |
|||
import org.thingsboard.server.dao.entity.AbstractEntityService; |
|||
import org.thingsboard.server.dao.exception.DataValidationException; |
|||
import org.thingsboard.server.dao.service.DataValidator; |
|||
import org.thingsboard.server.dao.service.PaginatedRemover; |
|||
import org.thingsboard.server.dao.tenant.TenantDao; |
|||
|
|||
import java.util.List; |
|||
|
|||
import static org.thingsboard.server.dao.DaoUtil.toUUIDs; |
|||
import static org.thingsboard.server.dao.service.Validator.validateId; |
|||
import static org.thingsboard.server.dao.service.Validator.validateIds; |
|||
import static org.thingsboard.server.dao.service.Validator.validatePageLink; |
|||
|
|||
@Service |
|||
@Slf4j |
|||
public class BaseEdgeService extends AbstractEntityService implements EdgeService { |
|||
|
|||
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; |
|||
public static final String INCORRECT_PAGE_LINK = "Incorrect page link "; |
|||
public static final String INCORRECT_EDGE_ID = "Incorrect edgeId "; |
|||
|
|||
@Autowired |
|||
private EdgeDao edgeDao; |
|||
|
|||
@Autowired |
|||
private TenantDao tenantDao; |
|||
|
|||
@Override |
|||
public Edge saveEdge(Edge edge) { |
|||
log.trace("Executing saveEdge [{}]", edge); |
|||
edgeValidator.validate(edge, Edge::getTenantId); |
|||
return edgeDao.save(edge.getTenantId(), edge); |
|||
} |
|||
|
|||
@Override |
|||
public Edge findEdgeById(TenantId tenantId, EdgeId edgeId) { |
|||
log.trace("Executing findEdgeById [{}]", edgeId); |
|||
validateId(edgeId, INCORRECT_EDGE_ID + edgeId); |
|||
return edgeDao.findById(tenantId, edgeId.getId()); |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<Edge> findEdgeByIdAsync(TenantId tenantId, EdgeId edgeId) { |
|||
log.trace("Executing findEdgeByIdAsync [{}]", edgeId); |
|||
validateId(edgeId, INCORRECT_EDGE_ID + edgeId); |
|||
return edgeDao.findByIdAsync(tenantId, edgeId.getId()); |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<List<Edge>> findEdgesByIdsAsync(TenantId tenantId, List<EdgeId> edgeIds) { |
|||
log.trace("Executing findEdgesByIdsAsync, tenantId [{}], edgeIds [{}]", tenantId, edgeIds); |
|||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
|||
validateIds(edgeIds, "Incorrect edgeIds " + edgeIds); |
|||
return edgeDao.findEdgesByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(edgeIds)); |
|||
} |
|||
|
|||
@Override |
|||
public List<Edge> findAllEdges(TenantId tenantId) { |
|||
log.trace("Executing findAllEdges"); |
|||
return edgeDao.find(tenantId); |
|||
} |
|||
|
|||
@Override |
|||
public TextPageData<Edge> findTenantEdges(TenantId tenantId, TextPageLink pageLink) { |
|||
log.trace("Executing findTenantEdges, tenantId [{}], pageLink [{}]", tenantId, pageLink); |
|||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
|||
validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink); |
|||
List<Edge> edges = edgeDao.findByTenantIdAndPageLink(tenantId.getId(), pageLink); |
|||
return new TextPageData<>(edges, pageLink); |
|||
} |
|||
|
|||
@Override |
|||
public void deleteEdge(TenantId tenantId, EdgeId edgeId) { |
|||
log.trace("Executing deleteEdge [{}]", edgeId); |
|||
validateId(edgeId, INCORRECT_EDGE_ID + edgeId); |
|||
deleteEntityRelations(tenantId, edgeId); |
|||
edgeDao.removeById(tenantId, edgeId.getId()); |
|||
} |
|||
|
|||
@Override |
|||
public void deleteEdgesByTenantId(TenantId tenantId) { |
|||
log.trace("Executing deleteEdgesByTenantId, tenantId [{}]", tenantId); |
|||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
|||
tenantEdgesRemover.removeEntities(tenantId, tenantId); |
|||
} |
|||
|
|||
private DataValidator<Edge> edgeValidator = |
|||
new DataValidator<Edge>() { |
|||
|
|||
@Override |
|||
protected void validateCreate(TenantId tenantId, Edge edge) { |
|||
} |
|||
|
|||
@Override |
|||
protected void validateUpdate(TenantId tenantId, Edge edge) { |
|||
} |
|||
|
|||
@Override |
|||
protected void validateDataImpl(TenantId tenantId, Edge edge) { |
|||
if (StringUtils.isEmpty(edge.getName())) { |
|||
throw new DataValidationException("Edge name should be specified!"); |
|||
} |
|||
if (edge.getTenantId() == null || edge.getTenantId().isNullUid()) { |
|||
throw new DataValidationException("Edge should be assigned to tenant!"); |
|||
} else { |
|||
Tenant tenant = tenantDao.findById(tenantId, edge.getTenantId().getId()); |
|||
if (tenant == null) { |
|||
throw new DataValidationException("Edge is referencing to non-existent tenant!"); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
private PaginatedRemover<TenantId, Edge> tenantEdgesRemover = |
|||
new PaginatedRemover<TenantId, Edge>() { |
|||
|
|||
@Override |
|||
protected List<Edge> findEntities(TenantId tenantId, TenantId id, TextPageLink pageLink) { |
|||
return edgeDao.findByTenantIdAndPageLink(id.getId(), pageLink); |
|||
} |
|||
|
|||
@Override |
|||
protected void removeEntity(TenantId tenantId, Edge entity) { |
|||
deleteEdge(tenantId, new EdgeId(entity.getId().getId())); |
|||
} |
|||
}; |
|||
|
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.edge; |
|||
|
|||
import com.datastax.driver.core.querybuilder.Select; |
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.TextPageLink; |
|||
import org.thingsboard.server.dao.DaoUtil; |
|||
import org.thingsboard.server.dao.model.nosql.EdgeEntity; |
|||
import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; |
|||
import org.thingsboard.server.dao.util.NoSqlDao; |
|||
|
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
|
|||
import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; |
|||
import static com.datastax.driver.core.querybuilder.QueryBuilder.in; |
|||
import static com.datastax.driver.core.querybuilder.QueryBuilder.select; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY; |
|||
|
|||
@Component |
|||
@Slf4j |
|||
@NoSqlDao |
|||
public class CassandraEdgeDao extends CassandraAbstractSearchTextDao<EdgeEntity, Edge> implements EdgeDao { |
|||
|
|||
@Override |
|||
protected Class<EdgeEntity> getColumnFamilyClass() { |
|||
return EdgeEntity.class; |
|||
} |
|||
|
|||
@Override |
|||
protected String getColumnFamilyName() { |
|||
return EDGE_COLUMN_FAMILY_NAME; |
|||
} |
|||
|
|||
@Override |
|||
public List<Edge> findByTenantIdAndPageLink(UUID tenantId, TextPageLink pageLink) { |
|||
log.debug("Try to find edges by tenantId [{}] and pageLink [{}]", tenantId, pageLink); |
|||
List<EdgeEntity> edgeEntities = findPageWithTextSearch(new TenantId(tenantId), EDGE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, |
|||
Collections.singletonList(eq(EDGE_TENANT_ID_PROPERTY, tenantId)), pageLink); |
|||
|
|||
log.trace("Found edges [{}] by tenantId [{}] and pageLink [{}]", edgeEntities, tenantId, pageLink); |
|||
return DaoUtil.convertDataList(edgeEntities); |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<List<Edge>> findEdgesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> edgeIds) { |
|||
log.debug("Try to find edges by tenantId [{}] and edge Ids [{}]", tenantId, edgeIds); |
|||
Select select = select().from(getColumnFamilyName()); |
|||
Select.Where query = select.where(); |
|||
query.and(eq(EDGE_TENANT_ID_PROPERTY, tenantId)); |
|||
query.and(in(ID_PROPERTY, edgeIds)); |
|||
return findListByStatementAsync(new TenantId(tenantId), query); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.edge; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.page.TextPageLink; |
|||
import org.thingsboard.server.dao.Dao; |
|||
|
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
|
|||
/** |
|||
* The Interface EdgeDao. |
|||
* |
|||
*/ |
|||
public interface EdgeDao extends Dao<Edge> { |
|||
|
|||
/** |
|||
* Find edges by tenantId and page link. |
|||
* |
|||
* @param tenantId the tenantId |
|||
* @param pageLink the page link |
|||
* @return the list of edge objects |
|||
*/ |
|||
List<Edge> findByTenantIdAndPageLink(UUID tenantId, TextPageLink pageLink); |
|||
|
|||
/** |
|||
* Find edges by tenantId and edge Ids. |
|||
* |
|||
* @param tenantId the tenantId |
|||
* @param edgeIds the edge Ids |
|||
* @return the list of edge objects |
|||
*/ |
|||
ListenableFuture<List<Edge>> findEdgesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> edgeIds); |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.model.nosql; |
|||
|
|||
import com.datastax.driver.core.utils.UUIDs; |
|||
import com.datastax.driver.mapping.annotations.ClusteringColumn; |
|||
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.databind.JsonNode; |
|||
import lombok.Data; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
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.UUID; |
|||
|
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ADDITIONAL_INFO_PROPERTY; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CONFIGURATION_PROPERTY; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY; |
|||
|
|||
@Data |
|||
@Table(name = EDGE_COLUMN_FAMILY_NAME) |
|||
public class EdgeEntity implements SearchTextEntity<Edge> { |
|||
|
|||
@PartitionKey |
|||
@Column(name = ID_PROPERTY) |
|||
private UUID id; |
|||
|
|||
@ClusteringColumn |
|||
@Column(name = EDGE_TENANT_ID_PROPERTY) |
|||
private UUID tenantId; |
|||
|
|||
@Column(name = EDGE_NAME_PROPERTY) |
|||
private String name; |
|||
|
|||
@Column(name = SEARCH_TEXT_PROPERTY) |
|||
private String searchText; |
|||
|
|||
@Column(name = EDGE_CONFIGURATION_PROPERTY, codec = JsonCodec.class) |
|||
private JsonNode configuration; |
|||
|
|||
@Column(name = EDGE_ADDITIONAL_INFO_PROPERTY, codec = JsonCodec.class) |
|||
private JsonNode additionalInfo; |
|||
|
|||
public EdgeEntity() { |
|||
super(); |
|||
} |
|||
|
|||
public EdgeEntity(Edge edge) { |
|||
if (edge.getId() != null) { |
|||
this.id = edge.getId().getId(); |
|||
} |
|||
if (edge.getTenantId() != null) { |
|||
this.tenantId = edge.getTenantId().getId(); |
|||
} |
|||
this.name = edge.getName(); |
|||
this.configuration = edge.getConfiguration(); |
|||
this.additionalInfo = edge.getAdditionalInfo(); |
|||
} |
|||
|
|||
@Override |
|||
public String getSearchTextSource() { |
|||
return getName(); |
|||
} |
|||
|
|||
@Override |
|||
public Edge toData() { |
|||
Edge edge = new Edge(new EdgeId(id)); |
|||
edge.setCreatedTime(UUIDs.unixTimestamp(id)); |
|||
if (tenantId != null) { |
|||
edge.setTenantId(new TenantId(tenantId)); |
|||
} |
|||
edge.setName(name); |
|||
edge.setConfiguration(configuration); |
|||
edge.setAdditionalInfo(additionalInfo); |
|||
return edge; |
|||
} |
|||
} |
|||
@ -0,0 +1,108 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.model.sql; |
|||
|
|||
import com.datastax.driver.core.utils.UUIDs; |
|||
import com.fasterxml.jackson.databind.JsonNode; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import org.hibernate.annotations.Type; |
|||
import org.hibernate.annotations.TypeDef; |
|||
import org.thingsboard.server.common.data.UUIDConverter; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.dao.model.BaseSqlEntity; |
|||
import org.thingsboard.server.dao.model.ModelConstants; |
|||
import org.thingsboard.server.dao.model.SearchTextEntity; |
|||
import org.thingsboard.server.dao.util.mapping.JsonStringType; |
|||
|
|||
import javax.persistence.Column; |
|||
import javax.persistence.Entity; |
|||
import javax.persistence.Table; |
|||
|
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY; |
|||
|
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@Entity |
|||
@TypeDef(name = "json", typeClass = JsonStringType.class) |
|||
@Table(name = EDGE_COLUMN_FAMILY_NAME) |
|||
public class EdgeEntity extends BaseSqlEntity<Edge> implements SearchTextEntity<Edge> { |
|||
|
|||
@Column(name = EDGE_TENANT_ID_PROPERTY) |
|||
private String tenantId; |
|||
|
|||
@Column(name = EDGE_NAME_PROPERTY) |
|||
private String name; |
|||
|
|||
@Column(name = SEARCH_TEXT_PROPERTY) |
|||
private String searchText; |
|||
|
|||
@Type(type = "json") |
|||
@Column(name = ModelConstants.EDGE_CONFIGURATION_PROPERTY) |
|||
private JsonNode configuration; |
|||
|
|||
@Type(type = "json") |
|||
@Column(name = ModelConstants.EDGE_ADDITIONAL_INFO_PROPERTY) |
|||
private JsonNode additionalInfo; |
|||
|
|||
public EdgeEntity() { |
|||
super(); |
|||
} |
|||
|
|||
public EdgeEntity(Edge edge) { |
|||
if (edge.getId() != null) { |
|||
this.setId(edge.getId().getId()); |
|||
} |
|||
if (edge.getTenantId() != null) { |
|||
this.tenantId = UUIDConverter.fromTimeUUID(edge.getTenantId().getId()); |
|||
} |
|||
this.name = edge.getName(); |
|||
this.configuration = edge.getConfiguration(); |
|||
this.additionalInfo = edge.getAdditionalInfo(); |
|||
} |
|||
|
|||
public String getSearchText() { |
|||
return searchText; |
|||
} |
|||
|
|||
@Override |
|||
public String getSearchTextSource() { |
|||
return name; |
|||
} |
|||
|
|||
@Override |
|||
public void setSearchText(String searchText) { |
|||
this.searchText = searchText; |
|||
} |
|||
|
|||
@Override |
|||
public Edge toData() { |
|||
Edge edge = new Edge(new EdgeId(UUIDConverter.fromString(id))); |
|||
edge.setCreatedTime(UUIDs.unixTimestamp(UUIDConverter.fromString(id))); |
|||
if (tenantId != null) { |
|||
edge.setTenantId(new TenantId(UUIDConverter.fromString(tenantId))); |
|||
} |
|||
edge.setName(name); |
|||
edge.setConfiguration(configuration); |
|||
edge.setAdditionalInfo(additionalInfo); |
|||
return edge; |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.sql.edge; |
|||
|
|||
import org.springframework.data.domain.Pageable; |
|||
import org.springframework.data.jpa.repository.Query; |
|||
import org.springframework.data.repository.CrudRepository; |
|||
import org.springframework.data.repository.query.Param; |
|||
import org.thingsboard.server.dao.model.sql.EdgeEntity; |
|||
import org.thingsboard.server.dao.util.SqlDao; |
|||
|
|||
import java.util.List; |
|||
|
|||
@SqlDao |
|||
public interface EdgeRepository extends CrudRepository<EdgeEntity, String> { |
|||
|
|||
@Query("SELECT a FROM EdgeEntity a WHERE a.tenantId = :tenantId " + |
|||
"AND LOWER(a.searchText) LIKE LOWER(CONCAT(:textSearch, '%')) " + |
|||
"AND a.id > :idOffset ORDER BY a.id") |
|||
List<EdgeEntity> findByTenantIdAndPageLink(@Param("tenantId") String tenantId, |
|||
@Param("textSearch") String textSearch, |
|||
@Param("idOffset") String idOffset, |
|||
Pageable pageable); |
|||
|
|||
List<EdgeEntity> findEdgesByTenantIdAndIdIn(String tenantId, List<String> edgeIds); |
|||
|
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
/** |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.sql.edge; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.data.domain.PageRequest; |
|||
import org.springframework.data.repository.CrudRepository; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.UUIDConverter; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.page.TextPageLink; |
|||
import org.thingsboard.server.dao.DaoUtil; |
|||
import org.thingsboard.server.dao.edge.EdgeDao; |
|||
import org.thingsboard.server.dao.model.sql.EdgeEntity; |
|||
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; |
|||
import org.thingsboard.server.dao.util.SqlDao; |
|||
|
|||
import java.util.List; |
|||
import java.util.Objects; |
|||
import java.util.UUID; |
|||
|
|||
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; |
|||
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID_STR; |
|||
|
|||
@Component |
|||
@SqlDao |
|||
public class JpaEdgeDao extends JpaAbstractSearchTextDao<EdgeEntity, Edge> implements EdgeDao { |
|||
|
|||
@Autowired |
|||
private EdgeRepository edgeRepository; |
|||
|
|||
@Override |
|||
public List<Edge> findByTenantIdAndPageLink(UUID tenantId, TextPageLink pageLink) { |
|||
return DaoUtil.convertDataList(edgeRepository |
|||
.findByTenantIdAndPageLink( |
|||
fromTimeUUID(tenantId), |
|||
Objects.toString(pageLink.getTextSearch(), ""), |
|||
pageLink.getIdOffset() == null ? NULL_UUID_STR : fromTimeUUID(pageLink.getIdOffset()), |
|||
new PageRequest(0, pageLink.getLimit()))); |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<List<Edge>> findEdgesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> edgeIds) { |
|||
return service.submit(() -> DaoUtil.convertDataList(edgeRepository.findEdgesByTenantIdAndIdIn(UUIDConverter.fromTimeUUID(tenantId), fromTimeUUIDs(edgeIds)))); |
|||
} |
|||
|
|||
@Override |
|||
protected Class<EdgeEntity> getEntityClass() { |
|||
return EdgeEntity.class; |
|||
} |
|||
|
|||
@Override |
|||
protected CrudRepository<EdgeEntity, String> getCrudRepository() { |
|||
return edgeRepository; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
export default angular.module('thingsboard.api.edge', []) |
|||
.factory('edgeService', EdgeService) |
|||
.name; |
|||
|
|||
/*@ngInject*/ |
|||
function EdgeService($http, $q) { |
|||
|
|||
var service = { |
|||
getEdges: getEdges, |
|||
getEdgesByIds: getEdgesByIds, |
|||
getEdge: getEdge, |
|||
deleteEdge: deleteEdge, |
|||
saveEdge: saveEdge |
|||
}; |
|||
|
|||
return service; |
|||
|
|||
function getEdges(pageLink, config) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/edges?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; |
|||
} |
|||
$http.get(url, config).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getEdgesByIds(edgeIds, config) { |
|||
var deferred = $q.defer(); |
|||
var ids = ''; |
|||
for (var i=0;i<edgeIds.length;i++) { |
|||
if (i>0) { |
|||
ids += ','; |
|||
} |
|||
ids += edgeIds[i]; |
|||
} |
|||
var url = '/api/edges?edgeIds=' + ids; |
|||
$http.get(url, config).then(function success(response) { |
|||
var entities = response.data; |
|||
entities.sort(function (entity1, entity2) { |
|||
var id1 = entity1.id.id; |
|||
var id2 = entity2.id.id; |
|||
var index1 = edgeIds.indexOf(id1); |
|||
var index2 = edgeIds.indexOf(id2); |
|||
return index1 - index2; |
|||
}); |
|||
deferred.resolve(entities); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getEdge(edgeId, config) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/edge/' + edgeId; |
|||
$http.get(url, config).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function saveEdge(edge) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/edge'; |
|||
$http.post(url, edge).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function deleteEdge(edgeId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/edge/' + edgeId; |
|||
$http.delete(url).then(function success() { |
|||
deferred.resolve(); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2019 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<md-dialog aria-label="{{ 'edge.add' | translate }}" tb-help="'edges'" help-container-id="help-container" style="width: 600px;"> |
|||
<form name="theForm" ng-submit="vm.add()"> |
|||
<md-toolbar> |
|||
<div class="md-toolbar-tools"> |
|||
<h2 translate>edge.add</h2> |
|||
<span flex></span> |
|||
<div id="help-container"></div> |
|||
<md-button class="md-icon-button" ng-click="vm.cancel()"> |
|||
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon> |
|||
</md-button> |
|||
</div> |
|||
</md-toolbar> |
|||
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> |
|||
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> |
|||
<md-dialog-content> |
|||
<div class="md-dialog-content"> |
|||
<tb-edge edge="vm.item" is-edit="true" is-create="true" the-form="theForm"></tb-edge> |
|||
</div> |
|||
</md-dialog-content> |
|||
<md-dialog-actions layout="row"> |
|||
<span flex></span> |
|||
<md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> |
|||
{{ 'action.add' | translate }} |
|||
</md-button> |
|||
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> |
|||
</md-dialog-actions> |
|||
</form> |
|||
</md-dialog> |
|||
|
|||
@ -0,0 +1,21 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2019 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<div flex layout="column"> |
|||
<div flex style="text-transform: uppercase;">{{ vm.types.edgeType[vm.item.type].name | translate }}</div> |
|||
<div class="tb-card-description">{{vm.item.additionalInfo.description}}</div> |
|||
</div> |
|||
@ -0,0 +1,49 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2019 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<md-button ng-click="onExportEdge({event: $event})" |
|||
ng-show="!isEdit" |
|||
class="md-raised md-primary">{{ 'edge.export' | translate }}</md-button> |
|||
<md-button ng-click="onDeleteEdge({event: $event})" |
|||
ng-if="'edge' | hasGenericPermission:'delete'" |
|||
ng-show="!isEdit" class="md-raised md-primary">{{ 'edge.delete' | translate }}</md-button> |
|||
|
|||
<div layout="row"> |
|||
<md-button ngclipboard data-clipboard-action="copy" |
|||
ngclipboard-success="onEdgeIdCopied(e)" |
|||
data-clipboard-text="{{edge.id.id}}" ng-show="!isEdit" |
|||
class="md-raised"> |
|||
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon> |
|||
<span translate>edge.copyId</span> |
|||
</md-button> |
|||
</div> |
|||
|
|||
<md-content class="md-padding" layout="column"> |
|||
<fieldset ng-disabled="$root.loading || !isEdit"> |
|||
<md-input-container class="md-block"> |
|||
<label translate>edge.name</label> |
|||
<input required name="name" ng-model="edge.name"> |
|||
<div ng-messages="theForm.name.$error"> |
|||
<div translate ng-message="required">edge.name-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
<md-input-container class="md-block"> |
|||
<label translate>edge.description</label> |
|||
<textarea ng-model="edge.additionalInfo.description" rows="2"></textarea> |
|||
</md-input-container> |
|||
</fieldset> |
|||
</md-content> |
|||
@ -0,0 +1,166 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import addEdgeTemplate from './add-edge.tpl.html'; |
|||
import edgeCard from './edge-card.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export function EdgeCardController(types) { |
|||
|
|||
var vm = this; |
|||
|
|||
vm.types = types; |
|||
} |
|||
|
|||
|
|||
/*@ngInject*/ |
|||
export function EdgeController($rootScope, userService, edgeService, $state, $stateParams, |
|||
$document, $mdDialog, $q, $translate, types, securityTypes, userPermissionsService) { |
|||
|
|||
var edgeActionsList = []; |
|||
|
|||
var edgeGroupActionsList = []; |
|||
|
|||
var vm = this; |
|||
|
|||
vm.types = types; |
|||
|
|||
vm.edgeGridConfig = { |
|||
|
|||
resource: securityTypes.resource.edge, |
|||
|
|||
deleteItemTitleFunc: deleteEdgeTitle, |
|||
deleteItemContentFunc: deleteEdgeText, |
|||
deleteItemsTitleFunc: deleteEdgesTitle, |
|||
deleteItemsActionTitleFunc: deleteEdgesActionTitle, |
|||
deleteItemsContentFunc: deleteEdgesText, |
|||
|
|||
saveItemFunc: saveEdge, |
|||
|
|||
getItemTitleFunc: getEdgeTitle, |
|||
|
|||
itemCardController: 'EdgeCardController', |
|||
itemCardTemplateUrl: edgeCard, |
|||
parentCtl: vm, |
|||
|
|||
actionsList: edgeActionsList, |
|||
groupActionsList: edgeGroupActionsList, |
|||
|
|||
onGridInited: gridInited, |
|||
|
|||
addItemTemplateUrl: addEdgeTemplate, |
|||
|
|||
addItemText: function() { return $translate.instant('edge.add-edge-text') }, |
|||
noItemsText: function() { return $translate.instant('edge.no-edges-text') }, |
|||
itemDetailsText: function() { return $translate.instant('edge.edge-details') } |
|||
}; |
|||
|
|||
if (angular.isDefined($stateParams.items) && $stateParams.items !== null) { |
|||
vm.edgeGridConfig.items = $stateParams.items; |
|||
} |
|||
|
|||
if (angular.isDefined($stateParams.topIndex) && $stateParams.topIndex > 0) { |
|||
vm.edgeGridConfig.topIndex = $stateParams.topIndex; |
|||
} |
|||
|
|||
initController(); |
|||
|
|||
function initController() { |
|||
var fetchEdgesFunction = function (pageLink, edgeType) { |
|||
return edgeService.getEdges(pageLink, true, edgeType); |
|||
}; |
|||
var deleteEdgeFunction = function (edgeId) { |
|||
return edgeService.deleteEdge(edgeId); |
|||
}; |
|||
var refreshEdgesParamsFunction = function() { |
|||
return {"topIndex": vm.topIndex}; |
|||
}; |
|||
|
|||
edgeActionsList.push( |
|||
{ |
|||
onAction: function ($event, item) { |
|||
vm.grid.deleteItem($event, item); |
|||
}, |
|||
name: function() { return $translate.instant('action.delete') }, |
|||
details: function() { return $translate.instant('edge.delete') }, |
|||
icon: "delete", |
|||
isEnabled: function() { |
|||
return userPermissionsService.hasGenericPermission(securityTypes.resource.edge, securityTypes.operation.delete); |
|||
} |
|||
} |
|||
); |
|||
|
|||
edgeGroupActionsList.push( |
|||
{ |
|||
onAction: function ($event) { |
|||
vm.grid.deleteItems($event); |
|||
}, |
|||
name: function() { return $translate.instant('edge.delete-edges') }, |
|||
details: deleteEdgesActionTitle, |
|||
icon: "delete" |
|||
} |
|||
); |
|||
vm.edgeGridConfig.refreshParamsFunc = refreshEdgesParamsFunction; |
|||
vm.edgeGridConfig.fetchItemsFunc = fetchEdgesFunction; |
|||
vm.edgeGridConfig.deleteItemFunc = deleteEdgeFunction; |
|||
|
|||
} |
|||
|
|||
function deleteEdgeTitle(edge) { |
|||
return $translate.instant('edge.delete-edge-title', {edgeName: edge.name}); |
|||
} |
|||
|
|||
function deleteEdgeText() { |
|||
return $translate.instant('edge.delete-edge-text'); |
|||
} |
|||
|
|||
function deleteEdgesTitle(selectedCount) { |
|||
return $translate.instant('edge.delete-edges-title', {count: selectedCount}, 'messageformat'); |
|||
} |
|||
|
|||
function deleteEdgesActionTitle(selectedCount) { |
|||
return $translate.instant('edge.delete-edges-action-title', {count: selectedCount}, 'messageformat'); |
|||
} |
|||
|
|||
function deleteEdgesText () { |
|||
return $translate.instant('edge.delete-edges-text'); |
|||
} |
|||
|
|||
function gridInited(grid) { |
|||
vm.grid = grid; |
|||
} |
|||
|
|||
function getEdgeTitle(edge) { |
|||
return edge ? edge.name : ''; |
|||
} |
|||
|
|||
function saveEdge(edge) { |
|||
var deferred = $q.defer(); |
|||
edgeService.saveEdge(edge).then( |
|||
function success(savedEdge) { |
|||
$rootScope.$broadcast('edgeSaved'); |
|||
deferred.resolve(savedEdge); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
return deferred.promise; |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import edgeFieldsetTemplate from './edge-fieldset.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function EdgeDirective($compile, $templateCache, $translate, $mdDialog, $document, toast, types) { |
|||
var linker = function (scope, element) { |
|||
var template = $templateCache.get(edgeFieldsetTemplate); |
|||
element.html(template); |
|||
|
|||
scope.types = types; |
|||
|
|||
scope.onEdgeIdCopied = function() { |
|||
toast.showSuccess($translate.instant('edge.idCopiedMessage'), 750, angular.element(element).parent().parent(), 'bottom left'); |
|||
}; |
|||
|
|||
$compile(element.contents())(scope); |
|||
|
|||
}; |
|||
return { |
|||
restrict: "E", |
|||
link: linker, |
|||
scope: { |
|||
edge: '=', |
|||
isEdit: '=', |
|||
theForm: '=', |
|||
isCreate: '<', |
|||
onExportEdge: '&', |
|||
onDeleteEdge: '&' |
|||
} |
|||
}; |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import edgesTemplate from './edges.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function EdgeRoutes($stateProvider) { |
|||
|
|||
$stateProvider |
|||
.state('home.edges', { |
|||
url: '/edges', |
|||
params: {'topIndex': 0}, |
|||
module: 'private', |
|||
auth: ['TENANT_ADMIN'], |
|||
views: { |
|||
"content@home": { |
|||
templateUrl: edgesTemplate, |
|||
controllerAs: 'vm', |
|||
controller: 'EdgeController' |
|||
} |
|||
}, |
|||
data: { |
|||
searchEnabled: true, |
|||
pageTitle: 'edge.edges' |
|||
}, |
|||
ncyBreadcrumb: { |
|||
label: '{"icon": "transform", "label": "edge.edges"}' |
|||
} |
|||
}); |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2019 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<tb-grid grid-configuration="vm.edgeGridConfig"> |
|||
<details-buttons tb-help="'edges'" help-container-id="help-container"> |
|||
<div id="help-container"></div> |
|||
</details-buttons> |
|||
<md-tabs ng-class="{'tb-headless': vm.grid.detailsConfig.isDetailsEditMode}" |
|||
id="tabs" md-border-bottom flex class="tb-absolute-fill"> |
|||
<md-tab label="{{ 'edge.details' | translate }}"> |
|||
<tb-edge edge="vm.grid.operatingItem()" |
|||
is-edit="vm.grid.detailsConfig.isDetailsEditMode" |
|||
the-form="vm.grid.detailsForm" |
|||
on-delete-edge="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-edge> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && ('edge' | hasGenericPermission:'readAttributes')" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}"> |
|||
<tb-attribute-table flex |
|||
readonly="!('edge' | hasGenericPermission:'writeAttributes')" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-type="{{vm.types.entityType.edge}}" |
|||
entity-name="vm.grid.operatingItem().name" |
|||
default-attribute-scope="{{vm.types.attributesScope.server.value}}"> |
|||
</tb-attribute-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && ('edge' | hasGenericPermission:'readTelemetry')" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.latest-telemetry' | translate }}"> |
|||
<tb-attribute-table flex |
|||
readonly="!('edge' | hasGenericPermission:'writeTelemetry')" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-type="{{vm.types.entityType.edge}}" |
|||
entity-name="vm.grid.operatingItem().name" |
|||
default-attribute-scope="{{vm.types.latestTelemetry.value}}" |
|||
disable-attribute-scope-selection="true"> |
|||
</tb-attribute-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && ('alarm' | hasGenericPermission:'read')" md-on-select="vm.grid.triggerResize()" label="{{ 'alarm.alarms' | translate }}"> |
|||
<tb-alarm-table flex entity-type="vm.types.entityType.edge" |
|||
entity-id="vm.grid.operatingItem().id.id"> |
|||
</tb-alarm-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'edge.events' | translate }}"> |
|||
<tb-event-table flex entity-type="vm.types.entityType.edge" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
tenant-id="vm.grid.operatingItem().tenantId.id" |
|||
default-event-type="{{vm.types.eventType.error.value}}"> |
|||
</tb-event-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}"> |
|||
<tb-relation-table flex |
|||
readonly="!('edge' | hasGenericPermission:'write')" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-type="{{vm.types.entityType.edge}}"> |
|||
</tb-relation-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && ('auditLog' | hasGenericPermission:'read')" md-on-select="vm.grid.triggerResize()" label="{{ 'audit-log.audit-logs' | translate }}"> |
|||
<tb-audit-log-table flex entity-type="vm.types.entityType.edge" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
audit-log-mode="{{vm.types.auditLogMode.entity}}"> |
|||
</tb-audit-log-table> |
|||
</md-tab> |
|||
</md-tabs> |
|||
</tb-grid> |
|||
@ -0,0 +1,25 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import EdgeRoutes from './edge.routes'; |
|||
import {EdgeController, EdgeCardController} from './edge.controller'; |
|||
import EdgeDirective from './edge.directive'; |
|||
|
|||
export default angular.module('thingsboard.edge', []) |
|||
.config(EdgeRoutes) |
|||
.controller('EdgeController', EdgeController) |
|||
.controller('EdgeCardController', EdgeCardController) |
|||
.directive('tbEdge', EdgeDirective) |
|||
.name; |
|||
Loading…
Reference in new issue