Browse Source

Move from device type to device profile

pull/3477/head
Igor Kulikov 6 years ago
parent
commit
83ea3f0836
  1. 9
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java
  2. 32
      application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
  3. 5
      common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java
  4. 20
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java
  5. 20
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java
  6. 26
      dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java
  7. 21
      dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java
  8. 12
      ui-ngx/src/app/core/http/device.service.ts
  9. 3
      ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.html
  10. 78
      ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.ts
  11. 12
      ui-ngx/src/app/modules/home/pages/device/device-table-header.component.html
  12. 2
      ui-ngx/src/app/modules/home/pages/device/device-table-header.component.scss
  13. 5
      ui-ngx/src/app/modules/home/pages/device/device-table-header.component.ts
  14. 6
      ui-ngx/src/app/modules/home/pages/device/device.component.html
  15. 2
      ui-ngx/src/app/modules/home/pages/device/device.component.ts
  16. 19
      ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts
  17. 1
      ui-ngx/src/assets/locale/locale.constant-en_US.json

9
application/src/main/java/org/thingsboard/server/controller/DeviceController.java

@ -47,6 +47,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
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.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
@ -315,6 +316,7 @@ public class DeviceController extends BaseController {
@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String type,
@RequestParam(required = false) String deviceProfileId,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
@ -323,6 +325,9 @@ public class DeviceController extends BaseController {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
if (type != null && type.trim().length() > 0) {
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndType(tenantId, type, pageLink));
} else if (deviceProfileId != null && deviceProfileId.length() > 0) {
DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId));
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndDeviceProfileId(tenantId, profileId, pageLink));
} else {
return checkNotNull(deviceService.findDeviceInfosByTenantId(tenantId, pageLink));
}
@ -379,6 +384,7 @@ public class DeviceController extends BaseController {
@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String type,
@RequestParam(required = false) String deviceProfileId,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
@ -390,6 +396,9 @@ public class DeviceController extends BaseController {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
if (type != null && type.trim().length() > 0) {
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
} else if (deviceProfileId != null && deviceProfileId.length() > 0) {
DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId));
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(tenantId, customerId, profileId, pageLink));
} else {
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink));
}

32
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java

@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.TenantProfileData;
@ -34,6 +35,7 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
import org.thingsboard.server.common.data.kv.BooleanDataEntry;
@ -48,6 +50,7 @@ import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.dao.device.DeviceProfileService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.relation.RelationService;
@ -101,6 +104,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
@Autowired
private DeviceService deviceService;
@Autowired
private DeviceProfileService deviceProfileService;
@Autowired
private AttributesService attributesService;
@ -213,16 +219,18 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
createUser(Authority.CUSTOMER_USER, demoTenant.getId(), customerB.getId(), "customerB@thingsboard.org", CUSTOMER_CRED);
createUser(Authority.CUSTOMER_USER, demoTenant.getId(), customerC.getId(), "customerC@thingsboard.org", CUSTOMER_CRED);
createDevice(demoTenant.getId(), customerA.getId(), DEFAULT_DEVICE_TYPE, "Test Device A1", "A1_TEST_TOKEN", null);
createDevice(demoTenant.getId(), customerA.getId(), DEFAULT_DEVICE_TYPE, "Test Device A2", "A2_TEST_TOKEN", null);
createDevice(demoTenant.getId(), customerA.getId(), DEFAULT_DEVICE_TYPE, "Test Device A3", "A3_TEST_TOKEN", null);
createDevice(demoTenant.getId(), customerB.getId(), DEFAULT_DEVICE_TYPE, "Test Device B1", "B1_TEST_TOKEN", null);
createDevice(demoTenant.getId(), customerC.getId(), DEFAULT_DEVICE_TYPE, "Test Device C1", "C1_TEST_TOKEN", null);
DeviceProfile defaultDeviceProfile = this.deviceProfileService.findOrCreateDeviceProfile(demoTenant.getId(), DEFAULT_DEVICE_TYPE);
createDevice(demoTenant.getId(), null, DEFAULT_DEVICE_TYPE, "DHT11 Demo Device", "DHT11_DEMO_TOKEN", "Demo device that is used in sample " +
createDevice(demoTenant.getId(), customerA.getId(), defaultDeviceProfile.getId(), "Test Device A1", "A1_TEST_TOKEN", null);
createDevice(demoTenant.getId(), customerA.getId(), defaultDeviceProfile.getId(), "Test Device A2", "A2_TEST_TOKEN", null);
createDevice(demoTenant.getId(), customerA.getId(), defaultDeviceProfile.getId(), "Test Device A3", "A3_TEST_TOKEN", null);
createDevice(demoTenant.getId(), customerB.getId(), defaultDeviceProfile.getId(), "Test Device B1", "B1_TEST_TOKEN", null);
createDevice(demoTenant.getId(), customerC.getId(), defaultDeviceProfile.getId(), "Test Device C1", "C1_TEST_TOKEN", null);
createDevice(demoTenant.getId(), null, defaultDeviceProfile.getId(), "DHT11 Demo Device", "DHT11_DEMO_TOKEN", "Demo device that is used in sample " +
"applications that upload data from DHT11 temperature and humidity sensor");
createDevice(demoTenant.getId(), null, DEFAULT_DEVICE_TYPE, "Raspberry Pi Demo Device", "RASPBERRY_PI_DEMO_TOKEN", "Demo device that is used in " +
createDevice(demoTenant.getId(), null, defaultDeviceProfile.getId(), "Raspberry Pi Demo Device", "RASPBERRY_PI_DEMO_TOKEN", "Demo device that is used in " +
"Raspberry Pi GPIO control sample application");
Asset thermostatAlarms = new Asset();
@ -231,8 +239,10 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
thermostatAlarms.setType("AlarmPropagationAsset");
thermostatAlarms = assetService.saveAsset(thermostatAlarms);
DeviceId t1Id = createDevice(demoTenant.getId(), null, "thermostat", "Thermostat T1", "T1_TEST_TOKEN", "Demo device for Thermostats dashboard").getId();
DeviceId t2Id = createDevice(demoTenant.getId(), null, "thermostat", "Thermostat T2", "T2_TEST_TOKEN", "Demo device for Thermostats dashboard").getId();
DeviceProfile thermostatDeviceProfile = this.deviceProfileService.findOrCreateDeviceProfile(demoTenant.getId(), "thermostat");
DeviceId t1Id = createDevice(demoTenant.getId(), null, thermostatDeviceProfile.getId(), "Thermostat T1", "T1_TEST_TOKEN", "Demo device for Thermostats dashboard").getId();
DeviceId t2Id = createDevice(demoTenant.getId(), null, thermostatDeviceProfile.getId(), "Thermostat T2", "T2_TEST_TOKEN", "Demo device for Thermostats dashboard").getId();
relationService.saveRelation(thermostatAlarms.getTenantId(), new EntityRelation(thermostatAlarms.getId(), t1Id, "ToAlarmPropagationAsset"));
relationService.saveRelation(thermostatAlarms.getTenantId(), new EntityRelation(thermostatAlarms.getId(), t2Id, "ToAlarmPropagationAsset"));
@ -308,14 +318,14 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
private Device createDevice(TenantId tenantId,
CustomerId customerId,
String type,
DeviceProfileId deviceProfileId,
String name,
String accessToken,
String description) {
Device device = new Device();
device.setTenantId(tenantId);
device.setCustomerId(customerId);
device.setType(type);
device.setDeviceProfileId(deviceProfileId);
device.setName(name);
if (description != null) {
ObjectNode additionalInfo = objectMapper.createObjectNode();

5
common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java

@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.device.DeviceSearchQuery;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
@ -56,6 +57,8 @@ public interface DeviceService {
PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink);
PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(TenantId tenantId, DeviceProfileId deviceProfileId, PageLink pageLink);
ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds);
void deleteDevicesByTenantId(TenantId tenantId);
@ -68,6 +71,8 @@ public interface DeviceService {
PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink);
PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(TenantId tenantId, CustomerId customerId, DeviceProfileId deviceProfileId, PageLink pageLink);
ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds);
void unassignCustomerDevices(TenantId tenantId, CustomerId customerId);

20
dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java

@ -89,6 +89,16 @@ public interface DeviceDao extends Dao<Device> {
*/
PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink);
/**
* Find device infos by tenantId, deviceProfileId and page link.
*
* @param tenantId the tenantId
* @param deviceProfileId the deviceProfileId
* @param pageLink the page link
* @return the list of device info objects
*/
PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(UUID tenantId, UUID deviceProfileId, PageLink pageLink);
/**
* Find devices by tenantId and devices Ids.
*
@ -140,6 +150,16 @@ public interface DeviceDao extends Dao<Device> {
*/
PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink);
/**
* Find device infos by tenantId, customerId, deviceProfileId and page link.
*
* @param tenantId the tenantId
* @param customerId the customerId
* @param deviceProfileId the deviceProfileId
* @param pageLink the page link
* @return the list of device info objects
*/
PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(UUID tenantId, UUID customerId, UUID deviceProfileId, PageLink pageLink);
/**
* Find devices by tenantId, customerId and devices Ids.

20
dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java

@ -87,6 +87,7 @@ import static org.thingsboard.server.dao.service.Validator.validateString;
public class DeviceServiceImpl extends AbstractEntityService implements DeviceService {
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
public static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId ";
public static final String INCORRECT_PAGE_LINK = "Incorrect page link ";
public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId ";
public static final String INCORRECT_DEVICE_ID = "Incorrect deviceId ";
@ -302,6 +303,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
return deviceDao.findDeviceInfosByTenantIdAndType(tenantId.getId(), type, pageLink);
}
@Override
public PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(TenantId tenantId, DeviceProfileId deviceProfileId, PageLink pageLink) {
log.trace("Executing findDeviceInfosByTenantIdAndDeviceProfileId, tenantId [{}], deviceProfileId [{}], pageLink [{}]", tenantId, deviceProfileId, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
validatePageLink(pageLink);
return deviceDao.findDeviceInfosByTenantIdAndDeviceProfileId(tenantId.getId(), deviceProfileId.getId(), pageLink);
}
@Override
public ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds) {
log.trace("Executing findDevicesByTenantIdAndIdsAsync, tenantId [{}], deviceIds [{}]", tenantId, deviceIds);
@ -356,6 +366,16 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
return deviceDao.findDeviceInfosByTenantIdAndCustomerIdAndType(tenantId.getId(), customerId.getId(), type, pageLink);
}
@Override
public PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(TenantId tenantId, CustomerId customerId, DeviceProfileId deviceProfileId, PageLink pageLink) {
log.trace("Executing findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId, tenantId [{}], customerId [{}], deviceProfileId [{}], pageLink [{}]", tenantId, customerId, deviceProfileId, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
validatePageLink(pageLink);
return deviceDao.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(tenantId.getId(), customerId.getId(), deviceProfileId.getId(), pageLink);
}
@Override
public ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds) {
log.trace("Executing findDevicesByTenantIdCustomerIdAndIdsAsync, tenantId [{}], customerId [{}], deviceIds [{}]", tenantId, customerId, deviceIds);

26
dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java

@ -106,6 +106,18 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " +
"FROM DeviceEntity d " +
"LEFT JOIN CustomerEntity c on c.id = d.customerId " +
"LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " +
"WHERE d.tenantId = :tenantId " +
"AND d.deviceProfileId = :deviceProfileId " +
"AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
Page<DeviceInfoEntity> findDeviceInfosByTenantIdAndDeviceProfileId(@Param("tenantId") UUID tenantId,
@Param("deviceProfileId") UUID deviceProfileId,
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " +
"AND d.customerId = :customerId " +
"AND d.type = :type " +
@ -130,6 +142,20 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " +
"FROM DeviceEntity d " +
"LEFT JOIN CustomerEntity c on c.id = d.customerId " +
"LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " +
"WHERE d.tenantId = :tenantId " +
"AND d.customerId = :customerId " +
"AND d.deviceProfileId = :deviceProfileId " +
"AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
Page<DeviceInfoEntity> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(@Param("tenantId") UUID tenantId,
@Param("customerId") UUID customerId,
@Param("deviceProfileId") UUID deviceProfileId,
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT DISTINCT d.type FROM DeviceEntity d WHERE d.tenantId = :tenantId")
List<String> findTenantDeviceTypes(@Param("tenantId") UUID tenantId);

21
dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java

@ -156,6 +156,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap)));
}
@Override
public PageData<DeviceInfo> findDeviceInfosByTenantIdAndDeviceProfileId(UUID tenantId, UUID deviceProfileId, PageLink pageLink) {
return DaoUtil.toPageData(
deviceRepository.findDeviceInfosByTenantIdAndDeviceProfileId(
tenantId,
deviceProfileId,
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap)));
}
@Override
public PageData<Device> findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) {
return DaoUtil.toPageData(
@ -178,6 +188,17 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap)));
}
@Override
public PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(UUID tenantId, UUID customerId, UUID deviceProfileId, PageLink pageLink) {
return DaoUtil.toPageData(
deviceRepository.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(
tenantId,
customerId,
deviceProfileId,
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap)));
}
@Override
public ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId) {
return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(tenantId)));

12
ui-ngx/src/app/core/http/device.service.ts

@ -46,12 +46,24 @@ export class DeviceService {
defaultHttpOptionsFromConfig(config));
}
public getTenantDeviceInfosByDeviceProfileId(pageLink: PageLink, deviceProfileId: string = '',
config?: RequestConfig): Observable<PageData<DeviceInfo>> {
return this.http.get<PageData<DeviceInfo>>(`/api/tenant/deviceInfos${pageLink.toQuery()}&deviceProfileId=${deviceProfileId}`,
defaultHttpOptionsFromConfig(config));
}
public getCustomerDeviceInfos(customerId: string, pageLink: PageLink, type: string = '',
config?: RequestConfig): Observable<PageData<DeviceInfo>> {
return this.http.get<PageData<DeviceInfo>>(`/api/customer/${customerId}/deviceInfos${pageLink.toQuery()}&type=${type}`,
defaultHttpOptionsFromConfig(config));
}
public getCustomerDeviceInfosByDeviceProfileId(customerId: string, pageLink: PageLink, deviceProfileId: string = '',
config?: RequestConfig): Observable<PageData<DeviceInfo>> {
return this.http.get<PageData<DeviceInfo>>(`/api/customer/${customerId}/deviceInfos${pageLink.toQuery()}&deviceProfileId=${deviceProfileId}`,
defaultHttpOptionsFromConfig(config));
}
public getDevice(deviceId: string, config?: RequestConfig): Observable<Device> {
return this.http.get<Device>(`/api/device/${deviceId}`, defaultHttpOptionsFromConfig(config));
}

3
ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.html

@ -30,7 +30,7 @@
(click)="clear()">
<mat-icon class="material-icons">close</mat-icon>
</button>
<button *ngIf="selectDeviceProfileFormGroup.get('deviceProfile').value && !disabled"
<button *ngIf="selectDeviceProfileFormGroup.get('deviceProfile').value && !disabled && editProfileEnabled"
type="button"
matSuffix mat-button mat-icon-button aria-label="Edit"
matTooltip="{{ 'device-profile.edit' | translate }}"
@ -40,6 +40,7 @@
</button>
<mat-autocomplete
class="tb-autocomplete"
(closed)="onPanelClosed()"
#deviceProfileAutocomplete="matAutocomplete"
[displayWith]="displayDeviceProfileFn">
<mat-option *ngFor="let deviceProfile of filteredDeviceProfiles | async" [value]="deviceProfile">

78
ui-ngx/src/app/modules/home/components/profile/device-profile-autocomplete.component.ts

@ -14,12 +14,21 @@
/// limitations under the License.
///
import { Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core';
import {
Component,
ElementRef,
EventEmitter,
forwardRef,
Input, NgZone,
OnInit,
Output,
ViewChild
} from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Observable } from 'rxjs';
import { PageLink } from '@shared/models/page/page-link';
import { Direction } from '@shared/models/page/sort-order';
import { map, mergeMap, share, startWith, tap } from 'rxjs/operators';
import { map, mergeMap, share, tap } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state';
import { TranslateService } from '@ngx-translate/core';
@ -39,6 +48,7 @@ import {
} from '@shared/models/device.models';
import { DeviceProfileService } from '@core/http/device-profile.service';
import { DeviceProfileDialogComponent, DeviceProfileDialogData } from './device-profile-dialog.component';
import { MatAutocomplete } from '@angular/material/autocomplete';
@Component({
selector: 'tb-device-profile-autocomplete',
@ -59,6 +69,12 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor,
@Input()
selectDefaultProfile = false;
@Input()
displayAllOnEmpty = false;
@Input()
editProfileEnabled = true;
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
@ -79,12 +95,23 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor,
@ViewChild('deviceProfileInput', {static: true}) deviceProfileInput: ElementRef;
@ViewChild('deviceProfileAutocomplete', {static: true}) deviceProfileAutocomplete: MatAutocomplete;
filteredDeviceProfiles: Observable<Array<DeviceProfileInfo>>;
searchText = '';
private dirty = false;
private ignoreClosedPanel = false;
private allDeviceProfile: DeviceProfileInfo = {
name: this.translate.instant('device-profile.all-device-profiles'),
type: DeviceProfileType.DEFAULT,
transportType: DeviceTransportType.DEFAULT,
id: null
};
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
@ -92,6 +119,7 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor,
public truncate: TruncatePipe,
private deviceProfileService: DeviceProfileService,
private fb: FormBuilder,
private zone: NgZone,
private dialog: MatDialog) {
this.selectDeviceProfileFormGroup = this.fb.group({
deviceProfile: [null]
@ -115,9 +143,25 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor,
} else {
modelValue = value;
}
this.updateView(modelValue);
if (!this.displayAllOnEmpty || modelValue) {
this.updateView(modelValue);
}
}),
map(value => {
if (value) {
if (typeof value === 'string') {
return value;
} else {
if (this.displayAllOnEmpty && value === this.allDeviceProfile) {
return '';
} else {
return value.name;
}
}
} else {
return '';
}
}),
map(value => value ? (typeof value === 'string' ? value : value.name) : ''),
mergeMap(name => this.fetchDeviceProfiles(name) ),
share()
);
@ -150,6 +194,9 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor,
this.deviceProfileChanged.emit(profile);
}
);
} else if (this.displayAllOnEmpty) {
this.modelValue = null;
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(this.allDeviceProfile, {emitEvent: false});
} else {
this.modelValue = null;
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(null, {emitEvent: false});
@ -165,8 +212,20 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor,
}
}
onPanelClosed() {
if (this.ignoreClosedPanel) {
this.ignoreClosedPanel = false;
} else {
if (this.displayAllOnEmpty && !this.selectDeviceProfileFormGroup.get('deviceProfile').value) {
this.zone.run(() => {
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(this.allDeviceProfile, {emitEvent: true});
}, 0);
}
}
}
updateView(deviceProfile: DeviceProfileInfo | null) {
const idValue = deviceProfile ? new DeviceProfileId(deviceProfile.id.id) : null;
const idValue = deviceProfile && deviceProfile.id ? new DeviceProfileId(deviceProfile.id.id) : null;
if (!entityIdEquals(this.modelValue, idValue)) {
this.modelValue = idValue;
this.propagateChange(this.modelValue);
@ -186,12 +245,17 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor,
});
return this.deviceProfileService.getDeviceProfileInfos(pageLink, {ignoreLoading: true}).pipe(
map(pageData => {
return pageData.data;
let data = pageData.data;
if (this.displayAllOnEmpty) {
data = [this.allDeviceProfile, ...data];
}
return data;
})
);
}
clear() {
this.ignoreClosedPanel = true;
this.selectDeviceProfileFormGroup.get('deviceProfile').patchValue(null, {emitEvent: true});
setTimeout(() => {
this.deviceProfileInput.nativeElement.blur();
@ -204,7 +268,7 @@ export class DeviceProfileAutocompleteComponent implements ControlValueAccessor,
}
deviceProfileEnter($event: KeyboardEvent) {
if ($event.keyCode === ENTER) {
if (this.editProfileEnabled && $event.keyCode === ENTER) {
$event.preventDefault();
if (!this.modelValue) {
this.createDeviceProfile($event, this.searchText);

12
ui-ngx/src/app/modules/home/pages/device/device-table-header.component.html

@ -15,9 +15,9 @@
limitations under the License.
-->
<tb-entity-subtype-select
[showLabel]="true"
[entityType]="entityType.DEVICE"
[ngModel]="entitiesTableConfig.componentsData.deviceType"
(ngModelChange)="deviceTypeChanged($event)">
</tb-entity-subtype-select>
<tb-device-profile-autocomplete
[ngModel]="entitiesTableConfig.componentsData.deviceProfileId"
(ngModelChange)="deviceProfileChanged($event)"
[displayAllOnEmpty]="true"
[editProfileEnabled]="false">
</tb-device-profile-autocomplete>

2
ui-ngx/src/app/modules/home/pages/device/device-table-header.component.scss

@ -23,7 +23,7 @@
}
:host ::ng-deep {
tb-entity-subtype-select {
tb-device-profile-autocomplete {
width: 100%;
mat-form-field {

5
ui-ngx/src/app/modules/home/pages/device/device-table-header.component.ts

@ -20,6 +20,7 @@ import { AppState } from '@core/core.state';
import { EntityTableHeaderComponent } from '../../components/entity/entity-table-header.component';
import { DeviceInfo } from '@app/shared/models/device.models';
import { EntityType } from '@shared/models/entity-type.models';
import { DeviceProfileId } from '../../../../shared/models/id/device-profile-id';
@Component({
selector: 'tb-device-table-header',
@ -34,8 +35,8 @@ export class DeviceTableHeaderComponent extends EntityTableHeaderComponent<Devic
super(store);
}
deviceTypeChanged(deviceType: string) {
this.entitiesTableConfig.componentsData.deviceType = deviceType;
deviceProfileChanged(deviceProfileId: DeviceProfileId) {
this.entitiesTableConfig.componentsData.deviceProfileId = deviceProfileId;
this.entitiesTableConfig.table.resetSortAndFilter(true);
}

6
ui-ngx/src/app/modules/home/pages/device/device.component.html

@ -90,12 +90,6 @@
(deviceProfileUpdated)="onDeviceProfileUpdated()"
(deviceProfileChanged)="onDeviceProfileChanged($event)">
</tb-device-profile-autocomplete>
<tb-entity-subtype-autocomplete
formControlName="type"
[required]="true"
[entityType]="entityType.DEVICE"
>
</tb-entity-subtype-autocomplete>
<mat-form-field class="mat-block">
<mat-label translate>device.label</mat-label>
<input matInput formControlName="label">

2
ui-ngx/src/app/modules/home/pages/device/device.component.ts

@ -80,7 +80,6 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
{
name: [entity ? entity.name : '', [Validators.required]],
deviceProfileId: [entity ? entity.deviceProfileId : null, [Validators.required]],
type: [entity ? entity.type : null, [Validators.required]],
label: [entity ? entity.label : ''],
deviceData: [entity ? entity.deviceData : null, [Validators.required]],
additionalInfo: this.fb.group(
@ -96,7 +95,6 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
updateForm(entity: DeviceInfo) {
this.entityForm.patchValue({name: entity.name});
this.entityForm.patchValue({deviceProfileId: entity.deviceProfileId});
this.entityForm.patchValue({type: entity.type});
this.entityForm.patchValue({label: entity.label});
this.entityForm.patchValue({deviceData: entity.deviceData});
this.entityForm.patchValue({additionalInfo:

19
ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts

@ -113,7 +113,7 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
const routeParams = route.params;
this.config.componentsData = {
deviceScope: route.data.devicesType,
deviceType: ''
deviceProfileId: null
};
this.customerId = routeParams.customerId;
return this.store.pipe(select(selectAuthUser), take(1)).pipe(
@ -152,14 +152,13 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
configureColumns(deviceScope: string): Array<EntityTableColumn<DeviceInfo>> {
const columns: Array<EntityTableColumn<DeviceInfo>> = [
new DateEntityTableColumn<DeviceInfo>('createdTime', 'common.created-time', this.datePipe, '150px'),
new EntityTableColumn<DeviceInfo>('name', 'device.name', '20%'),
new EntityTableColumn<DeviceInfo>('deviceProfileName', 'device-profile.device-profile', '20%'),
new EntityTableColumn<DeviceInfo>('type', 'device.device-type', '20%'),
new EntityTableColumn<DeviceInfo>('label', 'device.label', '20%')
new EntityTableColumn<DeviceInfo>('name', 'device.name', '25%'),
new EntityTableColumn<DeviceInfo>('deviceProfileName', 'device-profile.device-profile', '25%'),
new EntityTableColumn<DeviceInfo>('label', 'device.label', '25%')
];
if (deviceScope === 'tenant') {
columns.push(
new EntityTableColumn<DeviceInfo>('customerTitle', 'customer.customer', '20%'),
new EntityTableColumn<DeviceInfo>('customerTitle', 'customer.customer', '25%'),
new EntityTableColumn<DeviceInfo>('customerIsPublic', 'device.public', '60px',
entity => {
return checkBoxCell(entity.customerIsPublic);
@ -178,11 +177,15 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
configureEntityFunctions(deviceScope: string): void {
if (deviceScope === 'tenant') {
this.config.entitiesFetchFunction = pageLink =>
this.deviceService.getTenantDeviceInfos(pageLink, this.config.componentsData.deviceType);
this.deviceService.getTenantDeviceInfosByDeviceProfileId(pageLink,
this.config.componentsData.deviceProfileId !== null ?
this.config.componentsData.deviceProfileId.id : '');
this.config.deleteEntity = id => this.deviceService.deleteDevice(id.id);
} else {
this.config.entitiesFetchFunction = pageLink =>
this.deviceService.getCustomerDeviceInfos(this.customerId, pageLink, this.config.componentsData.deviceType);
this.deviceService.getCustomerDeviceInfosByDeviceProfileId(this.customerId, pageLink,
this.config.componentsData.deviceProfileId !== null ?
this.config.componentsData.deviceProfileId.id : '');
this.config.deleteEntity = id => this.deviceService.unassignDeviceFromCustomer(id.id);
}
}

1
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -755,6 +755,7 @@
"device-profile": {
"device-profile": "Device profile",
"device-profiles": "Device profiles",
"all-device-profiles": "All",
"add": "Add device profile",
"edit": "Edit device profile",
"device-profile-details": "Device profile details",

Loading…
Cancel
Save