Thingsboard input String widget - iot

i'am working with thingsboard as a plateform to supervise my sensors ,and i want to know if there is any way to add in my dashboard a field that allow me to write comments and those comments will be written in postgresql database ?
i Tried to use input widget but it dosent work

it's a bit harder to make comments that will not overwrite previous comments since you would keep those comments under server attributes (you can't work with postgreSQL directly from ThingsBoard).
Solution to that is that you have input widget and then RPC call to rule chain where you would need to have some script that would put new comment as new field to the JSON array. This obviously requires a bit advanced knowledge about TB.
Also you could probably do that thru "Custom action (with HTML template)".
UPDATE:
The easiest way you can have comments :
Create JSON server attribute on entity (Device, Asset)
(Optional) Create filter that will return only one entity
Create "Update JSON attribute" widget and point it to the server attribute of entity on which you have done first step (help your self with step 2.)
a. have something like this in that window: {"comments":[{"ts":1665472792000,"value":"My comm1"},{"ts":1668163473000,"value":"My comm2"}]}
Create "HTML Value Card" widget, which also points to that entity and it's server attribute
In "HTML Value Card" widget use this code in server attribute post-processing function:
var comm = parsed["comments"]
var returnValue = '';
if (comm){
var commLength = comm.length;
}
for (var i=0;i<commLength;i++){
returnValue += "<span>"+comm[i]["value"]+"<span><br>";
}
return returnValue;
This code in HTML of "HTML Value Card": ${nameOfYourServerAttribute}
Yes, you will have to manually add comments directly to JSON, I don't have time to write some widget for that.
Take a look at my example:

Related

Retain Sorting After Specific Action - Grails

I have a gsp form which displays the list of employees with the details (ie., Employee Name,Designation,Department,Status). All these columns are sortable. After calling a specific action in my controller class (ie., Changing the status of the employee from active to inactive and vice versa) the sorting gets disturbed. I am using the following code to sort while retrieving from DB
String strSort = params.sort ?: "empId";
strSort += " "
strSort += params.order?: "asc";
Is there any way I can retain the sort order which was there before posting a "Status change" action? If it is how it can be achieved?
As suggested by rvargas, it is possible through a variety of methods. queuekit plugin isn't released properly as yet so you could clone grails 3 / grails2 branch depending on which it is you are working with and also clone the test site to go with it to mess with this concept within the plugin:
In short You need to separate out your search feature and you can do this via a session value or send it as a subset list iteration.
I decided to not use sessions. Then when I click delete The bean is bound back in with the request sent (which be the id to delete)
At the very end it relists so no need to do any other here:
The most important bit being when I call the ajax reloadPage or even further postAction used by delete function is that I serialize search form. The actual search object is kept in a tidy manner here
But if this is too complex then in the very controller link the session search was commented out. I think you could just enable that forget all this complication and have a searchAgain() feature which renders the _list template like it does if it is xhr in my controller and rather than binding bean it binds the session.search map instead and if you did go down this route you probably want to change from g:render to g:include action="searchAgain"
Hope that helps you understand better
I can think of two ways to do it:
Pass your sort and order parameters to your action and send them back
with the result.
Store in session both parameters every time you update them.
To store and retrive from session use something like this:
private DEFAULT_SORT = 'myDefaultSort'
def myAction() {
if (params.sort && params.sort != session.getAttribute('sort-' + actionName)) {
session.setAttribute('sort-' + actionName, params.sort)
}
params.sort = session.getAttribute('sort-' + actionName)?:DEFAULT_SORT
...
//Your existing logic
}
If you receive a new/different sort parameter you save it into session. Then you try to load existing parameter from session, if you dont have any value stored, you get a default value.

PetaPoco complex types posting to controller

As per a question that I asked yesterday I was trying to find a way to dynamically create more text boxes and have those map to my view's model so upon post to the server it will grab all the dynamically(js) generated text boxes and post that to an object such as a List.
To give an example of this confusing question:
I have a textbox that is labeled "Primary Contact" and the ticket creator can enter the contacts name and phone number into this box. What I want to do essentially is, switch this to three text boxes. One for Name, Email and PhoneNumber instead of one box. Then I will create some javascript that will dynamically create three more boxes to add another contact to this List collection. Then when the user submits the form to modify or create the ticket it passes this collection inside the model to the controller. However with petapoco it is a little confusing. Let me show you the controller:
[HttpPost]
public ActionResult ModifyTicket(Ticket model)
{
string userString = User.Identity.Name.Replace("ONHOLD\\", "");
if (ModelState.IsValid)
{
model.CreatedDate = DateTime.Now;
model.LastUpdateBy = Util.GetEmployeeIdByName(userString);
model.LastUpdate = DateTime.Now;
model.IsComplete = false;
model.ClientString = Util.GetClientNameById(model.ClientId);
model.LocationString = Util.GetLocationNameById(model.LocationId);
model.Update();
SuccessMessage = "You have successfully updated ticket number: " + model.TicketId + " for the following client: " + model.ClientString + ".";
return RedirectToAction("Index");
}
ErrorMessage = "Woops! Something went wrong, please check back in a few moments, if the problem persists please contact development.";
return RedirectToAction("Index");
}
The simple answer to this would be that my database model would contain a List object for this exact reason. However, I am using PetaPoco and I'm not entirely sure how it would be done. I could manually add in a collection to my Database model but when I regenerate my model based on any database schema changes I will lose any changes I've made to the file.
I am also using a partial class that my view uses for validation using DataAnnotations. However this class is identical to the database model it just contains DataAnnotations to provide client-side validation.
If anyone understands what I'm trying to accomplish I would be more than happyto provide more information to clarify any missing pieces. I just need a resolution to this as I can't find a solid way to go about resolving this issue!
Not entirely sure what you mean but it's easy to model bind from/to a list with MVC as you may already know. As for saving a deep object like this I'd use the [Ignore] attribute on the Ticket.List so it isn't persisted and handle it separately. I'd load the Contacts in separately from the Ticket object then manually add them to the Ticket object, alternatively use a join query and try the one-to-many approach to load it all in one go.
I think you're expecting Petapoco to update all in one? This won't happen you'll need to break it up. Hard to say from what you've written so far. There won't be a long list of contacts (from the sounds of it) so just insert or update them one by one.
Well that might help, or might not.

How to create multiple domain objects from a GSP page

I have a Person class with two properties: name and address. I want to build a GSP page which allows for 10 users to be created at one time. This is how I'm implementing it and was wondering if there is a better way:
First, make 20 text boxes in the GSP page - 10 with someperson.name and 10 with someperson.address field names (make these in a loop or code them all individually, doesn't matter).
Second, process the submitted data in the controller. The someperson object has the submitted data, but in a not-so-nice structure ([name: ['Bob', 'John'], address: ['Address 1', 'Address 2']]), so I call transpose() on this to be able to access name, address pairs.
Then, build a list of Person objects using the pairs obtained from the previous step and validate/save them.
Finally, if validation fails (name cannot be null) then do something... don't know what yet! I'm thinking of passing the collection of Person objects to the GSP where they are iterated using a loop and if hasErrors then show them... Don't know how to highlight the fields which failed validation...
So, is there a better way (I should probably ask WHAT IS the better way)?
You should use Grails' data-binding support by declaring a command object like this
class PersonCommand {
List<Person> people = []
}
If you construct your form so that the request parameters are named like this:
person[0].name=bob
person[0].address=england
person[1].name=john
person[1].address=ireland
The data will be automatically bound to the personCommand argument of this controller action
class MyController {
def savePeople = {PersonCommand personCommand->
}
}
If you call personCommand.validate() it might in turn call validate() on each Person in people (I'm not sure). If it doesn't you can do this yourself by calling
boolean allPersonsValid = personCommand.people.every {it.validate()}
At this point you'll know whether all Person instances are valid. If they are not, you should pass the PersonCommand back to the GSP and you can use the Grails tags:
<g:eachError>
<g:hasErrors>
<g:renderErrors>
to highlight the fields in errors. If you're not exactly sure how to use these tags to do the highlight, I suggest you run grails generate-all for a domain class and look at the GSP code it generates.

asp.net mvc: What is the correct way to return html from controller to refresh select list?

I am new to ASP.NET MVC, particularly ajax operations. I have a form with a jquery dialog for adding items to a drop-down list. This posts to the controller action.
If nothing (ie void method) is returned from the Controller Action the page returns having updated the database, but obviously there no chnage to the form. What would be the best practice in updating the drop down list with the added id/value and selecting the item.
I think my options are:
1) Construct and return the html manually that makes up the new <select> tag
[this would be easy enough and work, but seems like I am missing something]
2) Use some kind of "helper" to construct the new html
[This seems to make sense]
3) Only return the id/value and add this to the list and select the item
[This seems like an overkill considering the item needs to be placed in the correct order etc]
4) Use some kind of Partial View
[Does this mean creating additional forms within ascx controls? not sure how this would effect submitting the main form its on? Also unless this is reusable by passing in parameters(not sure how thats done) maybe 2 is the option?]
UPDATE:
Having looked around a bit, it seems that generating html withing the controller is not a good idea. I have seen other posts that render partialviews to strings which I guess is what I need and separates concerns (since the html bits are in the ascx). Any comments on whether that is good practice.
look at the ContentResult you can specify the mime type of what you return (text/html)
You could alternatively make a control that take a IEnumerable of whatever you put in the selectlist, and build it using the view engine. That way you keep the formatting of the html (in this case a list of options) into a view, and not in your code.
<%# Control Language="C#"Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Article>>"%>
<%foreach (var article in Model){%>
<option><%:article.Title %></option>
<%} %>
I think I would go for that second one
From what I understood, the jQuery dialog contains a form that, when submitted, will post to an action which updates the database with some information. You want to get the newly added database information and update the same form that was used to trigger the database update.
If that is the case, then I think the best clean and logical option is to return JSON serialization of the items to be put in the drop down right after you update the database. Then, using jQuery, you would clear the drop down and append option tags into it.
You can also write a new, seperate action that returns the JSON serialization of the database objects you need. You would have jQuery call another post to this action as a callback to your first ajax post (the one used to update the database).
Here is a quick snippet
public ActionResult UpdateDatabase(string something)
{
/// update the database
IEnumerable<Items> items = getItemsFromDatabase(); // or w/e
var vals = items.Select(x=> new { value = x.ID, text = x.Name }); // something similar
return Json(vals);
}
Personally, I would write a separate function that returns JSON. This ensure separation of concerns, and gives me a function I can use in many different places.
Returning a JsonResult with all the items is the most versatile and least-bandwidth intensive solution as long as you are happy to iterate through the list in jQuery and update your drop-down list.
Using a partial view is nice for HTML that you can .load(...) directly into your select, but less versatile.
I would go with the JsonResult.
In your Controller:
public JsonResult UpdateItem(string sItem)
{
// 1. Insert new item into database if not exist...
// {update code here}
// 2. retrieve items from database:
IEnumerable<Item> Items = GetItems();
// 3. return enumerable list in JSON format:
return new JsonResult{ Data = new {Items = Items, Result = "OK" }};
}
On client-side:
Iterate through Items array and add the items to your list.

Dynamic (Runtime Generated) Forms in ASP.NET MVC [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
This is a general design question: How would you implement a dynamic (runtime generated) form in ASP.NET MVC?
Here's the situation:
A site admin can define form parameters (fields, type of fields, validation) with a GUI (MVC view).
As needed, the runtime generates the form for the end user based on the admin configuration. I'm assuming that all of this logic would reside in the controller - or perhaps extension methods, action filters or something like that.
End user fills out the form, hits submit, information is captured in database.
The customization does not need to support nested controls, 3rd party controls and so forth, but I suspect a very elegant design would allow for that. Mostly, I just need the admin to be able to specify additional fields as textboxes, checkboxes, radio buttons and comboboxes. I will also need the application to allocate a space for this data to be saved in the db, but I believe I have that part figured out.
Thanks for the help.
I had the same need in a recent project. I created a class library for this. I just released a new version of the library.
Maybe it can help you:
ASP.NET MVC Dynamic Forms
You can do this very easily using my FormFactory library.
By default it reflects against a view model to produce a PropertyVm[] array, but you can also create the properties programatically, so you could load settings from a database then create PropertyVm.
This is a snippet from a Linqpad script.
```
//import-package FormFactory
//import-package FormFactory.RazorGenerator
void Main()
{
var properties = new[]{
new PropertyVm(typeof(string), "username"){
DisplayName = "Username",
NotOptional = true,
},
new PropertyVm(typeof(string), "password"){
DisplayName = "Password",
NotOptional = true,
GetCustomAttributes = () => new object[]{ new DataTypeAttribute(DataType.Password) }
}
};
var html = FormFactory.RazorEngine.PropertyRenderExtension.Render(properties, new FormFactory.RazorEngine.RazorTemplateHtmlHelper());
Util.RawHtml(html.ToEncodedString()).Dump(); //Renders html for a username and password field.
}
```
Theres a demo site with examples of the various features you can set up (e.g. nested collections, autocomplete, datepickers etc.)
Another option is to have a very loosely coupled database schema.
//this will contain all the fields and types that the admin user sets
**ApplicationFields**
FieldName
FieldType
...
//these are all the values that have some mapping to a ParentObjectID
**FormValues**
ParentObjectID
FieldName
FieldValue
When you submit your runtime generated View (from ApplicationFields) then just loop through your FormCollection and try and set it on the ParentObject you need to update.
public ActionResult MyForm(FormCollection form)
{
//this is the main object that contains all the fields
var parentObject;
foreach (string key in form)
{
parentObject.SetValue(key, form[key]);
}
...
Then your parentObject might be something like this...
public partial class ParentObject
{
IList _FormValues;
public void SetValue(string key, string value)
{
//try and find if this value already exists
FormValue v = _FormValues.SingleOrDefault(k => k.Key == key);
//if it does just set it
if (v != null)
{
v.Value = value;
return;
}
//else this might be a new form field added and therefore create a new value
v = new FormValue
{
ParentObjectID = this.ID,
Key = key,
Value = value
};
_FormValues.Add(v);
}
}
One way to do this is to create your own ModelBinder which would be at the heart of your generated forms. A modelbinder is responsible for validating the ModelState and rebuilding the typed ViewDataModel (assuming your views are typed).
The DataAnnotations model binder could be a good reference for this what this custom modelbinder allows you to do is via Attributes on your ViewDataModel describe the attribute's validation (and hint at UI rendering). However this is all defined compile time but would be a great reference to start off writing a custom modelbinder.
In your case your model binder should get the validation for a field at runtime from an xml file/string.
If you have a route like:
routes.MapRoute(null, "Forms/{formName}/", new { action = "Index", controller = "Forms", formName = ""}),
Then you could locate the correct form xml in FormsController.Index(string formName) and pass it to the view.
The FormsModel should hold all the possible methods to get data I dont see any other way around this. The Xml could map to a function name (possibly even arguments) that you can invoke using reflection on the FormsModel to fill the ViewData or typed ViewDataModel with data.
The view for Form Index could generate a form from that xml through an HtmlHelper Extension that takes an XmlDocument.
Then when you (or asp.net mvc) binds your form to your ViewData your custom model binder is invoked it can inspect the current controller values to look for the formName and look up the corresponding xml that holds all the validation rules. The ModelBinder is then responsible for filling up ModelState with any runtime defined errors.
It's a hard task but when pulled off succesfully well worth it in my view :)
Update a better alternative to model data would be a very loose database schema as David Liddle suggests. I'd still go through the trouble of saving it as xml (or someother serialized format) and using that for generating the view and to hold validation rules for a custom ModelBinder so that you have more control on layout and validation of each field.
cottsak's answer is very attractive.
There are at least two client-side XForms engines. Here's one:
https://community.emc.com/community/edn/xmltech
I can't see huge advantages of generating XForms or any other "abstraction" over the HTML comparing with straight forward generation of HTML with "Web Forms 2.0" controls list for model like List<Tuple<Meta, Value>>. Note: on server side you in any case would be obligated to parse results manually to fit it to your structrures.
Searching for "next layer abstractions" is good for rapid development, but see, "generate code" (runtime or build-time) has its own specific. Usually the generating code of "lower layer" is the better solution than generating the "higher abstract layer" code.
So just go and wirte code that generate Web 2 Controls in #Foreach loop.

Resources