add rulesWithTags to oh-repeater (#1724)

fixes #1721 Add Scenes option to oh-repeater component

This PR adds the possibility to iterate over a list of rules queried via
a tag.

For example it allows to create a list of Scenes via the oh-repeater by
using the rulesTag = Scene and trigger the rule via a oh-button.

Example

```
slots:
  default:
    - component: oh-list
      slots:
        default:
          - component: oh-repeater
            config:
              for: scene
              sourceType: rulesWithTags
              ruleTags: Scene
            slots:
              default:
                - component: oh-button
                  config:
                    action: rule
                    actionRule: =loop.scene.uid
                    text: =loop.scene.name
```

--
Signed-off-by: Stefan Höhn <mail@stefanhoehn.com>
pull/1727/head
stefan-hoehn 2023-02-21 19:58:02 +01:00 committed by GitHub
parent de0e823488
commit b3ca6b2796
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 17 additions and 3 deletions

View File

@ -44,6 +44,7 @@ Iterate over an array and repeat the children components in the default slot
<PropOption value="itemsWithTags" label="Items with tags in the &quot;itemTags&quot; parameter" /> <PropOption value="itemsWithTags" label="Items with tags in the &quot;itemTags&quot; parameter" />
<PropOption value="itemStateOptions" label="State options of the item specified in &quot;itemOptions&quot;" /> <PropOption value="itemStateOptions" label="State options of the item specified in &quot;itemOptions&quot;" />
<PropOption value="itemCommandOptions" label="Command options of the item specified in &quot;itemOptions&quot;" /> <PropOption value="itemCommandOptions" label="Command options of the item specified in &quot;itemOptions&quot;" />
<PropOption value="rulesWithTags" label="Rules with tags in the &quot;ruleTags&quot; parameter" />
</PropOptions> </PropOptions>
</PropBlock> </PropBlock>
<PropBlock type="TEXT" name="in" label="Source array"> <PropBlock type="TEXT" name="in" label="Source array">
@ -76,6 +77,11 @@ Iterate over an array and repeat the children components in the default slot
Iterate over items with the given tags (comma-separated, for "itemsWithTags" source type) Iterate over items with the given tags (comma-separated, for "itemsWithTags" source type)
</PropDescription> </PropDescription>
</PropBlock> </PropBlock>
<PropBlock type="TEXT" name="ruleTags" label="Rule Tags">
<PropDescription>
Iterate over rules with the given tags (comma-separated, for "rulesWithTags" source type)
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="itemOptions" label="Item with Options"> <PropBlock type="TEXT" name="itemOptions" label="Item with Options">
<PropDescription> <PropDescription>
Iterate over the state options or command options of this item (for "itemStateOptions" or "itemCommandOptions" source type) Iterate over the state options or command options of this item (for "itemStateOptions" or "itemCommandOptions" source type)

View File

@ -10,7 +10,8 @@ export default () => [
{ value: 'itemsInGroup', label: 'Member of the group defined in the "groupItem" parameter' }, { value: 'itemsInGroup', label: 'Member of the group defined in the "groupItem" parameter' },
{ value: 'itemsWithTags', label: 'Items with tags in the "itemTags" parameter' }, { value: 'itemsWithTags', label: 'Items with tags in the "itemTags" parameter' },
{ value: 'itemStateOptions', label: 'State options of the item specified in "itemOptions"' }, { value: 'itemStateOptions', label: 'State options of the item specified in "itemOptions"' },
{ value: 'itemCommandOptions', label: 'Command options of the item specified in "itemOptions"' } { value: 'itemCommandOptions', label: 'Command options of the item specified in "itemOptions"' },
{ value: 'rulesWithTags', label: 'Rules with tags in the "ruleTags" parameter' }
]), ]),
pt('in', 'Source array', 'Source array (for "array" source type)'), pt('in', 'Source array', 'Source array (for "array" source type)'),
pn('rangeStart', 'Range Start', 'Start of range (for "range" source type)'), pn('rangeStart', 'Range Start', 'Start of range (for "range" source type)'),
@ -18,6 +19,7 @@ export default () => [
pn('rangeStep', 'Range Step', 'Step of range (for "range" source type)'), pn('rangeStep', 'Range Step', 'Step of range (for "range" source type)'),
pi('groupItem', 'Group Item', 'Group item to whose members will be iterated (for "itemsInGroup" source type)'), pi('groupItem', 'Group Item', 'Group item to whose members will be iterated (for "itemsInGroup" source type)'),
pt('itemTags', 'Item Tags', 'Iterate over items with the given tags (comma-separated, for "itemsWithTags" source type)'), pt('itemTags', 'Item Tags', 'Iterate over items with the given tags (comma-separated, for "itemsWithTags" source type)'),
pt('ruleTags', 'Rule Tags', 'Iterate over rules with the given tags (comma-separated, for "rulesWithTags" source type)'),
pt('itemOptions', 'Item with Options', 'Iterate over the state options or command options of this item (for "itemStateOptions" or "itemCommandOptions" source type)'), pt('itemOptions', 'Item with Options', 'Iterate over the state options or command options of this item (for "itemStateOptions" or "itemCommandOptions" source type)'),
pt('fetchMetadata', 'Fetch Item Metadata Namespaces', 'Fetch the metadata from these namespaces (for "itemsInGroup" and "itemsWithTags" source types)'), pt('fetchMetadata', 'Fetch Item Metadata Namespaces', 'Fetch the metadata from these namespaces (for "itemsInGroup" and "itemsWithTags" source types)'),
pt('filter', 'Filter expression', 'Specify an expression WITHOUT THE = PREFIX to filter the resulting array'), pt('filter', 'Filter expression', 'Specify an expression WITHOUT THE = PREFIX to filter the resulting array'),

View File

@ -13,7 +13,7 @@
<script> <script>
import mixin from '../widget-mixin' import mixin from '../widget-mixin'
import { OhRepeaterDefinition } from '@/assets/definitions/widgets/system' import { OhRepeaterDefinition } from '@/assets/definitions/widgets/system'
import { compareItems } from '@/components/widgets/widget-order' import { compareItems, compareRules } from '@/components/widgets/widget-order'
import { Fragment } from 'vue-fragment' import { Fragment } from 'vue-fragment'
export default { export default {
@ -76,13 +76,15 @@ export default {
const step = this.config.rangeStep || 1 const step = this.config.rangeStep || 1
return Promise.resolve(Array(Math.ceil((stop + 1 - start) / step)).fill(start).map((x, y) => x + y * step)) return Promise.resolve(Array(Math.ceil((stop + 1 - start) / step)).fill(start).map((x, y) => x + y * step))
} else if (this.config.sourceType === 'itemsWithTags' && this.config.itemTags) { } else if (this.config.sourceType === 'itemsWithTags' && this.config.itemTags) {
return this.$oh.api.get('/rest/items?metadata=' + this.config.fetchMetadata + '&tags=' + this.config.itemTags).then((d) => d.sort(compareItems)) return this.$oh.api.get('/rest/items?metadata=' + this.config.fetchMetadata + '&tags=' + this.config.itemTags).then((d) => Promise.resolve(d.sort(compareItems)))
} else if (this.config.sourceType === 'itemsInGroup') { } else if (this.config.sourceType === 'itemsInGroup') {
return this.$oh.api.get('/rest/items/' + this.config.groupItem + '?metadata=' + this.config.fetchMetadata + '&tags=' + this.config.itemTags).then((i) => Promise.resolve(i.members.sort(compareItems))) return this.$oh.api.get('/rest/items/' + this.config.groupItem + '?metadata=' + this.config.fetchMetadata + '&tags=' + this.config.itemTags).then((i) => Promise.resolve(i.members.sort(compareItems)))
} else if (this.config.sourceType === 'itemStateOptions') { } else if (this.config.sourceType === 'itemStateOptions') {
return this.$oh.api.get('/rest/items/' + this.config.itemOptions).then((i) => Promise.resolve((i.stateDescription) ? i.stateDescription.options : [])) return this.$oh.api.get('/rest/items/' + this.config.itemOptions).then((i) => Promise.resolve((i.stateDescription) ? i.stateDescription.options : []))
} else if (this.config.sourceType === 'itemCommandOptions') { } else if (this.config.sourceType === 'itemCommandOptions') {
return this.$oh.api.get('/rest/items/' + this.config.itemOptions).then((i) => Promise.resolve((i.commandDescription) ? i.commandDescription.commandOptions : [])) return this.$oh.api.get('/rest/items/' + this.config.itemOptions).then((i) => Promise.resolve((i.commandDescription) ? i.commandDescription.commandOptions : []))
} else if (this.config.sourceType === 'rulesWithTags' && this.config.ruleTags) {
return this.$oh.api.get('/rest/rules?summary=true' + '&tags=' + this.config.ruleTags).then((r) => Promise.resolve(r.sort(compareRules)))
} else { } else {
return Promise.resolve(this.config.in) return Promise.resolve(this.config.in)
} }

View File

@ -50,3 +50,7 @@ export function compareParents (i1, i2) {
} }
return modelOrder return modelOrder
} }
export function compareRules (r1, r2) {
return r1.name.localeCompare(r2.name)
}