thingsboard-memoizeit

Entity view misc fixes

9/10/2018 8:37:46 AM

Details

diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
index 227bed0..b5adc32 100644
--- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
@@ -19,16 +19,22 @@ import com.google.common.util.concurrent.ListenableFuture;
 import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
+import org.thingsboard.server.common.data.Customer;
+import org.thingsboard.server.common.data.Device;
 import org.thingsboard.server.common.data.EntitySubtype;
 import org.thingsboard.server.common.data.EntityType;
 import org.thingsboard.server.common.data.EntityView;
 import org.thingsboard.server.common.data.audit.ActionType;
 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
 import org.thingsboard.server.common.data.exception.ThingsboardException;
+import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.id.DeviceId;
 import org.thingsboard.server.common.data.id.EntityViewId;
 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.exception.IncorrectParameterException;
+import org.thingsboard.server.dao.model.ModelConstants;
 import org.thingsboard.server.service.security.model.SecurityUser;
 
 import java.util.ArrayList;
@@ -101,6 +107,84 @@ public class EntityViewController extends BaseController {
     }
 
     @PreAuthorize("hasAuthority('TENANT_ADMIN')")
+    @RequestMapping(value = "/customer/{customerId}/entityView/{entityViewId}", method = RequestMethod.POST)
+    @ResponseBody
+    public EntityView assignEntityViewToCustomer(@PathVariable("customerId") String strCustomerId,
+                                             @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
+        checkParameter("customerId", strCustomerId);
+        checkParameter(ENTITY_VIEW_ID, strEntityViewId);
+        try {
+            CustomerId customerId = new CustomerId(toUUID(strCustomerId));
+            Customer customer = checkCustomerId(customerId);
+
+            EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
+            checkEntityViewId(entityViewId);
+
+            EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(entityViewId, customerId));
+
+            logEntityAction(entityViewId, savedEntityView,
+                    savedEntityView.getCustomerId(),
+                    ActionType.ASSIGNED_TO_CUSTOMER, null, strEntityViewId, strCustomerId, customer.getName());
+
+            return savedEntityView;
+        } catch (Exception e) {
+            logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,
+                    null,
+                    ActionType.ASSIGNED_TO_CUSTOMER, e, strEntityViewId, strCustomerId);
+            throw handleException(e);
+        }
+    }
+
+    @PreAuthorize("hasAuthority('TENANT_ADMIN')")
+    @RequestMapping(value = "/customer/entityView/{entityViewId}", method = RequestMethod.DELETE)
+    @ResponseBody
+    public EntityView unassignEntityViewFromCustomer(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
+        checkParameter(ENTITY_VIEW_ID, strEntityViewId);
+        try {
+            EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
+            EntityView entityView = checkEntityViewId(entityViewId);
+            if (entityView.getCustomerId() == null || entityView.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
+                throw new IncorrectParameterException("Entity View isn't assigned to any customer!");
+            }
+            Customer customer = checkCustomerId(entityView.getCustomerId());
+
+            EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(entityViewId));
+
+            logEntityAction(entityViewId, entityView,
+                    entityView.getCustomerId(),
+                    ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEntityViewId, customer.getId().toString(), customer.getName());
+
+            return savedEntityView;
+        } catch (Exception e) {
+            logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,
+                    null,
+                    ActionType.UNASSIGNED_FROM_CUSTOMER, e, strEntityViewId);
+            throw handleException(e);
+        }
+    }
+
+    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
+    @RequestMapping(value = "/customer/{customerId}/entityViews", params = {"limit"}, method = RequestMethod.GET)
+    @ResponseBody
+    public TextPageData<EntityView> getCustomerEntityViews(
+            @PathVariable("customerId") String strCustomerId,
+            @RequestParam int limit,
+            @RequestParam(required = false) String textSearch,
+            @RequestParam(required = false) String idOffset,
+            @RequestParam(required = false) String textOffset) throws ThingsboardException {
+        checkParameter("customerId", strCustomerId);
+        try {
+            TenantId tenantId = getCurrentUser().getTenantId();
+            CustomerId customerId = new CustomerId(toUUID(strCustomerId));
+            checkCustomerId(customerId);
+            TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
+            return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
+        } catch (Exception e) {
+            throw handleException(e);
+        }
+    }
+
+    @PreAuthorize("hasAuthority('TENANT_ADMIN')")
     @RequestMapping(value = "/tenant/entityViews", params = {"limit"}, method = RequestMethod.GET)
     @ResponseBody
     public TextPageData<EntityView> getTenantEntityViews(
diff --git a/ui/src/app/entity-view/entity-view.directive.js b/ui/src/app/entity-view/entity-view.directive.js
index 5a3d876..b07d437 100644
--- a/ui/src/app/entity-view/entity-view.directive.js
+++ b/ui/src/app/entity-view/entity-view.directive.js
@@ -20,7 +20,7 @@ import entityViewFieldsetTemplate from './entity-view-fieldset.tpl.html';
 /* eslint-enable import/no-unresolved, import/default */
 
 /*@ngInject*/
-export default function EntityViewDirective($compile, $templateCache, toast, $translate, types, clipboardService, entityViewService, customerService) {
+export default function EntityViewDirective($compile, $templateCache, $filter, toast, $translate, types, clipboardService, entityViewService, customerService) {
     var linker = function (scope, element) {
         var template = $templateCache.get(entityViewFieldsetTemplate);
         element.html(template);
@@ -30,6 +30,8 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr
         scope.isPublic = false;
         scope.assignedCustomer = null;
 
+        scope.allowedEntityTypes = [types.entityType.device, types.entityType.asset];
+
         scope.$watch('entityView', function(newVal) {
             if (newVal) {
                 if (scope.entityView.customerId && scope.entityView.customerId.id !== types.id.nullUid) {
@@ -45,9 +47,41 @@ export default function EntityViewDirective($compile, $templateCache, toast, $tr
                     scope.isPublic = false;
                     scope.assignedCustomer = null;
                 }
+                scope.startTs = $filter('date')(scope.entityView.endTs, 'yyyy-MM-dd HH:mm:ss');
+                scope.endTs = $filter('date')(scope.entityView.startTs, 'yyyy-MM-dd HH:mm:ss');
+            }
+        });
+
+
+        scope.$watch('startTs', function (newDate) {
+            if (newDate) {
+                if (newDate.getTime() > scope.maxStartTs) {
+                    scope.startTs = angular.copy(scope.maxStartTs);
+                }
+                updateMinMaxDates();
+            }
+        });
+
+        scope.$watch('endTs', function (newDate) {
+            if (newDate) {
+                if (newDate.getTime() < scope.minEndTs) {
+                    scope.endTs = angular.copy(scope.minEndTs);
+                }
+                updateMinMaxDates();
             }
         });
 
+        function updateMinMaxDates() {
+            if (scope.endTs) {
+                scope.maxStartTs = angular.copy(new Date(scope.endTs.getTime() - 1000));
+                scope.entityView.endTs = $filter('date')(scope.endTs, 'yyyy-MM-dd HH:mm:ss');
+            }
+            if (scope.startTs) {
+                scope.minEndTs = angular.copy(new Date(scope.startTs.getTime() + 1000));
+                scope.entityView.startTs = $filter('date')(scope.startTs, 'yyyy-MM-dd HH:mm:ss');
+            }
+        }
+
         scope.onEntityViewIdCopied = function() {
             toast.showSuccess($translate.instant('entity-view.idCopiedMessage'), 750, angular.element(element).parent().parent(), 'bottom left');
         };
diff --git a/ui/src/app/entity-view/entity-view.routes.js b/ui/src/app/entity-view/entity-view.routes.js
index 481dfc8..c14d430 100644
--- a/ui/src/app/entity-view/entity-view.routes.js
+++ b/ui/src/app/entity-view/entity-view.routes.js
@@ -38,7 +38,7 @@ export default function EntityViewRoutes($stateProvider, types) {
                 entityViewsType: 'tenant',
                 searchEnabled: true,
                 searchByEntitySubtype: true,
-                searchEntityType: types.entityType.entityview,
+                searchEntityType: types.entityType.entityView,
                 pageTitle: 'entity-view.entity-views'
             },
             ncyBreadcrumb: {
@@ -61,7 +61,7 @@ export default function EntityViewRoutes($stateProvider, types) {
                 entityViewsType: 'customer',
                 searchEnabled: true,
                 searchByEntitySubtype: true,
-                searchEntityType: types.entityType.entityview,
+                searchEntityType: types.entityType.entityView,
                 pageTitle: 'customer.entity-views'
             },
             ncyBreadcrumb: {
diff --git a/ui/src/app/entity-view/entity-view-fieldset.tpl.html b/ui/src/app/entity-view/entity-view-fieldset.tpl.html
index cb46f3d..c73b0a2 100644
--- a/ui/src/app/entity-view/entity-view-fieldset.tpl.html
+++ b/ui/src/app/entity-view/entity-view-fieldset.tpl.html
@@ -52,9 +52,33 @@
 	      		<div translate ng-message="required">entity-view.name-required</div>
 	    	</div>				
 		</md-input-container>
+        <tb-entity-select flex ng-disabled="!isEdit"
+                          the-form="theForm"
+                          tb-required="true"
+                          allowed-entity-types="allowedEntityTypes"
+                          ng-model="entityView.entityId">
+        </tb-entity-select>
         <md-input-container class="md-block">
             <label translate>entity-view.description</label>
             <textarea ng-model="entityView.additionalInfo.description" rows="2"></textarea>
         </md-input-container>
+        <section layout="row" layout-align="start start">
+            <mdp-date-picker ng-model="startTs"
+                             mdp-max-date="maxStartTs"
+                             mdp-placeholder="{{ 'entity-view.start-ts' | translate }}"></mdp-date-picker>
+            <mdp-time-picker ng-model="startTs"
+                             mdp-max-date="maxStartTs"
+                             mdp-placeholder="{{ 'entity-view.start-ts' | translate }}"
+                             mdp-auto-switch="true"></mdp-time-picker>
+        </section>
+        <section layout="row" layout-align="start start">
+            <mdp-date-picker ng-model="endTs"
+                             mdp-min-date="minEndTs"
+                             mdp-placeholder="{{ 'entity-view.end-ts' | translate }}"></mdp-date-picker>
+            <mdp-time-picker ng-model="endTs"
+                             mdp-min-date="minEndTs"
+                             mdp-placeholder="{{ 'entity-view.end-ts' | translate }}"
+                             mdp-auto-switch="true"></mdp-time-picker>
+        </section>
 	</fieldset>
 </md-content>
diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json
index 09769ed..e98d4fe 100644
--- a/ui/src/app/locale/locale.constant-en_US.json
+++ b/ui/src/app/locale/locale.constant-en_US.json
@@ -822,7 +822,9 @@
         "unable-entity-view-device-alias-title": "Unable to delete entity view alias",
         "unable-entity-view-device-alias-text": "Device alias '{{entityViewAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}",
         "select-entity-view": "Select entity view",
-        "make-public": "Make entity view public"
+        "make-public": "Make entity view public",
+        "start-ts": "Start ts",
+        "end-ts": "End ts"
     },
     "event": {
         "event-type": "Event type",