[OH3] How to use transformation in expressions (custom-widgets)

Hi,

I’d like to apply a transformation on a DateTime item from inside a widget expression to reuse informations from a single item for different purposes without the overhead of creating multiple items and define different transformation patterns.

Anyone knows how this could work. Maybe @ysc :stuck_out_tongue: ?

Thx

You can’t…
But regarding your present use case access to a nicely initialized dayjs() instance would be nice. Especially with plugins like RelativeTime (https://day.js.org/docs/en/display/from-now). Day.js is already imported as a library for the charts.

2 Likes

Thats enough reason for me looking into it - thank you!

Did you succeed somehow?
Not completely sure about your use case, but it sounds similar … :wink:

I’m currently trying to highlight (colorize) timestamps from datetime Items within a oh-repeater when the timestamp is older than an hour/older than a day …

Recent attempt (which is NOT working):

  - component: oh-repeater
    config:
      for: i
      sourceType: itemsInGroup
      groupItem: =props.mainItem
      fetchMetadata: semantics,widgetOrder,uiSemantics
      filter: '(vars.detailsOn ? true :  ( loop.i.state < items["tAgeOneHour"].state )'
    slots:
      default:
        - component: oh-label-item
          config:
            icon: =props.icon
            iconColor: '=items[loop.i.name].state === "ON" || items[loop.i.name].state > 0 ? "green" : "gray"'
            footer: =loop.i.metadata.uiSemantics.config.preposition + loop.i.metadata.uiSemantics.config.location
            title: =loop.i.metadata.uiSemantics.config.equipment
            item: =loop.i.name

Which should filter the results to just those, which are “older than an hour”. Unfortunately, is brings all items in the group:

Hey @curlyel

just based on your question, it should work with something like this:

    - component: oh-repeater
      config:
        for: i
        sourceType: itemsInGroup
        groupItem: gLastUpdate
        filter: loop.i.state < dayjs().add(-1,"hour").format()
      slots:
        default:
          ...

Make sure, that you assign the group name to the ‘groupItem’ config prop.
You can adjust the dayjs expression to your liking then (List of available units).

Hope it helps

1 Like

Thanks Yannick for the pointing to dayjs.
I’ve changed my repeater list to show colored badges instead of the actual timestamps:

You both are the best!!!

It works - filtered by timed out heartbeat:

Unfiltered (full) list:

That’s the working code:

  - component: oh-repeater
    config:
      for: i
      sourceType: itemsInGroup
      groupItem: =props.mainItem
      fetchMetadata: semantics,widgetOrder,uiSemantics
      filter: '( loop.i.state < dayjs().add(-1,"hour").format() ) ? true : vars.detailsOn '
    slots:
      default:
        - component: oh-list-item
          config:
            icon: =props.icon
            iconColor: '=items[loop.i.name].state === "ON" || items[loop.i.name].state > 0 ? "green" : "gray"'
            footer: =loop.i.metadata.uiSemantics.config.preposition + loop.i.metadata.uiSemantics.config.location 
            title: =loop.i.metadata.uiSemantics.config.equipment
            item: =loop.i.name
            badge: =dayjs(loop.i.state).fromNow()
            badgeColor: '=dayjs(loop.i.state).fromNow().includes("Sek") ? "green" : dayjs(loop.i.state).fromNow().includes("Minu") ? "green" : dayjs(loop.i.state).fromNow().includes("Stun") ? "orange" : "red"'

Many thanks mates!

EDIT: Any idea for some sleeker code for:

badgeColor: '=dayjs(loop.i.state).fromNow().includes("Sek") ? "green" : dayjs(loop.i.state).fromNow().includes("Minu") ? "green" : dayjs(loop.i.state).fromNow().includes("Stun") ? "orange" : "red"'`

EDIT2:
Slightly better (but not that much ;-):

badgeColor: '=dayjs(loop.i.state).isAfter(dayjs().add(-1,"hour")) ? "green" : dayjs(loop.i.state).isAfter(dayjs().add(-1,"day")) ? "orange" : "red"'

:wink:

1 Like

This is more or less as good as it gets - You can save a few more chars with something like this:

badgeColor: =dayjs().diff(dayjs(items[loop.i.name].state),"h")<1?"green":dayjs().diff(dayjs(items[loop.i.name].state),"d")<1?"orange":"red"

//edit
Based on the best practice mentioned here by Yannick, I updated the above expression to use items[loop.i.name].state instead of loop.i.state

1 Like

really nice, by the way is it possible to sort them?

Andy

IIRC, Yannick said somewhere that the widgetOrder is considered by the oh-repeater. That’s why I have included it in my fetchMetadata:

  fetchMetadata: semantics,widgetOrder,uiSemantics

Admittedly, I haven’t really checked if it does have the intended effect.
I don’t have the widgetOrder metadata set to the above items yet but am still thinking how to do it by a script based e.g. on location and equipment name.

AND: Maybe, items in lists as above ARE sorted by their item label.
BUT: Since I show the equipment and location label instead of the actual items labels (which are always “Letzte Aktivität” for each in my case), we won’t notice that …

That may be the reason, why the list appears to be unsorted :wink:

1 Like

I made a quick check, and you’re right - you can manipulate the order with the widgetOrder metadata.

Yes, they are - I interpreted the question more towards the need for a custom sorting, which is possible with widgetOrder as I learned. :slight_smile:

Thanks for the clarification!

Welcome.
Happy giving something back :wink:

and how did you sort it by timed out heartbeat?

Not possible so far. That’s why I’ve filtered to the relevant (older than 1 hour).

ok thx it just looked like it would have been sorted since mine are currently not, that’s why I asked

Hi, great work and i successfully enriched the uiSemantics metadata for my Timestamp items that i created. They are showing in the widget but the format does not seem to be correct at my end. I created all lights and all batteries repeater widgets but here i am struggling. Can someone give me a hint what is wrong? Thank you.

EDIT: corrected working YAML and updated screenshot.

image

uid: all_timestamps
tags:
  - in test
  - in use
props:
  parameters:
    - description: A text prop
      label: Prop 1
      name: prop1
      required: false
      type: TEXT
    - description: Icon to show
      label: the icon
      name: icon
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: The Group Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 20, 2021, 1:10:26 AM
component: f7-card
config:
  title: =props.prop1
slots:
  default:
    - component: oh-list
      slots:
        default:
          - component: oh-repeater
            config:
              fragment: true
              for: i
              sourceType: itemsInGroup
              groupItem: =props.item
              fetchMetadata: semantics, widgetOrder, uiSemantics
              filter: '( loop.i.state < dayjs().add(-25,"minutes").format() ) ? true : vars.detailsOn '
            slots:
              default:
                - component: oh-list-item
                  config:
                    icon: =props.icon
                    iconColor: '=items[loop.i.name].state === "ON" || items[loop.i.name].state > 0 ? "green" : "gray"'
                    footer: =loop.i.metadata.uiSemantics.config.preposition.label + loop.i.metadata.uiSemantics.config.location.label
                    title: =loop.i.metadata.uiSemantics.config.equipment.label
                    item: =loop.i.name
                    badge: =dayjs(loop.i.state).fromNow()
                    badgeColor: =dayjs().diff(dayjs(items[loop.i.name].state),"h")<1?"green":dayjs().diff(dayjs(items[loop.i.name].state),"d")<1?"orange":"red"

i solved it. was a formatting issue with slots: default not properly below each other. code is ok. YAML formatter did not report an error.

Did you manage to list the items in order? I’m trying to make it appear in order from newest to oldest, but I don’t know what documentation to use, thanks for this great post!

hi, i was not searching for a solution to sort yet and this widget is still on a test page in my openHAB, but i have seen some discussion about the sort order above in this thread that you can use meta data to achieve this.

thank you, I continue to search, and keep you informed