openhab / openhab-webui

Web UIs of openHAB
Eclipse Public License 2.0
212 stars 232 forks source link

Add oh-context component #2533

Open JustinGeorgi opened 1 month ago

JustinGeorgi commented 1 month ago

Closes #2437, Closes #2148

This PR adds a new component, the oh-context. Similar to the repeater, this component is not rendered, but injects information into the widget at it's tree location.

The component allows for that addition of three things:

Here is are widgets that I have been using to test all these different capabilities:

Main widget:

uid: oh_context_demo
tags: []
props: {}
timestamp: Apr 13, 2024, 10:44:43 AM
component: oh-context
config:
  constants:
    fruitColor:
      apple: red
      banana: =(dayjs().hour() < 6)?'green':((dayjs().hour() < 14)?'yellow':'black')
      orange: orange
      blueberry: blue
  functions:
    nextFruit: >
      =(fr) =>
        (fr)
        ? (['apple','banana','orange','blueberry'])[(['blueberry','apple','banana','orange']).indexOf(fr)]
        : ('apple')
    a2o: =(str) => (str || 'no fruit').replaceAll('a','o')
  variables:
    currentFruit: apple
slots:
  default:
    - component: f7-card
      config:
        content: =`Global fruit is ${fn.a2o(vars.currentFruit)}`
        textColor: =const.fruitColor[vars.currentFruit] || 'deeppurple'
        title: Fn, Const, and Scoped Variables
      slots:
        default:
          - component: oh-context
            config:
              functions:
                a2o: =(str) => (str || 'no fruit').replaceAll('a','0')
              variables:
                currentFruit: orange
            slots:
              default:
                - component: f7-row
                  config:
                    style:
                      justify-content: space-around
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: currentFruit
                          actionVariableValue: =fn.nextFruit(vars.currentFruit)
                          text: =`Local fruit is ${fn.a2o(vars.currentFruit)}`
                      - component: oh-button
                        config:
                          text: =`Clear local fruit`
                          clearVariable: currentFruit
                - component: f7-row
                  config:
                    style:
                      justify-content: center
                  slots:
                    default:
                      - component: Label
                        config:
                          text: Input local fruit
                      - component: oh-input
                        config:
                          type: text
                          variable: currentFruit
                          placeholder: Please select a fruit
                          outline: true
                          style:
                            margin-left: 18px
                            color: var(--f7-text-color)
    - component: oh-input-card
      config:
        title: Input global fruit
        type: text
        variable: currentFruit
        placeholder: Please select a fruit
    - component: oh-context
      config:
        constants:
          fruitColor:
            apple: green
            banana: black
            orange: orange
            blueberry: pink
      slots:
        default:
          - component: f7-card
            config:
              content: =`Global fruit is ${fn.a2o(vars.currentFruit)}`
              textColor: =const.fruitColor[vars.currentFruit] || 'deeppurple'
              title: Fn, Const, and Scoped Variables
            slots:
              default:
                - component: f7-row
                  config:
                    style:
                      justify-content: space-around
                  slots:
                    default:
                      - component: f7-row
                        config:
                          style:
                            justify-content: space-around
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: variable
                                actionVariable: currentFruit
                                actionVariableValue: =fn.nextFruit(vars.currentFruit)
                                text: =`Global fruit is ${fn.a2o(vars.currentFruit)}`
                            - component: oh-button
                              config:
                                text: =`Clear global fruit`
                                clearVariable: currentFruit
                            - component: oh-button
                              config:
                                action: variable
                                actionVariable: widgetFruit
                                actionVariableValue: =fn.nextFruit(vars.widgetFruit || 'apple')
                                text: =`Global widget fruit is ${fn.a2o(vars.widgetFruit || 'apple')}`
    - component: widget:oh_context_widget
    - component: oh-list-card
      config:
        title: Variables
      slots:
        default:
          - component: oh-toggle-item
            config:
              title: Toggle
              variable: togVar
          - component: oh-slider-item
            config:
              title: Slider
              variable: slideVar
          - component: oh-stepper-item
            config:
              title: Stepper
              variable: stepVar
    - component: oh-context
      config:
        variables:
          togVar: true
          slideVar: 10
          stepVar: 10
      slots:
        default:
          - component: oh-list-card
            config:
              title: Local Variables
            slots:
              default:
                - component: oh-toggle-item
                  config:
                    title: Toggle
                    variable: togVar
                - component: oh-slider-item
                  config:
                    title: Slider
                    variable: slideVar
                - component: oh-stepper-item
                  config:
                    title: Stepper
                    variable: stepVar

image

Sub widget included in the main widget:

uid: oh_context_widget
tags: []
props:
  parameters: []
  parameterGroups: []
timestamp: Apr 13, 2024, 9:20:55 AM
component: f7-card
config:
  content: =`Global fruit is ${fn.a2o(vars.currentFruit)} but global widget fruit
    is ${fn.a2o(vars.widgetFruit || 'apple')}`
  textColor: =const.fruitColor[vars.widgetFruit || 'apple']
  title: Fn, Const, and Scoped Variables in Widgets
slots:
  default:
    - component: f7-row
      config:
        style:
          justify-content: space-around
      slots:
        default:
          - component: oh-button
            config:
              action: variable
              actionVariable: currentFruit
              actionVariableValue: =fn.nextFruit(vars.currentFruit)
              text: =`Global fruit is ${fn.a2o(vars.currentFruit)}`
          - component: oh-button
            config:
              action: variable
              actionVariable: widgetFruit
              actionVariableValue: =fn.nextFruit(vars.widgetFruit || 'apple')
              text: =`Global widget fruit is ${fn.a2o(vars.widgetFruit || 'apple')}`
          - component: oh-context
            config:
              variables:
                widgetFruit: blueberry
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: widgetFruit
                    actionVariableValue: =fn.nextFruit(vars.widgetFruit)
                    text: =`Local widget fruit is ${fn.a2o(vars.widgetFruit)}`

I've done some pretty extensive testing, but this has grown into a fairly large addition, so any and all additional testing is appreciated. There's no telling what I've missed.

relativeci[bot] commented 1 month ago

Job #1895: Bundle Size — 10.56MiB (+0.05%).

1e93504(current) vs 1232bf5 main#1894(baseline)

[!WARNING] Bundle contains 2 duplicate packages – View duplicate packages

Bundle metrics  Change 3 changes Regression 1 regression
                 Current
Job #1895
     Baseline
Job #1894
Regression  Initial JS 1.87MiB(+0.26%) 1.86MiB
No change  Initial CSS 607.87KiB 607.87KiB
Change  Cache Invalidation 18.71% 17.8%
No change  Chunks 223 223
No change  Assets 246 246
Change  Modules 2865(+0.14%) 2861
No change  Duplicate Modules 141 141
No change  Duplicate Code 1.73% 1.73%
No change  Packages 95 95
No change  Duplicate Packages 2 2

Bundle size by type  Change 1 change Regression 1 regression
|            |       Current
[Job #1895](https://app.relative-ci.com/projects/ZNG5hy4VeSJQVQcq1Kvu/jobs/1895-FrfAqdfXrvh3d6k1m7bR?utm_source=github&utm_medium=pr-report "View job report") |      Baseline
[Job #1894](https://app.relative-ci.com/projects/ZNG5hy4VeSJQVQcq1Kvu/jobs/1894-mOUNmtX5fZnD9w1U5wkM?utm_source=github&utm_medium=pr-report "View baseline job report") | |:--|--:|--:| | Regression  [JS](https://app.relative-ci.com/projects/ZNG5hy4VeSJQVQcq1Kvu/jobs/1895-FrfAqdfXrvh3d6k1m7bR/assets?ba=%7B%22filters%22%3A%22ft.CSS-0_ft.JS-1_ft.IMG-0_ft.MEDIA-0_ft.FONT-0_ft.HTML-0_ft.OTHER-0%22%7D "View JS assets") | `8.75MiB` (`+0.06%`) | `8.75MiB` | | Not changed  [CSS](https://app.relative-ci.com/projects/ZNG5hy4VeSJQVQcq1Kvu/jobs/1895-FrfAqdfXrvh3d6k1m7bR/assets?ba=%7B%22filters%22%3A%22ft.CSS-1_ft.JS-0_ft.IMG-0_ft.MEDIA-0_ft.FONT-0_ft.HTML-0_ft.OTHER-0%22%7D "View CSS assets") | `890.07KiB` | `890.07KiB` | | Not changed  [Fonts](https://app.relative-ci.com/projects/ZNG5hy4VeSJQVQcq1Kvu/jobs/1895-FrfAqdfXrvh3d6k1m7bR/assets?ba=%7B%22filters%22%3A%22ft.CSS-0_ft.JS-0_ft.IMG-0_ft.MEDIA-0_ft.FONT-1_ft.HTML-0_ft.OTHER-0%22%7D "View Fonts assets") | `526.1KiB` | `526.1KiB` | | Not changed  [Media](https://app.relative-ci.com/projects/ZNG5hy4VeSJQVQcq1Kvu/jobs/1895-FrfAqdfXrvh3d6k1m7bR/assets?ba=%7B%22filters%22%3A%22ft.CSS-0_ft.JS-0_ft.IMG-0_ft.MEDIA-1_ft.FONT-0_ft.HTML-0_ft.OTHER-0%22%7D "View Media assets") | `295.6KiB` | `295.6KiB` | | Not changed  [IMG](https://app.relative-ci.com/projects/ZNG5hy4VeSJQVQcq1Kvu/jobs/1895-FrfAqdfXrvh3d6k1m7bR/assets?ba=%7B%22filters%22%3A%22ft.CSS-0_ft.JS-0_ft.IMG-1_ft.MEDIA-0_ft.FONT-0_ft.HTML-0_ft.OTHER-0%22%7D "View IMG assets") | `140.74KiB` | `140.74KiB` | | Not changed  [HTML](https://app.relative-ci.com/projects/ZNG5hy4VeSJQVQcq1Kvu/jobs/1895-FrfAqdfXrvh3d6k1m7bR/assets?ba=%7B%22filters%22%3A%22ft.CSS-0_ft.JS-0_ft.IMG-0_ft.MEDIA-0_ft.FONT-0_ft.HTML-1_ft.OTHER-0%22%7D "View HTML assets") | `1.24KiB` | `1.24KiB` | | Not changed  [Other](https://app.relative-ci.com/projects/ZNG5hy4VeSJQVQcq1Kvu/jobs/1895-FrfAqdfXrvh3d6k1m7bR/assets?ba=%7B%22filters%22%3A%22ft.CSS-0_ft.JS-0_ft.IMG-0_ft.MEDIA-0_ft.FONT-0_ft.HTML-0_ft.OTHER-1%22%7D "View Other assets") | `871B` | `871B` |

View job #1895 reportView JustinGeorgi:jag-oh-context branch activityView project dashboard