Showing
7 changed files
with
83 additions
and
8 deletions
... | ... | @@ -180,6 +180,8 @@ public abstract class BaseController { |
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 | 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'"; |
183 | + public static final String WIDGET_TYPE_ID_PARAM_DESCRIPTION = "A string value representing the widget type id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; | |
184 | + | |
183 | 185 | |
184 | 186 | protected static final String SYSTEM_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' authority."; |
185 | 187 | protected static final String SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' or 'TENANT_ADMIN' authority."; |
... | ... | @@ -198,7 +200,6 @@ public abstract class BaseController { |
198 | 200 | protected static final String ASSET_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the asset name."; |
199 | 201 | protected static final String DASHBOARD_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the dashboard title."; |
200 | 202 | 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."; | |
202 | 203 | protected static final String RPC_TEXT_SEARCH_DESCRIPTION = "Not implemented. Leave empty."; |
203 | 204 | protected static final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device name."; |
204 | 205 | protected static final String USER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the user email."; |
... | ... | @@ -227,7 +228,6 @@ public abstract class BaseController { |
227 | 228 | protected static final String EDGE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle"; |
228 | 229 | protected static final String RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, root"; |
229 | 230 | 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"; | |
231 | 231 | protected static final String AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, entityType, entityName, userName, actionType, actionStatus"; |
232 | 232 | protected static final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESC (DESCENDING)"; |
233 | 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 lombok.extern.slf4j.Slf4j; |
19 | 21 | import org.springframework.http.HttpStatus; |
20 | 22 | import org.springframework.security.access.prepost.PreAuthorize; |
... | ... | @@ -48,10 +50,20 @@ import java.util.List; |
48 | 50 | @RequestMapping("/api") |
49 | 51 | public class WidgetTypeController extends BaseController { |
50 | 52 | |
53 | + private static final String WIDGET_TYPE_DESCRIPTION = "Widget Type represents the template for widget creation. Widget Type and Widget are similar to class and object in OOP theory."; | |
54 | + private static final String WIDGET_TYPE_DETAILS_DESCRIPTION = "Widget Type Details extend Widget Type and add image and description properties. " + | |
55 | + "Those properties are useful to edit the Widget Type but they are not required for Dashboard rendering. "; | |
56 | + private static final String WIDGET_TYPE_INFO_DESCRIPTION = "Widget Type Info is a lightweight object that represents Widget Type but does not contain the heavyweight widget descriptor JSON"; | |
57 | + | |
58 | + | |
59 | + @ApiOperation(value = "Get Widget Type Details (getWidgetTypeById)", | |
60 | + notes = "Get the Widget Type Details based on the provided Widget Type Id. " + WIDGET_TYPE_DETAILS_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) | |
51 | 61 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
52 | 62 | @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.GET) |
53 | 63 | @ResponseBody |
54 | - public WidgetTypeDetails getWidgetTypeById(@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { | |
64 | + public WidgetTypeDetails getWidgetTypeById( | |
65 | + @ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true) | |
66 | + @PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { | |
55 | 67 | checkParameter("widgetTypeId", strWidgetTypeId); |
56 | 68 | try { |
57 | 69 | WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); |
... | ... | @@ -61,10 +73,21 @@ public class WidgetTypeController extends BaseController { |
61 | 73 | } |
62 | 74 | } |
63 | 75 | |
76 | + @ApiOperation(value = "Create Or Update Widget Type (saveWidgetType)", | |
77 | + notes = "Create or update the Widget Type. " + WIDGET_TYPE_DESCRIPTION + " " + | |
78 | + "When creating the Widget Type, platform generates Widget Type Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " + | |
79 | + "The newly created Widget Type Id will be present in the response. " + | |
80 | + "Specify existing Widget Type id to update the Widget Type. " + | |
81 | + "Referencing non-existing Widget Type Id will cause 'Not Found' error." + | |
82 | + "\n\nWidget Type alias is unique in the scope of Widget Bundle. " + | |
83 | + "Special Tenant Id '13814000-1dd2-11b2-8080-808080808080' is automatically used if the create request is sent by user with 'SYS_ADMIN' authority." | |
84 | + + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) | |
64 | 85 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
65 | 86 | @RequestMapping(value = "/widgetType", method = RequestMethod.POST) |
66 | 87 | @ResponseBody |
67 | - public WidgetTypeDetails saveWidgetType(@RequestBody WidgetTypeDetails widgetTypeDetails) throws ThingsboardException { | |
88 | + public WidgetTypeDetails saveWidgetType( | |
89 | + @ApiParam(value = "A JSON value representing the Widget Type Details.", required = true) | |
90 | + @RequestBody WidgetTypeDetails widgetTypeDetails) throws ThingsboardException { | |
68 | 91 | try { |
69 | 92 | if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { |
70 | 93 | widgetTypeDetails.setTenantId(TenantId.SYS_TENANT_ID); |
... | ... | @@ -84,10 +107,14 @@ public class WidgetTypeController extends BaseController { |
84 | 107 | } |
85 | 108 | } |
86 | 109 | |
110 | + @ApiOperation(value = "Delete widget type (deleteWidgetType)", | |
111 | + notes = "Deletes the Widget Type. Referencing non-existing Widget Type Id will cause an error." + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) | |
87 | 112 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
88 | 113 | @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.DELETE) |
89 | 114 | @ResponseStatus(value = HttpStatus.OK) |
90 | - public void deleteWidgetType(@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { | |
115 | + public void deleteWidgetType( | |
116 | + @ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true) | |
117 | + @PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { | |
91 | 118 | checkParameter("widgetTypeId", strWidgetTypeId); |
92 | 119 | try { |
93 | 120 | WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); |
... | ... | @@ -101,11 +128,15 @@ public class WidgetTypeController extends BaseController { |
101 | 128 | } |
102 | 129 | } |
103 | 130 | |
131 | + @ApiOperation(value = "Get all Widget types for specified Bundle (getBundleWidgetTypes)", | |
132 | + notes = "Returns an array of Widget Type objects that belong to specified Widget Bundle." + WIDGET_TYPE_DESCRIPTION + " " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) | |
104 | 133 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
105 | 134 | @RequestMapping(value = "/widgetTypes", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) |
106 | 135 | @ResponseBody |
107 | 136 | public List<WidgetType> getBundleWidgetTypes( |
137 | + @ApiParam(value = "System or Tenant", required = true) | |
108 | 138 | @RequestParam boolean isSystem, |
139 | + @ApiParam(value = "Widget Bundle alias", required = true) | |
109 | 140 | @RequestParam String bundleAlias) throws ThingsboardException { |
110 | 141 | try { |
111 | 142 | TenantId tenantId; |
... | ... | @@ -120,11 +151,15 @@ public class WidgetTypeController extends BaseController { |
120 | 151 | } |
121 | 152 | } |
122 | 153 | |
154 | + @ApiOperation(value = "Get all Widget types details for specified Bundle (getBundleWidgetTypes)", | |
155 | + notes = "Returns an array of Widget Type Details objects that belong to specified Widget Bundle." + WIDGET_TYPE_DETAILS_DESCRIPTION + " " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) | |
123 | 156 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
124 | 157 | @RequestMapping(value = "/widgetTypesDetails", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) |
125 | 158 | @ResponseBody |
126 | 159 | public List<WidgetTypeDetails> getBundleWidgetTypesDetails( |
160 | + @ApiParam(value = "System or Tenant", required = true) | |
127 | 161 | @RequestParam boolean isSystem, |
162 | + @ApiParam(value = "Widget Bundle alias", required = true) | |
128 | 163 | @RequestParam String bundleAlias) throws ThingsboardException { |
129 | 164 | try { |
130 | 165 | TenantId tenantId; |
... | ... | @@ -139,11 +174,15 @@ public class WidgetTypeController extends BaseController { |
139 | 174 | } |
140 | 175 | } |
141 | 176 | |
177 | + @ApiOperation(value = "Get Widget Type Info objects (getBundleWidgetTypesInfos)", | |
178 | + notes = "Get the Widget Type Info objects based on the provided parameters. " + WIDGET_TYPE_INFO_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER) | |
142 | 179 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
143 | 180 | @RequestMapping(value = "/widgetTypesInfos", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) |
144 | 181 | @ResponseBody |
145 | 182 | public List<WidgetTypeInfo> getBundleWidgetTypesInfos( |
183 | + @ApiParam(value = "System or Tenant", required = true) | |
146 | 184 | @RequestParam boolean isSystem, |
185 | + @ApiParam(value = "Widget Bundle alias", required = true) | |
147 | 186 | @RequestParam String bundleAlias) throws ThingsboardException { |
148 | 187 | try { |
149 | 188 | TenantId tenantId; |
... | ... | @@ -158,12 +197,17 @@ public class WidgetTypeController extends BaseController { |
158 | 197 | } |
159 | 198 | } |
160 | 199 | |
200 | + @ApiOperation(value = "Get Widget Type (getWidgetType)", | |
201 | + notes = "Get the Widget Type based on the provided parameters. " + WIDGET_TYPE_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER) | |
161 | 202 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
162 | 203 | @RequestMapping(value = "/widgetType", params = {"isSystem", "bundleAlias", "alias"}, method = RequestMethod.GET) |
163 | 204 | @ResponseBody |
164 | 205 | public WidgetType getWidgetType( |
206 | + @ApiParam(value = "System or Tenant", required = true) | |
165 | 207 | @RequestParam boolean isSystem, |
208 | + @ApiParam(value = "Widget Bundle alias", required = true) | |
166 | 209 | @RequestParam String bundleAlias, |
210 | + @ApiParam(value = "Widget Type alias", required = true) | |
167 | 211 | @RequestParam String alias) throws ThingsboardException { |
168 | 212 | try { |
169 | 213 | TenantId tenantId; | ... | ... |
... | ... | @@ -54,7 +54,7 @@ public class WidgetsBundleController extends BaseController { |
54 | 54 | @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.GET) |
55 | 55 | @ResponseBody |
56 | 56 | public WidgetsBundle getWidgetsBundleById( |
57 | - @ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION) | |
57 | + @ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true) | |
58 | 58 | @PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException { |
59 | 59 | checkParameter("widgetsBundleId", strWidgetsBundleId); |
60 | 60 | try { |
... | ... | @@ -78,7 +78,7 @@ public class WidgetsBundleController extends BaseController { |
78 | 78 | @RequestMapping(value = "/widgetsBundle", method = RequestMethod.POST) |
79 | 79 | @ResponseBody |
80 | 80 | public WidgetsBundle saveWidgetsBundle( |
81 | - @ApiParam(value = "A JSON value representing the Widget Bundle.") | |
81 | + @ApiParam(value = "A JSON value representing the Widget Bundle.", required = true) | |
82 | 82 | @RequestBody WidgetsBundle widgetsBundle) throws ThingsboardException { |
83 | 83 | try { |
84 | 84 | if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { |
... | ... | @@ -104,7 +104,9 @@ public class WidgetsBundleController extends BaseController { |
104 | 104 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
105 | 105 | @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.DELETE) |
106 | 106 | @ResponseStatus(value = HttpStatus.OK) |
107 | - public void deleteWidgetsBundle(@PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException { | |
107 | + public void deleteWidgetsBundle( | |
108 | + @ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true) | |
109 | + @PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException { | |
108 | 110 | checkParameter("widgetsBundleId", strWidgetsBundleId); |
109 | 111 | try { |
110 | 112 | WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); | ... | ... |
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.data.widget; |
17 | 17 | |
18 | +import io.swagger.annotations.ApiModelProperty; | |
18 | 19 | import lombok.Data; |
19 | 20 | import org.thingsboard.server.common.data.BaseData; |
20 | 21 | import org.thingsboard.server.common.data.HasTenantId; |
... | ... | @@ -27,12 +28,16 @@ public class BaseWidgetType extends BaseData<WidgetTypeId> implements HasTenantI |
27 | 28 | |
28 | 29 | private static final long serialVersionUID = 8388684344603660756L; |
29 | 30 | |
31 | + @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", readOnly = true) | |
30 | 32 | private TenantId tenantId; |
31 | 33 | @NoXss |
34 | + @ApiModelProperty(position = 4, value = "Reference to widget bundle", readOnly = true) | |
32 | 35 | private String bundleAlias; |
33 | 36 | @NoXss |
37 | + @ApiModelProperty(position = 5, value = "Unique alias that is used in dashboards as a reference widget type", readOnly = true) | |
34 | 38 | private String alias; |
35 | 39 | @NoXss |
40 | + @ApiModelProperty(position = 6, value = "Widget name used in search and UI", readOnly = true) | |
36 | 41 | private String name; |
37 | 42 | |
38 | 43 | public BaseWidgetType() { |
... | ... | @@ -50,4 +55,19 @@ public class BaseWidgetType extends BaseData<WidgetTypeId> implements HasTenantI |
50 | 55 | this.alias = widgetType.getAlias(); |
51 | 56 | this.name = widgetType.getName(); |
52 | 57 | } |
58 | + | |
59 | + @ApiModelProperty(position = 1, value = "JSON object with the Widget Type Id. " + | |
60 | + "Specify this field to update the Widget Type. " + | |
61 | + "Referencing non-existing Widget Type Id will cause error. " + | |
62 | + "Omit this field to create new Widget Type." ) | |
63 | + @Override | |
64 | + public WidgetTypeId getId() { | |
65 | + return super.getId(); | |
66 | + } | |
67 | + | |
68 | + @ApiModelProperty(position = 2, value = "Timestamp of the Widget Type creation, in milliseconds", example = "1609459200000", readOnly = true) | |
69 | + @Override | |
70 | + public long getCreatedTime() { | |
71 | + return super.getCreatedTime(); | |
72 | + } | |
53 | 73 | } | ... | ... |
... | ... | @@ -16,12 +16,14 @@ |
16 | 16 | package org.thingsboard.server.common.data.widget; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | +import io.swagger.annotations.ApiModelProperty; | |
19 | 20 | import lombok.Data; |
20 | 21 | import org.thingsboard.server.common.data.id.WidgetTypeId; |
21 | 22 | |
22 | 23 | @Data |
23 | 24 | public class WidgetType extends BaseWidgetType { |
24 | 25 | |
26 | + @ApiModelProperty(position = 7, value = "Complex JSON object that describes the widget type", readOnly = true) | |
25 | 27 | private transient JsonNode descriptor; |
26 | 28 | |
27 | 29 | public WidgetType() { | ... | ... |
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | package org.thingsboard.server.common.data.widget; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; |
19 | +import io.swagger.annotations.ApiModelProperty; | |
19 | 20 | import lombok.Data; |
20 | 21 | import org.thingsboard.server.common.data.id.WidgetTypeId; |
21 | 22 | import org.thingsboard.server.common.data.validation.NoXss; |
... | ... | @@ -24,8 +25,10 @@ import org.thingsboard.server.common.data.validation.NoXss; |
24 | 25 | @JsonPropertyOrder({ "alias", "name", "image", "description", "descriptor" }) |
25 | 26 | public class WidgetTypeDetails extends WidgetType { |
26 | 27 | |
28 | + @ApiModelProperty(position = 8, value = "Base64 encoded thumbnail", readOnly = true) | |
27 | 29 | private String image; |
28 | 30 | @NoXss |
31 | + @ApiModelProperty(position = 9, value = "Description of the widget", readOnly = true) | |
29 | 32 | private String description; |
30 | 33 | |
31 | 34 | public WidgetTypeDetails() { | ... | ... |
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.data.widget; |
17 | 17 | |
18 | +import io.swagger.annotations.ApiModelProperty; | |
18 | 19 | import lombok.Data; |
19 | 20 | import org.thingsboard.server.common.data.id.WidgetTypeId; |
20 | 21 | import org.thingsboard.server.common.data.validation.NoXss; |
... | ... | @@ -22,10 +23,13 @@ import org.thingsboard.server.common.data.validation.NoXss; |
22 | 23 | @Data |
23 | 24 | public class WidgetTypeInfo extends BaseWidgetType { |
24 | 25 | |
26 | + @ApiModelProperty(position = 7, value = "Base64 encoded widget thumbnail", readOnly = true) | |
25 | 27 | private String image; |
26 | 28 | @NoXss |
29 | + @ApiModelProperty(position = 7, value = "Description of the widget type", readOnly = true) | |
27 | 30 | private String description; |
28 | 31 | @NoXss |
32 | + @ApiModelProperty(position = 8, value = "Type of the widget (timeseries, latest, control, alarm or static)", readOnly = true) | |
29 | 33 | private String widgetType; |
30 | 34 | |
31 | 35 | public WidgetTypeInfo() { | ... | ... |