Browse Source

Manage edge dashboards functionality

pull/2818/head
Volodymyr Babak 7 years ago
parent
commit
6be5f9aa4d
  1. 22
      application/src/main/java/org/thingsboard/server/controller/DashboardController.java
  2. 2
      common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java
  3. 39
      common/data/src/main/java/org/thingsboard/server/common/data/ShortEdgeInfo.java
  4. 17
      dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java
  5. 20
      dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java
  6. 60
      ui/src/app/api/dashboard.service.js
  7. 2
      ui/src/app/customer/customer.controller.js
  8. 122
      ui/src/app/dashboard/add-dashboards-to-edge.controller.js
  9. 77
      ui/src/app/dashboard/add-dashboards-to-edge.tpl.html
  10. 21
      ui/src/app/dashboard/dashboard.routes.js
  11. 190
      ui/src/app/dashboard/dashboards.controller.js
  12. 2
      ui/src/app/dashboard/index.js
  13. 29
      ui/src/app/edge/edge.controller.js
  14. 20
      ui/src/app/locale/locale.constant-en_US.json
  15. 8
      ui/src/app/services/menu.service.js

22
application/src/main/java/org/thingsboard/server/controller/DashboardController.java

@ -689,4 +689,26 @@ public class DashboardController extends BaseController {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edge/{edgeId}/dashboards", params = { "limit" }, method = RequestMethod.GET)
@ResponseBody
public TimePageData<DashboardInfo> getEdgeDashboards(
@PathVariable("edgeId") String strEdgeId,
@RequestParam int limit,
@RequestParam(required = false) Long startTime,
@RequestParam(required = false) Long endTime,
@RequestParam(required = false, defaultValue = "false") boolean ascOrder,
@RequestParam(required = false) String offset) throws ThingsboardException {
checkParameter("edgeId", strEdgeId);
try {
TenantId tenantId = getCurrentUser().getTenantId();
EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
checkEdgeId(edgeId, Operation.READ);
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(dashboardService.findDashboardsByTenantIdAndEdgeId(tenantId, edgeId, pageLink).get());
} catch (Exception e) {
throw handleException(e);
}
}
}

2
common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java

@ -62,4 +62,6 @@ public interface DashboardService {
void unassignEdgeDashboards(TenantId tenantId, EdgeId edgeId);
void updateEdgeDashboards(TenantId tenantId, EdgeId edgeId);
ListenableFuture<TimePageData<DashboardInfo>> findDashboardsByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);
}

39
common/data/src/main/java/org/thingsboard/server/common/data/ShortEdgeInfo.java

@ -1,15 +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.
*/
package org.thingsboard.server.common.data;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.thingsboard.server.common.data.id.EdgeId;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ShortEdgeInfo {
@Getter @Setter
private EdgeId edgeId;
@Getter @Setter
private String title;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ShortEdgeInfo that = (ShortEdgeInfo) o;
return edgeId.equals(that.edgeId);
}
@Override
public int hashCode() {
return edgeId.hashCode();
}
}

17
dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java

@ -299,6 +299,23 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
new EdgeDashboardsUpdater(edge).removeEntities(tenantId, edge);
}
@Override
public ListenableFuture<TimePageData<DashboardInfo>> findDashboardsByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {
log.trace("Executing findDashboardsByTenantIdAndEdgeId, tenantId [{}], edgeId [{}], pageLink [{}]", tenantId, edgeId, pageLink);
Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
Validator.validateId(edgeId, "Incorrect customerId " + edgeId);
Validator.validatePageLink(pageLink, "Incorrect page link " + pageLink);
ListenableFuture<List<DashboardInfo>> dashboards = dashboardInfoDao.findDashboardsByTenantIdAndEdgeId(tenantId.getId(), edgeId.getId(), pageLink);
return Futures.transform(dashboards, new Function<List<DashboardInfo>, TimePageData<DashboardInfo>>() {
@Nullable
@Override
public TimePageData<DashboardInfo> apply(@Nullable List<DashboardInfo> dashboards) {
return new TimePageData<>(dashboards, pageLink);
}
});
}
private Dashboard updateAssignedEdge(TenantId tenantId, DashboardId dashboardId, Edge edge) {
Dashboard dashboard = findDashboardById(tenantId, dashboardId);
if (dashboard.updateAssignedEdge(edge)) {

20
dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java

@ -25,6 +25,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.DashboardInfo;
import org.thingsboard.server.common.data.ShortCustomerInfo;
import org.thingsboard.server.common.data.ShortEdgeInfo;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
@ -47,6 +48,8 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final JavaType assignedCustomersType =
objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortCustomerInfo.class);
private static final JavaType assignedEdgesType =
objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortEdgeInfo.class);
@Column(name = ModelConstants.DASHBOARD_TENANT_ID_PROPERTY)
private String tenantId;
@ -60,6 +63,9 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements
@Column(name = ModelConstants.DASHBOARD_ASSIGNED_CUSTOMERS_PROPERTY)
private String assignedCustomers;
@Column(name = ModelConstants.DASHBOARD_ASSIGNED_EDGES_PROPERTY)
private String assignedEdges;
public DashboardInfoEntity() {
super();
}
@ -79,6 +85,13 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements
log.error("Unable to serialize assigned customers to string!", e);
}
}
if (dashboardInfo.getAssignedEdges() != null) {
try {
this.assignedEdges = objectMapper.writeValueAsString(dashboardInfo.getAssignedEdges());
} catch (JsonProcessingException e) {
log.error("Unable to serialize assigned edges to string!", e);
}
}
}
@Override
@ -110,6 +123,13 @@ public class DashboardInfoEntity extends BaseSqlEntity<DashboardInfo> implements
log.warn("Unable to parse assigned customers!", e);
}
}
if (!StringUtils.isEmpty(assignedEdges)) {
try {
dashboardInfo.setAssignedEdges(objectMapper.readValue(assignedEdges, assignedEdgesType));
} catch (IOException e) {
log.warn("Unable to parse assigned edges!", e);
}
}
return dashboardInfo;
}

60
ui/src/app/api/dashboard.service.js

@ -45,7 +45,10 @@ function DashboardService($rootScope, $http, $q, $location, $filter) {
getPublicDashboardLink: getPublicDashboardLink,
updateDashboardEdges: updateDashboardEdges,
addDashboardEdges: addDashboardEdges,
removeDashboardEdges: removeDashboardEdges
removeDashboardEdges: removeDashboardEdges,
getEdgeDashboards: getEdgeDashboards,
assignDashboardToEdge: assignDashboardToEdge,
unassignDashboardFromEdge: unassignDashboardFromEdge
}
return service;
@ -285,6 +288,20 @@ function DashboardService($rootScope, $http, $q, $location, $filter) {
}
dashboard.assignedCustomersText = assignedCustomersTitles.join(', ');
}
dashboard.assignedEdgesIds = [];
if (dashboard.assignedEdges && dashboard.assignedEdges.length) {
// var assignedEdgesTitles = [];
for (var j = 0; j < dashboard.assignedEdges.length; j++) {
var assignedEdge = dashboard.assignedEdges[j];
dashboard.assignedEdgesIds.push(assignedEdge.edgeId.id);
// if (assignedCustomer.public) {
// dashboard.publicCustomerId = assignedCustomer.customerId.id;
// } else {
// assignedCustomersTitles.push(assignedCustomer.title);
// }
}
// dashboard.assignedCustomersText = assignedCustomersTitles.join(', ');
}
return dashboard;
}
@ -292,6 +309,7 @@ function DashboardService($rootScope, $http, $q, $location, $filter) {
delete dashboard.publicCustomerId;
delete dashboard.assignedCustomersText;
delete dashboard.assignedCustomersIds;
delete dashboard.assignedEdgeIds;
return dashboard;
}
@ -327,4 +345,44 @@ function DashboardService($rootScope, $http, $q, $location, $filter) {
});
return deferred.promise;
}
function getEdgeDashboards(edgeId, pageLink, config) {
var deferred = $q.defer();
var url = '/api/edge/' + edgeId + '/dashboards?limit=' + pageLink.limit;
if (angular.isDefined(pageLink.idOffset)) {
url += '&offset=' + pageLink.idOffset;
}
$http.get(url, config).then(function success(response) {
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();
});
return deferred.promise;
}
function assignDashboardToEdge(edgeId, dashboardId) {
var deferred = $q.defer();
var url = '/api/edge/' + edgeId + '/dashboard/' + dashboardId;
$http.post(url, null).then(function success(response) {
deferred.resolve(prepareDashboard(response.data));
}, function fail() {
deferred.reject();
});
return deferred.promise;
}
function unassignDashboardFromEdge(edgeId, dashboardId) {
var deferred = $q.defer();
var url = '/api/edge/' + edgeId + '/dashboard/' + dashboardId;
$http.delete(url).then(function success(response) {
deferred.resolve(prepareDashboard(response.data));
}, function fail() {
deferred.reject();
});
return deferred.promise;
}
}

2
ui/src/app/customer/customer.controller.js

@ -89,7 +89,7 @@ export default function CustomerController(customerService, $state, $stateParams
return $translate.instant('customer.manage-customer-edges')
}
},
icon: "toys"
icon: "wifi_tethering"
},
{
onAction: function ($event, item) {

122
ui/src/app/dashboard/add-dashboards-to-edge.controller.js

@ -0,0 +1,122 @@
/*
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*@ngInject*/
export default function AddDashboardsToEdgeController(dashboardService, $mdDialog, $q, edgeId, dashboards) {
var vm = this;
vm.dashboards = dashboards;
vm.searchText = '';
vm.assign = assign;
vm.cancel = cancel;
vm.hasData = hasData;
vm.noData = noData;
vm.searchDashboardTextUpdated = searchDashboardTextUpdated;
vm.toggleDashboardSelection = toggleDashboardSelection;
vm.theDashboards = {
getItemAtIndex: function (index) {
if (index > vm.dashboards.data.length) {
vm.theDashboards.fetchMoreItems_(index);
return null;
}
var item = vm.dashboards.data[index];
if (item) {
item.indexNumber = index + 1;
}
return item;
},
getLength: function () {
if (vm.dashboards.hasNext) {
return vm.dashboards.data.length + vm.dashboards.nextPageLink.limit;
} else {
return vm.dashboards.data.length;
}
},
fetchMoreItems_: function () {
if (vm.dashboards.hasNext && !vm.dashboards.pending) {
vm.dashboards.pending = true;
dashboardService.getTenantDashboards(vm.dashboards.nextPageLink).then(
function success(dashboards) {
vm.dashboards.data = vm.dashboards.data.concat(dashboards.data);
vm.dashboards.nextPageLink = dashboards.nextPageLink;
vm.dashboards.hasNext = dashboards.hasNext;
if (vm.dashboards.hasNext) {
vm.dashboards.nextPageLink.limit = vm.dashboards.pageSize;
}
vm.dashboards.pending = false;
},
function fail() {
vm.dashboards.hasNext = false;
vm.dashboards.pending = false;
});
}
}
}
function cancel () {
$mdDialog.cancel();
}
function assign () {
var tasks = [];
for (var dashboardId in vm.dashboards.selections) {
tasks.push(dashboardService.assignDashboardToEdge(edgeId, dashboardId));
}
$q.all(tasks).then(function () {
$mdDialog.hide();
});
}
function noData () {
return vm.dashboards.data.length == 0 && !vm.dashboards.hasNext;
}
function hasData () {
return vm.dashboards.data.length > 0;
}
function toggleDashboardSelection ($event, dashboard) {
$event.stopPropagation();
var selected = angular.isDefined(dashboard.selected) && dashboard.selected;
dashboard.selected = !selected;
if (dashboard.selected) {
vm.dashboards.selections[dashboard.id.id] = true;
vm.dashboards.selectedCount++;
} else {
delete vm.dashboards.selections[dashboard.id.id];
vm.dashboards.selectedCount--;
}
}
function searchDashboardTextUpdated () {
vm.dashboards = {
pageSize: vm.dashboards.pageSize,
data: [],
nextPageLink: {
limit: vm.dashboards.pageSize,
textSearch: vm.searchText
},
selections: {},
selectedCount: 0,
hasNext: true,
pending: false
};
}
}

77
ui/src/app/dashboard/add-dashboards-to-edge.tpl.html

@ -0,0 +1,77 @@
<!--
Copyright © 2016-2019 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<md-dialog aria-label="{{ 'dashboard.assign-dashboard-to-edge' | translate }}">
<form name="theForm" ng-submit="vm.assign()">
<md-toolbar>
<div class="md-toolbar-tools">
<h2 translate>dashboard.assign-dashboard-to-edge</h2>
<span flex></span>
<md-button class="md-icon-button" ng-click="vm.cancel()">
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon>
</md-button>
</div>
</md-toolbar>
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear>
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span>
<md-dialog-content>
<div class="md-dialog-content">
<fieldset>
<span translate>dashboard.assign-dashboard-to-edge-text</span>
<md-input-container class="md-block" style='margin-bottom: 0px;'>
<label>&nbsp;</label>
<md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">
search
</md-icon>
<input id="dashboard-search" autofocus ng-model="vm.searchText"
ng-change="vm.searchDashboardTextUpdated()"
placeholder="{{ 'common.enter-search' | translate }}"/>
</md-input-container>
<div style='min-height: 150px;'>
<span translate layout-align="center center"
style="text-transform: uppercase; display: flex; height: 150px;"
class="md-subhead"
ng-show="vm.noData()">dashboard.no-dashboards-text</span>
<md-virtual-repeat-container ng-show="vm.hasData()"
tb-scope-element="repeatContainer" md-top-index="vm.topIndex" flex
style='min-height: 150px; width: 100%;'>
<md-list>
<md-list-item md-virtual-repeat="dashboard in vm.theDashboards" md-on-demand
class="repeated-item" flex>
<md-checkbox ng-click="vm.toggleDashboardSelection($event, dashboard)"
aria-label="{{ 'item.selected' | translate }}"
ng-checked="dashboard.selected"></md-checkbox>
<span> {{ dashboard.title }} </span>
</md-list-item>
</md-list>
</md-virtual-repeat-container>
</div>
</fieldset>
</div>
</md-dialog-content>
<md-dialog-actions layout="row">
<span flex></span>
<md-button ng-disabled="$root.loading || vm.dashboards.selectedCount == 0" type="submit"
class="md-raised md-primary">
{{ 'action.assign' | translate }}
</md-button>
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' |
translate }}
</md-button>
</md-dialog-actions>
</form>
</md-dialog>

21
ui/src/app/dashboard/dashboard.routes.js

@ -124,4 +124,25 @@ export default function DashboardRoutes($stateProvider) {
label: '{"icon": "dashboard", "label": "customer.dashboard"}'
}
})
.state('home.edges.dashboards', {
url: '/:edgeId/dashboards',
params: {'topIndex': 0},
module: 'private',
auth: ['TENANT_ADMIN'],
views: {
"content@home": {
templateUrl: dashboardsTemplate,
controllerAs: 'vm',
controller: 'DashboardsController'
}
},
data: {
dashboardsType: 'edge',
searchEnabled: true,
pageTitle: 'edge.dashboards'
},
ncyBreadcrumb: {
label: '{"icon": "dashboard", "label": "{{ vm.edgeDashboardsTitle }}", "translate": "false"}'
}
})
}

190
ui/src/app/dashboard/dashboards.controller.js

@ -21,6 +21,7 @@ import addDashboardsToCustomerTemplate from './add-dashboards-to-customer.tpl.ht
import makeDashboardPublicDialogTemplate from './make-dashboard-public-dialog.tpl.html';
import manageAssignedCustomersTemplate from './manage-assigned-customers.tpl.html';
import manageAssignedEdgesTemplate from './manage-assigned-edges.tpl.html';
import addDashboardsToEdgeTemplate from './add-dashboards-to-edge.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
@ -60,6 +61,7 @@ export function DashboardsController(userService, dashboardService, customerServ
$state, $stateParams, $mdDialog, $document, $q, $translate) {
var customerId = $stateParams.customerId;
var edgeId = $stateParams.edgeId;
var dashboardActionsList = [
{
@ -215,7 +217,7 @@ export function DashboardsController(userService, dashboardService, customerServ
},
name: function() { return $translate.instant('action.assign') },
details: function() { return $translate.instant('dashboard.manage-assigned-edges') },
icon: "assignment",
icon: "wifi_tethering",
isEnabled: function(dashboard) {
return dashboard;
}
@ -255,6 +257,32 @@ export function DashboardsController(userService, dashboardService, customerServ
}
);
dashboardGroupActionsList.push(
{
onAction: function ($event, items) {
assignDashboardsToEdges($event, items);
},
name: function() { return $translate.instant('dashboard.assign-dashboards') },
details: function(selectedCount) {
return $translate.instant('dashboard.assign-dashboards-to-edge-text', {count: selectedCount}, "messageformat");
},
icon: "wifi_tethering"
}
);
dashboardGroupActionsList.push(
{
onAction: function ($event, items) {
unassignDashboardsFromEdges($event, items);
},
name: function() { return $translate.instant('dashboard.unassign-dashboards') },
details: function(selectedCount) {
return $translate.instant('dashboard.unassign-dashboards-from-edge-action-text', {count: selectedCount}, "messageformat");
},
icon: "portable_wifi_off"
}
);
dashboardGroupActionsList.push(
{
onAction: function ($event, items) {
@ -386,6 +414,60 @@ export function DashboardsController(userService, dashboardService, customerServ
} else if (vm.dashboardsScope === 'customer_user') {
vm.dashboardGridConfig.addItemAction = {};
}
} else if (vm.dashboardsScope === 'edge') {
fetchDashboardsFunction = function (pageLink) {
return dashboardService.getEdgeDashboards(edgeId, pageLink);
};
deleteDashboardFunction = function (dashboardId) {
return dashboardService.unassignDashboardFromEdge(edgeId, dashboardId);
};
refreshDashboardsParamsFunction = function () {
return {"edgeId": edgeId, "topIndex": vm.topIndex};
};
dashboardActionsList.push(
{
onAction: function ($event, item) {
exportDashboard($event, item);
},
name: function() { $translate.instant('action.export') },
details: function() { return $translate.instant('dashboard.export') },
icon: "file_download"
}
);
dashboardActionsList.push(
{
onAction: function ($event, item) {
unassignFromEdge($event, item, edgeId);
},
name: function() { return $translate.instant('action.unassign') },
details: function() { return $translate.instant('dashboard.unassign-from-edge') },
icon: "assignment_return"
}
);
dashboardGroupActionsList.push(
{
onAction: function ($event, items) {
unassignDashboardsFromEdge($event, items, edgeId);
},
name: function() { return $translate.instant('dashboard.unassign-dashboards') },
details: function(selectedCount) {
return $translate.instant('dashboard.unassign-dashboards-from-edge-action-title', {count: selectedCount}, "messageformat");
},
icon: "assignment_return"
}
);
vm.dashboardGridConfig.addItemAction = {
onAction: function ($event) {
addDashboardsToEdge($event);
},
name: function() { return $translate.instant('dashboard.assign-dashboards') },
details: function() { return $translate.instant('dashboard.assign-new-dashboard') },
icon: "add"
};
}
vm.dashboardGridConfig.refreshParamsFunc = refreshDashboardsParamsFunction;
@ -628,21 +710,40 @@ export function DashboardsController(userService, dashboardService, customerServ
showManageAssignedEdgesDialog($event, [dashboard.id.id], 'manage', dashboard.assignedEdgesIds);
}
// function assignDashboardsToEdges($event, items) {
// var dashboardIds = [];
// for (var id in items.selections) {
// dashboardIds.push(id);
// }
// showManageAssignedEdgesDialog($event, dashboardIds, 'assign');
// }
//
// function unassignDashboardsFromEdges($event, items) {
// var dashboardIds = [];
// for (var id in items.selections) {
// dashboardIds.push(id);
// }
// showManageAssignedEdgesDialog($event, dashboardIds, 'unassign');
// }
function assignDashboardsToEdges($event, items) {
var dashboardIds = [];
for (var id in items.selections) {
dashboardIds.push(id);
}
showManageAssignedEdgesDialog($event, dashboardIds, 'assign');
}
function unassignDashboardsFromEdges($event, items) {
var dashboardIds = [];
for (var id in items.selections) {
dashboardIds.push(id);
}
showManageAssignedEdgesDialog($event, dashboardIds, 'unassign');
}
function unassignDashboardsFromEdge($event, items, edgeId) {
var confirm = $mdDialog.confirm()
.targetEvent($event)
.title($translate.instant('dashboard.unassign-dashboards-title', {count: items.selectedCount}, 'messageformat'))
.htmlContent($translate.instant('dashboard.unassign-dashboards-from-edge-text'))
.ariaLabel($translate.instant('dashboard.unassign-dashboards'))
.cancel($translate.instant('action.no'))
.ok($translate.instant('action.yes'));
$mdDialog.show(confirm).then(function () {
var tasks = [];
for (var id in items.selections) {
tasks.push(dashboardService.unassignDashboardFromEdge(edgeId, id));
}
$q.all(tasks).then(function () {
vm.grid.refreshList();
});
});
}
function showManageAssignedEdgesDialog($event, dashboardIds, actionType, assignedEdges) {
if ($event) {
@ -661,4 +762,61 @@ export function DashboardsController(userService, dashboardService, customerServ
}, function () {
});
}
function addDashboardsToEdge($event) {
if ($event) {
$event.stopPropagation();
}
var pageSize = 10;
dashboardService.getTenantDashboards({limit: pageSize, textSearch: ''}).then(
function success(_dashboards) {
var dashboards = {
pageSize: pageSize,
data: _dashboards.data,
nextPageLink: _dashboards.nextPageLink,
selections: {},
selectedCount: 0,
hasNext: _dashboards.hasNext,
pending: false
};
if (dashboards.hasNext) {
dashboards.nextPageLink.limit = pageSize;
}
$mdDialog.show({
controller: 'AddDashboardsToEdgeController',
controllerAs: 'vm',
templateUrl: addDashboardsToEdgeTemplate,
locals: {edgeId: edgeId, dashboards: dashboards},
parent: angular.element($document[0].body),
fullscreen: true,
targetEvent: $event
}).then(function () {
vm.grid.refreshList();
}, function () {
});
},
function fail() {
});
}
function unassignFromEdge($event, dashboard, edgeId) {
if ($event) {
$event.stopPropagation();
}
var title = $translate.instant('dashboard.unassign-dashboard-title', {dashboardTitle: dashboard.title});
var content = $translate.instant('dashboard.unassign-dashboard-from-edge-text');
var label = $translate.instant('dashboard.unassign-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.unassignDashboardFromEdge(edgeId, dashboard.id.id).then(function success() {
vm.grid.refreshList();
});
});
}
}

2
ui/src/app/dashboard/index.js

@ -47,6 +47,7 @@ import AddWidgetController from './add-widget.controller';
import DashboardDirective from './dashboard.directive';
import EditWidgetDirective from './edit-widget.directive';
import DashboardToolbar from './dashboard-toolbar.directive';
import AddDashboardsToEdgeController from './add-dashboards-to-edge.controller';
export default angular.module('thingsboard.dashboard', [
uiRouter,
@ -79,6 +80,7 @@ export default angular.module('thingsboard.dashboard', [
.controller('ManageAssignedCustomersController', ManageAssignedCustomersController)
.controller('ManageAssignedEdgesController', ManageAssignedEdgesController)
.controller('AddWidgetController', AddWidgetController)
.controller('AddDashboardsToEdgeController', AddDashboardsToEdgeController)
.directive('tbDashboardDetails', DashboardDirective)
.directive('tbEditWidget', EditWidgetDirective)
.directive('tbDashboardToolbar', DashboardToolbar)

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

@ -216,6 +216,19 @@ export function EdgeController($rootScope, userService, edgeService, customerSer
}
});
edgeActionsList.push(
{
onAction: function ($event, item) {
openEdgeDashboards($event, item);
},
name: function() { return $translate.instant('dashboard.dashboards') },
details: function() {
return $translate.instant('edge.manage-edge-dashboards');
},
icon: "dashboard"
}
);
edgeActionsList.push(
{
onAction: function ($event, item) {
@ -240,6 +253,8 @@ export function EdgeController($rootScope, userService, edgeService, customerSer
}
);
edgeGroupActionsList.push(
{
onAction: function ($event) {
@ -531,4 +546,18 @@ export function EdgeController($rootScope, userService, edgeService, customerSer
});
});
}
function openEdgeDashboards($event, edge) {
if ($event) {
$event.stopPropagation();
}
$state.go('home.edges.dashboards', {edgeId: edge.id.id});
}
// function openEdgeRuleChains($event, edge) {
// if ($event) {
// $event.stopPropagation();
// }
// $state.go('home.edges.rule-chains', {edgeId: edge.id.id});
// }
}

20
ui/src/app/locale/locale.constant-en_US.json

@ -569,7 +569,20 @@
"hide-details": "Hide details",
"select-state": "Select target state",
"state-controller": "State controller",
"manage-assigned-edges": "Manage assigned edges"
"manage-assigned-edges": "Manage assigned edges",
"unassign-dashboard-from-edge-text": "After the confirmation the dashboard will be unassigned and won't be accessible by the edge.",
"assigned-edges": "Assigned edges",
"unassign-from-edge": "Unassign from edge",
"unassign-dashboards-from-edge-action-title": "Unassign { count, plural, 1 {1 dashboard} other {# dashboards} } from edge",
"unassign-dashboards-from-edge-text": "After the confirmation all selected dashboards will be unassigned and won't be accessible by the edge.",
"assign-dashboard-to-edge": "Assign Dashboard(s) To Edge",
"assign-dashboard-to-edge-text": "Please select the dashboards to assign to the edge",
"assign-dashboards-to-edge-text": "Assign { count, plural, 1 {1 dashboard} other {# dashboards} } to edges",
"unassign-dashboards-from-edge-action-text": "Unassign { count, plural, 1 {1 dashboard} other {# dashboards} } from edges",
"assign-to-edges": "Assign Dashboard(s) To Edges",
"assign-to-edges-text": "Please select the edges to assign the dashboard(s)",
"unassign-from-edges": "Unassign Dashboard(s) From Edges",
"unassign-from-edges-text": "Please select the edges to unassign from the dashboard(s)"
},
"datakey": {
"settings": "Settings",
@ -759,7 +772,10 @@
"make-private-edge-text": "After the confirmation the edge and all its data will be made private and won't be accessible by others.",
"import": "Import edge",
"label": "Label",
"assign-new-edge": "Assign new edge"
"assign-new-edge": "Assign new edge",
"manage-edge-dashboards": "Manage edge dashboards",
"unassign-from-edge": "Unassign from edge",
"dashboards": "Edge Dashboards"
},
"error": {
"unable-to-connect": "Unable to connect to the server! Please check your internet connection.",

8
ui/src/app/services/menu.service.js

@ -188,7 +188,7 @@ function Menu(userService, $state, $rootScope) {
name: 'edge.edges',
type: 'link',
state: 'home.edges',
icon: 'toys'
icon: 'router'
},
{
name: 'widget.widget-library',
@ -265,7 +265,7 @@ function Menu(userService, $state, $rootScope) {
places: [
{
name: 'edge.edges',
icon: 'toys',
icon: 'router',
state: 'home.edges'
}
]
@ -326,7 +326,7 @@ function Menu(userService, $state, $rootScope) {
name: 'edge.edges',
type: 'link',
state: 'home.edges',
icon: 'toys'
icon: 'router'
},
{
name: 'dashboard.dashboards',
@ -371,7 +371,7 @@ function Menu(userService, $state, $rootScope) {
places: [
{
name: 'edge.edges',
icon: 'toys',
icon: 'router',
state: 'home.edges'
}
]

Loading…
Cancel
Save