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)}}
|
{{#let (union (or @item.Tags (array)) (or @tags (array))) as |tags|}}
|
||||||
{{#if (has-block)}}
|
{{#if (gt tags.length 0)}}
|
||||||
{{yield
|
{{#if (has-block)}}
|
||||||
(component 'tag-list' item=item)
|
{{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}}
|
</dt>
|
||||||
<dl class="tag-list">
|
<dd data-test-tags>
|
||||||
<dt>
|
{{#each tags as |item|}}
|
||||||
<Tooltip>
|
<span>{{item}}</span>
|
||||||
Tags
|
{{/each}}
|
||||||
</Tooltip>
|
</dd>
|
||||||
</dt>
|
</dl>
|
||||||
<dd data-test-tags>
|
{{/if}}
|
||||||
{{#each item.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]'),
|
name: text('[data-test-service-name]'),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
page.tabs.tagsTab = {
|
||||||
|
tags: collection('.tag-list dd > span', {
|
||||||
|
name: text(),
|
||||||
|
}),
|
||||||
|
};
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue