Commit bf068011e0fcf416d473f18d80a32ade205d83f0

Authored by Andrii Shvaika
1 parent 2ee26655

Widget Bundle Controller

... ... @@ -179,12 +179,14 @@ public abstract class BaseController {
179 179 public static final String ENTITY_ID_PARAM_DESCRIPTION = "A string value representing the entity id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
180 180 public static final String ENTITY_TYPE_PARAM_DESCRIPTION = "A string value representing the entity type. For example, 'DEVICE'";
181 181 public static final String RULE_CHAIN_ID_PARAM_DESCRIPTION = "A string value representing the rule chain id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  182 + public static final String WIDGET_BUNDLE_ID_PARAM_DESCRIPTION = "A string value representing the widget bundle id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
182 183
183 184 protected static final String SYSTEM_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' authority.";
184 185 protected static final String SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' or 'TENANT_ADMIN' authority.";
185 186 protected static final String TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'TENANT_ADMIN' authority.";
186 187 protected static final String TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority.";
187 188 protected static final String CUSTOMER_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'CUSTOMER_USER' authority.";
  189 + protected static final String AVAILABLE_FOR_ANY_AUTHORIZED_USER = "\n\nAvailable for any authorized user. ";
188 190
189 191 protected static final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page";
190 192 protected static final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0";
... ... @@ -195,6 +197,8 @@ public abstract class BaseController {
195 197
196 198 protected static final String ASSET_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the asset name.";
197 199 protected static final String DASHBOARD_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the dashboard title.";
  200 + protected static final String WIDGET_BUNDLE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the widget bundle title.";
  201 + protected static final String WIDGET_TYPE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the widget type title.";
198 202 protected static final String RPC_TEXT_SEARCH_DESCRIPTION = "Not implemented. Leave empty.";
199 203 protected static final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device name.";
200 204 protected static final String USER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the user email.";
... ... @@ -222,6 +226,8 @@ public abstract class BaseController {
222 226 protected static final String EVENT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, id";
223 227 protected static final String EDGE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle";
224 228 protected static final String RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, root";
  229 + protected static final String WIDGET_BUNDLE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, tenantId";
  230 + protected static final String WIDGET_TYPE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, alias, bundleAlias, name";
225 231 protected static final String AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, entityType, entityName, userName, actionType, actionStatus";
226 232 protected static final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESC (DESCENDING)";
227 233 protected static final String SORT_ORDER_ALLOWABLE_VALUES = "ASC, DESC";
... ...
... ... @@ -15,6 +15,8 @@
15 15 */
16 16 package org.thingsboard.server.controller;
17 17
  18 +import io.swagger.annotations.ApiOperation;
  19 +import io.swagger.annotations.ApiParam;
18 20 import org.springframework.http.HttpStatus;
19 21 import org.springframework.security.access.prepost.PreAuthorize;
20 22 import org.springframework.web.bind.annotation.PathVariable;
... ... @@ -44,10 +46,16 @@ import java.util.List;
44 46 @RequestMapping("/api")
45 47 public class WidgetsBundleController extends BaseController {
46 48
  49 + private static final String WIDGET_BUNDLE_DESCRIPTION = "Widget Bundle represents a group(bundle) of widgets. Widgets are grouped into bundle by type or use case. ";
  50 +
  51 + @ApiOperation(value = "Get Widget Bundle (getWidgetsBundleById)",
  52 + notes = "Get the Widget Bundle based on the provided Widget Bundle Id. " + WIDGET_BUNDLE_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
47 53 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
48 54 @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.GET)
49 55 @ResponseBody
50   - public WidgetsBundle getWidgetsBundleById(@PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException {
  56 + public WidgetsBundle getWidgetsBundleById(
  57 + @ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION)
  58 + @PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException {
51 59 checkParameter("widgetsBundleId", strWidgetsBundleId);
52 60 try {
53 61 WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId));
... ... @@ -57,10 +65,21 @@ public class WidgetsBundleController extends BaseController {
57 65 }
58 66 }
59 67
  68 + @ApiOperation(value = "Create Or Update Widget Bundle (saveWidgetsBundle)",
  69 + notes = "Create or update the Widget Bundle. " + WIDGET_BUNDLE_DESCRIPTION + " " +
  70 + "When creating the bundle, platform generates Widget Bundle Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
  71 + "The newly created Widget Bundle Id will be present in the response. " +
  72 + "Specify existing Widget Bundle id to update the Widget Bundle. " +
  73 + "Referencing non-existing Widget Bundle Id will cause 'Not Found' error." +
  74 + "\n\nWidget Bundle alias is unique in the scope of tenant. " +
  75 + "Special Tenant Id '13814000-1dd2-11b2-8080-808080808080' is automatically used if the create bundle request is sent by user with 'SYS_ADMIN' authority."
  76 + + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
60 77 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
61 78 @RequestMapping(value = "/widgetsBundle", method = RequestMethod.POST)
62 79 @ResponseBody
63   - public WidgetsBundle saveWidgetsBundle(@RequestBody WidgetsBundle widgetsBundle) throws ThingsboardException {
  80 + public WidgetsBundle saveWidgetsBundle(
  81 + @ApiParam(value = "A JSON value representing the Widget Bundle.")
  82 + @RequestBody WidgetsBundle widgetsBundle) throws ThingsboardException {
64 83 try {
65 84 if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
66 85 widgetsBundle.setTenantId(TenantId.SYS_TENANT_ID);
... ... @@ -80,6 +99,8 @@ public class WidgetsBundleController extends BaseController {
80 99 }
81 100 }
82 101
  102 + @ApiOperation(value = "Delete widgets bundle (deleteWidgetsBundle)",
  103 + notes = "Deletes the widget bundle. Referencing non-existing Widget Bundle Id will cause an error." + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
83 104 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
84 105 @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.DELETE)
85 106 @ResponseStatus(value = HttpStatus.OK)
... ... @@ -97,14 +118,22 @@ public class WidgetsBundleController extends BaseController {
97 118 }
98 119 }
99 120
  121 + @ApiOperation(value = "Get Widget Bundles (getWidgetsBundles)",
  122 + notes = "Returns a page of Widget Bundle objects available for current user. " + WIDGET_BUNDLE_DESCRIPTION + " " +
  123 + PAGE_DATA_PARAMETERS + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
100 124 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
101 125 @RequestMapping(value = "/widgetsBundles", params = {"pageSize", "page"}, method = RequestMethod.GET)
102 126 @ResponseBody
103 127 public PageData<WidgetsBundle> getWidgetsBundles(
  128 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
104 129 @RequestParam int pageSize,
  130 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
105 131 @RequestParam int page,
  132 + @ApiParam(value = WIDGET_BUNDLE_TEXT_SEARCH_DESCRIPTION)
106 133 @RequestParam(required = false) String textSearch,
  134 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = WIDGET_BUNDLE_SORT_PROPERTY_ALLOWABLE_VALUES)
107 135 @RequestParam(required = false) String sortProperty,
  136 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
108 137 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
109 138 try {
110 139 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
... ... @@ -119,6 +148,8 @@ public class WidgetsBundleController extends BaseController {
119 148 }
120 149 }
121 150
  151 + @ApiOperation(value = "Get all Widget Bundles (getWidgetsBundles)",
  152 + notes = "Returns an array of Widget Bundle objects that are available for current user." + WIDGET_BUNDLE_DESCRIPTION + " " + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
122 153 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
123 154 @RequestMapping(value = "/widgetsBundles", method = RequestMethod.GET)
124 155 @ResponseBody
... ...
... ... @@ -15,6 +15,10 @@
15 15 */
16 16 package org.thingsboard.server.common.data.widget;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
  20 +import lombok.Getter;
  21 +import lombok.Setter;
18 22 import org.thingsboard.server.common.data.HasTenantId;
19 23 import org.thingsboard.server.common.data.SearchTextBased;
20 24 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -23,17 +27,37 @@ import org.thingsboard.server.common.data.validation.NoXss;
23 27
24 28 import java.util.Arrays;
25 29
  30 +@ApiModel
26 31 public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements HasTenantId {
27 32
28 33 private static final long serialVersionUID = -7627368878362410489L;
29 34
  35 + @Getter
  36 + @Setter
  37 + @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", readOnly = true)
30 38 private TenantId tenantId;
  39 +
31 40 @NoXss
  41 + @Getter
  42 + @Setter
  43 + @ApiModelProperty(position = 4, value = "Unique alias that is used in widget types as a reference widget bundle", readOnly = true)
32 44 private String alias;
  45 +
33 46 @NoXss
  47 + @Getter
  48 + @Setter
  49 + @ApiModelProperty(position = 5, value = "Title used in search and UI", readOnly = true)
34 50 private String title;
  51 +
  52 + @Getter
  53 + @Setter
  54 + @ApiModelProperty(position = 6, value = "Base64 encoded thumbnail", readOnly = true)
35 55 private String image;
  56 +
36 57 @NoXss
  58 + @Getter
  59 + @Setter
  60 + @ApiModelProperty(position = 7, value = "Description", readOnly = true)
37 61 private String description;
38 62
39 63 public WidgetsBundle() {
... ... @@ -53,42 +77,21 @@ public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements H
53 77 this.description = widgetsBundle.getDescription();
54 78 }
55 79
56   - public TenantId getTenantId() {
57   - return tenantId;
58   - }
59   -
60   - public void setTenantId(TenantId tenantId) {
61   - this.tenantId = tenantId;
62   - }
63   -
64   - public String getAlias() {
65   - return alias;
66   - }
67   -
68   - public void setAlias(String alias) {
69   - this.alias = alias;
70   - }
71   -
72   - public String getTitle() {
73   - return title;
74   - }
75   -
76   - public void setTitle(String title) {
77   - this.title = title;
78   - }
79   -
80   - public String getImage() {
81   - return image;
  80 + @ApiModelProperty(position = 1, value = "JSON object with the Widget Bundle Id. " +
  81 + "Specify this field to update the Widget Bundle. " +
  82 + "Referencing non-existing Widget Bundle Id will cause error. " +
  83 + "Omit this field to create new Widget Bundle." )
  84 + @Override
  85 + public WidgetsBundleId getId() {
  86 + return super.getId();
82 87 }
83 88
84   - public void setImage(String image) {
85   - this.image = image;
  89 + @ApiModelProperty(position = 2, value = "Timestamp of the Widget Bundle creation, in milliseconds", example = "1609459200000", readOnly = true)
  90 + @Override
  91 + public long getCreatedTime() {
  92 + return super.getCreatedTime();
86 93 }
87 94
88   - public String getDescription() { return description; }
89   -
90   - public void setDescription(String description) { this.description = description; }
91   -
92 95 @Override
93 96 public String getSearchText() {
94 97 return getTitle();
... ...