ui: [BUGFIX] De-duplicate Tag rendering (#10186)
* Add some tests for duplicated and non-duplicated tags * Ensure tags get de-duped and add docs * Update docs to include info on the recursive-ness
This commit is contained in:
parent
b4c5a8c028
commit
79f59f76e2
|
@ -0,0 +1,3 @@
|
|||
```release-note:bug
|
||||
ui: De-duplicate tags in rendered tag listings
|
||||
```
|
|
@ -0,0 +1,75 @@
|
|||
# TagList
|
||||
|
||||
Template only component for rendering a list of tags. You can pass either/or/and `@tags=tags` and/or `@item=item` (`item` must have a `Tags` property) for ease. If you pass both they are merged and de-duped.
|
||||
|
||||
Tags are de-duplicated when rendered.
|
||||
|
||||
```hbs preview-template
|
||||
<TagList
|
||||
@item={{hash
|
||||
Tags=(array 'tag' 'tag' 'another-tag')
|
||||
}}
|
||||
/>
|
||||
|
||||
<hr />
|
||||
|
||||
<TagList
|
||||
@tags={{array 'another-tag' 'tag' 'tag'}}
|
||||
/>
|
||||
```
|
||||
|
||||
`TagList` is also a recursive component, which can currently be used for when you need to wrap the `TagList` component in more DOM, but you only want that DOM to appear if your array of tags is non-empty.
|
||||
|
||||
|
||||
```hbs preview-template
|
||||
<figure>
|
||||
<figcaption>
|
||||
This list has tags therefore the red border div will also be rendered.
|
||||
</figcaption>
|
||||
|
||||
<TagList
|
||||
@item={{hash
|
||||
Tags=(array 'tag' 'tag' 'another-tag')
|
||||
}}
|
||||
as |Tags|>
|
||||
<div style="border: 1px solid red;">
|
||||
<Tags />
|
||||
</div>
|
||||
</TagList>
|
||||
|
||||
</figure>
|
||||
|
||||
<hr />
|
||||
|
||||
<figure>
|
||||
<figcaption>
|
||||
This list has no tags therefore the tags _and_ red border div will **not** be rendered.
|
||||
</figcaption>
|
||||
|
||||
<TagList
|
||||
@item={{hash
|
||||
Tags=(array)
|
||||
}}
|
||||
as |Tags|>
|
||||
<div style="border: 1px solid red;">
|
||||
<Tags />
|
||||
</div>
|
||||
</TagList>
|
||||
|
||||
</figure>
|
||||
```
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `item` | `Object` | | Object with a `Tags` property equalling an array of string tags |
|
||||
| `tags` | `Array` | | An array of string tags |
|
||||
|
||||
## Yields
|
||||
|
||||
When used as a block level component the `TagList` yields itself, see above example for usage.
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `Tags` | `Array` | The resulting collection of data after searching/sorting/filtering |
|
|
@ -1,20 +1,29 @@
|
|||
{{#if (gt item.Tags.length 0)}}
|
||||
{{#if (has-block)}}
|
||||
{{yield
|
||||
(component 'tag-list' item=item)
|
||||
{{#let (union (or @item.Tags (array)) (or @tags (array))) as |tags|}}
|
||||
{{#if (gt tags.length 0)}}
|
||||
{{#if (has-block)}}
|
||||
{{yield
|
||||
(component 'tag-list' item=@item)
|
||||
}}
|
||||
{{else}}
|
||||
<dl
|
||||
class="tag-list"
|
||||
...attributes
|
||||
>
|
||||
<dt
|
||||
{{tooltip}}
|
||||
>
|
||||
{{t "components.tag-list.title"
|
||||
default=(array
|
||||
"common.consul.tags"
|
||||
)
|
||||
}}
|
||||
{{else}}
|
||||
<dl class="tag-list">
|
||||
<dt>
|
||||
<Tooltip>
|
||||
Tags
|
||||
</Tooltip>
|
||||
</dt>
|
||||
<dd data-test-tags>
|
||||
{{#each item.Tags as |item|}}
|
||||
<span>{{item}}</span>
|
||||
{{/each}}
|
||||
</dd>
|
||||
</dl>
|
||||
</dt>
|
||||
<dd data-test-tags>
|
||||
{{#each tags as |item|}}
|
||||
<span>{{item}}</span>
|
||||
{{/each}}
|
||||
</dd>
|
||||
</dl>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
@setupApplicationTest
|
||||
Feature: dc / services / show / tags
|
||||
Background:
|
||||
Given 1 datacenter model with the value "dc1"
|
||||
And 1 node models
|
||||
Scenario: A service with multiple tags
|
||||
Given 1 service model from yaml
|
||||
---
|
||||
- Service:
|
||||
Name: service
|
||||
Kind: ~
|
||||
Tags:
|
||||
- tag
|
||||
- tag1
|
||||
- tag2
|
||||
---
|
||||
When I visit the service page for yaml
|
||||
---
|
||||
dc: dc1
|
||||
service: service
|
||||
---
|
||||
And I see tags on the tabs
|
||||
When I click tags on the tabs
|
||||
And I see tagsIsSelected on the tabs
|
||||
And I see 3 tag models on the tabs.tagsTab component
|
||||
Scenario: A service with multiple duplicated tags
|
||||
Given 1 service model from yaml
|
||||
---
|
||||
- Service:
|
||||
Name: service
|
||||
Kind: ~
|
||||
Tags:
|
||||
- tag1
|
||||
- tag2
|
||||
- tag
|
||||
- tag
|
||||
- tag1
|
||||
- tag2
|
||||
---
|
||||
When I visit the service page for yaml
|
||||
---
|
||||
dc: dc1
|
||||
service: service
|
||||
---
|
||||
And I see tags on the tabs
|
||||
When I click tags on the tabs
|
||||
And I see tagsIsSelected on the tabs
|
||||
And I see 3 tag models on the tabs.tagsTab component
|
|
@ -0,0 +1,10 @@
|
|||
import steps from '../../../steps';
|
||||
|
||||
// step definitions that are shared between features should be moved to the
|
||||
// tests/acceptance/steps/steps.js file
|
||||
|
||||
export default function(assert) {
|
||||
return steps(assert).then('I should find a file', function() {
|
||||
assert.ok(true, this.step);
|
||||
});
|
||||
}
|
|
@ -36,5 +36,10 @@ export default function(visitable, clickable, attribute, collection, text, inten
|
|||
name: text('[data-test-service-name]'),
|
||||
}),
|
||||
};
|
||||
page.tabs.tagsTab = {
|
||||
tags: collection('.tag-list dd > span', {
|
||||
name: text(),
|
||||
}),
|
||||
};
|
||||
return page;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue