I finished my first Custom Widget for MainUI - last thing to do is a time conversion.
I added the duration of the actual playing track, but this is shown in seconds, what is not very useful.
previously in my sitemap I converted this via a tiny javascript file while defining the item, but this is not recognized by the widget… so I guess I have to add the js to the line which loads the item state.
can someone help me out how this actually would look like?
the javascript “mmss.js” which converts the seconds is in the “transform” folder.
or do I have to figure out another way without the conversion script?
What type is the duration Item? If it’s a Number:Time you can use DateTime formatting on the Item’s State Description metadata to show hours:minutes:seconds (or what ever you prefer) and in your widget you’ll use .stateDescription instead of .state. Note that .stateDescrption only exists when the Item has a State Description metadata defined.
As an example here is the runtime of my UPS which is a Number:Time.
Yes because if it’s just a plain old number what I presented above won’t work. If you can convert it to a Number:Time that would probably be easiest as then you can use the state description as written above.
If not, you’ll need to create a JavaScript transform to do the operations to split the seconds out into hours:minutes:seconds (there are lots of examples on the forum). Then in the State Description metadata you’ll call the transformation just like you would do in a label on the sitemap.
JS(fromseconds.js):%s
Overall, the tl;dr is you can’t do this inline in the widget. You have to do it in the State Description metadata for the Item and then in your widget used the formatted state by calling .stateDescription instead of .state.
what I did:
changed the item file definition from Number to Number:Time
changed the items State Description via UI to JS(mmss.js):%s (the item itself is defined in a file)
changed .state to stateDescription in my yaml code
In the widgets you do have access to the dayjs libraries. If you build your duration seconds into a string that that dayjs can parse you then have a fairly full suite of formatting options in the widget.
And now that I look there I’ve told you wrong. It’s displayState, not stateDescription.
I don’t see anywhere that dayjs supports durations in which case the same work to divide out a number of seconds to populate a dayjs function call would be required to just generate the String directly.
There is a duration extension (Durations · Day.js), but it isn’t available in the widget editor, though perhaps that warrants a feature request in the long run.
You’re right absolutely right though, I was just thinking a quick and dirty couple of conversions and a partial iso string would be one option if the metadata route wasn’t satisfactory from some reason and this had to be done in the yaml.
As rich points out, this is a bit of a kludge and you’ll still have to do a little math and also fake an ISO formatted string. The dayjs library will parse a string that has a date ISO date format and then has many of the standard date display formatting options. So if your duration item is just in seconds it might look something like this:
The “2000-01-01T00:” at the front is just a dummy date to give the string the correct formatting, then you can use the Math.trunc method to get the minutes from your seconds value (in this case a randomly chosen 146 seconds) and conversely extract the seconds after that. The dayjs .format method would then output 2:26.
Rich’s method is more elegant and you should really only resort to this in one of two cases. In the first case you modify your transform to put the duration into the iso format because then you can skip right to dayjs(item state). If you keep the simple seconds duration string then you would have to substitute into that line above your call to the items object and (as that gets you a string) use Number to parse it. So the final line gets pretty convoluted:
The only other reason to go this way over Rich’s pattern would be if you want a different format in the item’s pattern for some other display elsewhere.
actually it doesn’t matter if the itemtype is Number or Number:Time for this to operate.
the problem that nothing was displayed was because of the wrong definition .stateDescription
instead of .displayState