Commit 06a0941dbea59cb975f6f62215e34fd38eb9be07

Authored by Volodymyr Babak
1 parent 5bf9528e

Entity view misc fixes

... ... @@ -19,16 +19,22 @@ import com.google.common.util.concurrent.ListenableFuture;
19 19 import org.springframework.http.HttpStatus;
20 20 import org.springframework.security.access.prepost.PreAuthorize;
21 21 import org.springframework.web.bind.annotation.*;
  22 +import org.thingsboard.server.common.data.Customer;
  23 +import org.thingsboard.server.common.data.Device;
22 24 import org.thingsboard.server.common.data.EntitySubtype;
23 25 import org.thingsboard.server.common.data.EntityType;
24 26 import org.thingsboard.server.common.data.EntityView;
25 27 import org.thingsboard.server.common.data.audit.ActionType;
26 28 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
27 29 import org.thingsboard.server.common.data.exception.ThingsboardException;
  30 +import org.thingsboard.server.common.data.id.CustomerId;
  31 +import org.thingsboard.server.common.data.id.DeviceId;
28 32 import org.thingsboard.server.common.data.id.EntityViewId;
29 33 import org.thingsboard.server.common.data.id.TenantId;
30 34 import org.thingsboard.server.common.data.page.TextPageData;
31 35 import org.thingsboard.server.common.data.page.TextPageLink;
  36 +import org.thingsboard.server.dao.exception.IncorrectParameterException;
  37 +import org.thingsboard.server.dao.model.ModelConstants;
32 38 import org.thingsboard.server.service.security.model.SecurityUser;
33 39
34 40 import java.util.ArrayList;
... ... @@ -101,6 +107,84 @@ public class EntityViewController extends BaseController {
101 107 }
102 108
103 109 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  110 + @RequestMapping(value = "/customer/{customerId}/entityView/{entityViewId}", method = RequestMethod.POST)
  111 + @ResponseBody
  112 + public EntityView assignEntityViewToCustomer(@PathVariable("customerId") String strCustomerId,
  113 + @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
  114 + checkParameter("customerId", strCustomerId);
  115 + checkParameter(ENTITY_VIEW_ID, strEntityViewId);
  116 + try {
  117 + CustomerId customerId = new CustomerId(toUUID(strCustomerId));
  118 + Customer customer = checkCustomerId(customerId);
  119 +
  120 + EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
  121 + checkEntityViewId(entityViewId);
  122 +
  123 + EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(entityViewId, customerId));
  124 +
  125 + logEntityAction(entityViewId, savedEntityView,
  126 + savedEntityView.getCustomerId(),
  127 + ActionType.ASSIGNED_TO_CUSTOMER, null, strEntityViewId, strCustomerId, customer.getName());
  128 +
  129 + return savedEntityView;
  130 + } catch (Exception e) {
  131 + logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,
  132 + null,
  133 + ActionType.ASSIGNED_TO_CUSTOMER, e, strEntityViewId, strCustomerId);
  134 + throw handleException(e);
  135 + }
  136 + }
  137 +
  138 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  139 + @RequestMapping(value = "/customer/entityView/{entityViewId}", method = RequestMethod.DELETE)
  140 + @ResponseBody
  141 + public EntityView unassignEntityViewFromCustomer(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
  142 + checkParameter(ENTITY_VIEW_ID, strEntityViewId);
  143 + try {
  144 + EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
  145 + EntityView entityView = checkEntityViewId(entityViewId);
  146 + if (entityView.getCustomerId() == null || entityView.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
  147 + throw new IncorrectParameterException("Entity View isn't assigned to any customer!");
  148 + }
  149 + Customer customer = checkCustomerId(entityView.getCustomerId());
  150 +
  151 + EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(entityViewId));
  152 +
  153 + logEntityAction(entityViewId, entityView,
  154 + entityView.getCustomerId(),
  155 + ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEntityViewId, customer.getId().toString(), customer.getName());
  156 +
  157 + return savedEntityView;
  158 + } catch (Exception e) {
  159 + logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,
  160 + null,
  161 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strEntityViewId);
  162 + throw handleException(e);
  163 + }
  164 + }
  165 +
  166 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
  167 + @RequestMapping(value = "/customer/{customerId}/entityViews", params = {"limit"}, method = RequestMethod.GET)
  168 + @ResponseBody
  169 + public TextPageData<EntityView> getCustomerEntityViews(
  170 + @PathVariable("customerId") String strCustomerId,
  171 + @RequestParam int limit,
  172 + @RequestParam(required = false) String textSearch,
  173 + @RequestParam(required = false) String idOffset,
  174 + @RequestParam(required = false) String textOffset) throws ThingsboardException {
  175 + checkParameter("customerId", strCustomerId);
  176 + try {
  177 + TenantId tenantId = getCurrentUser().getTenantId();
  178 + CustomerId customerId = new CustomerId(toUUID(strCustomerId));
  179 + checkCustomerId(customerId);
  180 + TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
  181 + return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
  182 + } catch (Exception e) {
  183 + throw handleException(e);
  184 + }
  185 + }
  186 +
  187 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
104 188 @RequestMapping(value = "/tenant/entityViews", params = {"limit"}, method = RequestMethod.GET)
105 189 @ResponseBody
106 190 public TextPageData<EntityView> getTenantEntityViews(
... ...
... ... @@ -52,9 +52,33 @@
52 52 <div translate ng-message="required">entity-view.name-required</div>
53 53 </div>
54 54 </md-input-container>
  55 + <tb-entity-select flex ng-disabled="!isEdit"
  56 + the-form="theForm"
  57 + tb-required="true"
  58 + allowed-entity-types="allowedEntityTypes"
  59 + ng-model="entityView.entityId">
  60 + </tb-entity-select>
55 61 <md-input-container class="md-block">
56 62 <label translate>entity-view.description</label>
57 63 <textarea ng-model="entityView.additionalInfo.description" rows="2"></textarea>
58 64 </md-input-container>
  65 + <section layout="row" layout-align="start start">
  66 + <mdp-date-picker ng-model="startTs"
  67 + mdp-max-date="maxStartTs"
  68 + mdp-placeholder="{{ 'entity-view.start-ts' | translate }}"></mdp-date-picker>
  69 + <mdp-time-picker ng-model="startTs"
  70 + mdp-max-date="maxStartTs"
  71 + mdp-placeholder="{{ 'entity-view.start-ts' | translate }}"
  72 + mdp-auto-switch="true"></mdp-time-picker>
  73 + </section>
  74 + <section layout="row" layout-align="start start">
  75 + <mdp-date-picker ng-model="endTs"
  76 + mdp-min-date="minEndTs"
  77 + mdp-placeholder="{{ 'entity-view.end-ts' | translate }}"></mdp-date-picker>
  78 + <mdp-time-picker ng-model="endTs"
  79 + mdp-min-date="minEndTs"
  80 + mdp-placeholder="{{ 'entity-view.end-ts' | translate }}"
  81 + mdp-auto-switch="true"></mdp-time-picker>
  82 + </section>
59 83 </fieldset>
60 84 </md-content>
... ...
... ... @@ -20,7 +20,7 @@ import entityViewFieldsetTemplate from './entity-view-fieldset.tpl.html';
20 20 /* eslint-enable import/no-unresolved, import/default */
21 21
22 22 /*@ngInject*/
23   -export default function EntityViewDirective($compile, $templateCache, toast, $translate, types, clipboardService, entityViewService, customerService) {
  23 +export default function EntityViewDirective($compile, $templateCache, $filter, toast, $translate, types, clipboardService, entityViewService, customerService) {
24 24 var linker = function (scope, element) {
25 25 var template = $templateCache.get(entityViewFieldsetTemplate);
26 26 element.html(template);
... ... @@ -30,6 +30,8 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr
30 30 scope.isPublic = false;
31 31 scope.assignedCustomer = null;
32 32
  33 + scope.allowedEntityTypes = [types.entityType.device, types.entityType.asset];
  34 +
33 35 scope.$watch('entityView', function(newVal) {
34 36 if (newVal) {
35 37 if (scope.entityView.customerId && scope.entityView.customerId.id !== types.id.nullUid) {
... ... @@ -45,9 +47,41 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr
45 47 scope.isPublic = false;
46 48 scope.assignedCustomer = null;
47 49 }
  50 + scope.startTs = $filter('date')(scope.entityView.endTs, 'yyyy-MM-dd HH:mm:ss');
  51 + scope.endTs = $filter('date')(scope.entityView.startTs, 'yyyy-MM-dd HH:mm:ss');
  52 + }
  53 + });
  54 +
  55 +
  56 + scope.$watch('startTs', function (newDate) {
  57 + if (newDate) {
  58 + if (newDate.getTime() > scope.maxStartTs) {
  59 + scope.startTs = angular.copy(scope.maxStartTs);
  60 + }
  61 + updateMinMaxDates();
  62 + }
  63 + });
  64 +
  65 + scope.$watch('endTs', function (newDate) {
  66 + if (newDate) {
  67 + if (newDate.getTime() < scope.minEndTs) {
  68 + scope.endTs = angular.copy(scope.minEndTs);
  69 + }
  70 + updateMinMaxDates();
48 71 }
49 72 });
50 73
  74 + function updateMinMaxDates() {
  75 + if (scope.endTs) {
  76 + scope.maxStartTs = angular.copy(new Date(scope.endTs.getTime() - 1000));
  77 + scope.entityView.endTs = $filter('date')(scope.endTs, 'yyyy-MM-dd HH:mm:ss');
  78 + }
  79 + if (scope.startTs) {
  80 + scope.minEndTs = angular.copy(new Date(scope.startTs.getTime() + 1000));
  81 + scope.entityView.startTs = $filter('date')(scope.startTs, 'yyyy-MM-dd HH:mm:ss');
  82 + }
  83 + }
  84 +
51 85 scope.onEntityViewIdCopied = function() {
52 86 toast.showSuccess($translate.instant('entity-view.idCopiedMessage'), 750, angular.element(element).parent().parent(), 'bottom left');
53 87 };
... ...
... ... @@ -38,7 +38,7 @@ export default function EntityViewRoutes($stateProvider, types) {
38 38 entityViewsType: 'tenant',
39 39 searchEnabled: true,
40 40 searchByEntitySubtype: true,
41   - searchEntityType: types.entityType.entityview,
  41 + searchEntityType: types.entityType.entityView,
42 42 pageTitle: 'entity-view.entity-views'
43 43 },
44 44 ncyBreadcrumb: {
... ... @@ -61,7 +61,7 @@ export default function EntityViewRoutes($stateProvider, types) {
61 61 entityViewsType: 'customer',
62 62 searchEnabled: true,
63 63 searchByEntitySubtype: true,
64   - searchEntityType: types.entityType.entityview,
  64 + searchEntityType: types.entityType.entityView,
65 65 pageTitle: 'customer.entity-views'
66 66 },
67 67 ncyBreadcrumb: {
... ...
... ... @@ -822,7 +822,9 @@
822 822 "unable-entity-view-device-alias-title": "Unable to delete entity view alias",
823 823 "unable-entity-view-device-alias-text": "Device alias '{{entityViewAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}",
824 824 "select-entity-view": "Select entity view",
825   - "make-public": "Make entity view public"
  825 + "make-public": "Make entity view public",
  826 + "start-ts": "Start ts",
  827 + "end-ts": "End ts"
826 828 },
827 829 "event": {
828 830 "event-type": "Event type",
... ...