I would expect your extension point config page to have to supply javascript to trigger refreshing the elements. I'm pretty sure Wicket can help with that.... ):
That frowny face is confidence inspiring… lol!
Any ideas what I should look into to get started figuring this out?
I hate spending time researching something that will have a short lifespan. Wicket is going away for v8.3.
Agreed
However It makes me feel better spending time on it that inevitably there will be industries like life sciences and other validated environments that get stuck on a validated 8.1 for a long time. Not the perfect answer, but better than it being a 100% waste of time
The key is to override getCalculatedFields()
on RecordActionTable
.
You'll want to create a (probably) ICalculatedField
, something like this:
calcFields.add(new ICalculatedField<>() {
@Override
public String getFieldvalue(DatasourceRecord record) {
Datasource ds = IgnitionGateway.get().getDatasourceManager().getDatasource(record.getName());
if (ds == null) {
return "null";
} else {
return WordUtils.capitalizeFully(ds.getStatus().toString());
}
}
@Override
public String getHeaderKey() {
return "Config.Database.Connections.Status";
}
});
RecordActionTable will automatically set up a one-second refresh polling task on page load for all calculated fields.
The keywords here make this much easier to look for! I think I found an example of it in the NodeRed Module on Github
I understand the snippet provided, but it looks like the calcFields
object isn't defined in your snippet, so I just added it as an empty array. Is there any reason I should be calling the super method for the calculated fields instead of doing it this way?
Example Code
@Override
protected List<ICalculatedField<DatabaseRecord>> getCalculatedFields() {
List<ICalculatedField<DatabaseRecord>> calcFields = new ArrayList<>();
calcFields.add(new ICalculatedField<DatabaseRecord>() {
@Override
public String getFieldvalue(DatabaseRecord record) {
// Get the time in milliseconds
long time = System.currentTimeMillis();
// Return the time as a string in the format "HH:mm:ss"
return String.format("%tT", time);
}
@Override
public String getHeaderKey() {
return "DatabaseRecord.Status.Name";
}
});
return calcFields;
}
Here is the output field from this:
With your code, the calculated field will get created each time the getter is called, instead of once per class initialization. It probably really doesn't matter, but it's a minor optimization to store the calculated fields in a field of the class, instead of creating them each time.
Also, be careful with terminology in Java/the JVM. Array has a very specific meaning; you made a list, which happens to be backed by an array internally, but if you said "I returned an array" from a method that returns a list, java programmers will be confused
The super method just returns null, so there's no reason to call it.
Also, this can sometimes cause issues if the receiver expects the list to be mutable, but you can create a list inline with the List.of()
static method, e.g something like this:
@Override
protected List<ICalculatedField<DatabaseRecord>> getCalculatedFields() {
var calcFields = List.of(
new ICalculatedField<DatabaseRecord>() {
@Override
public String getFieldvalue(DatabaseRecord record) {
// Get the time in milliseconds
long time = System.currentTimeMillis();
// Return the time as a string in the format "HH:mm:ss"
return String.format("%tT", time);
}
@Override
public String getHeaderKey() {
return "DatabaseRecord.Status.Name";
}
}
);
return calcFields;
}
This did exactly what I was looking for!
Is it possible through the sdk to create the "interactive" version of this the same way that the Database connection status page does?
Where you can click on the text "ERROR" to get a popup with the actual fault?
The status page is React, so I don't know if you can get exactly the same appearance. getFieldValue
is documented to allow any return value, so you could try return a Wicket component directly? No idea if that will work or not.