Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/userGuide/syntax/cardstacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ Name | Type | Default | Description
tag | `String` | `null` | Tags of each card component.<br>Each unique tag should be seperated by a `,`.<br> Tags are added to the search field.
header | `String` | `null` | Header of each card component.<br> Supports the use of inline markdown elements.
keywords | `String` | `null` | Keywords of each card component.<br>Each unique keyword should be seperated by a `,`.<br> Keywords are added to the search field.
disable | `Boolean` | `false` | Disable card. <br> This removes visibility of the card and makes it unsearchable.
disabled | `Boolean` | `false` | Disable card. <br> This removes visibility of the card and makes it unsearchable.



Expand Down
62 changes: 62 additions & 0 deletions packages/vue-components/src/__tests__/CardStack.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,66 @@ describe('CardStack', () => {
await wrapper.vm.$nextTick();
expect(wrapper.element).toMatchSnapshot();
});

test('should have all tags checked by default on load', async () => {
const wrapper = mount(CardStack, {
slots: { default: CARDS_CUSTOMISATION },
global: DEFAULT_GLOBAL_MOUNT_OPTIONS,
});
await wrapper.vm.$nextTick();
const allTags = wrapper.vm.cardStackRef.tagMapping.map(key => key[0]);
expect(wrapper.vm.selectedTags).toEqual(expect.arrayContaining(allTags));
expect(wrapper.vm.allSelected).toBe(true);
});

test('toggleAllTags should unselect everything and then select everything', async () => {
const wrapper = mount(CardStack, {
slots: { default: CARDS_CUSTOMISATION },
global: DEFAULT_GLOBAL_MOUNT_OPTIONS,
});
await wrapper.vm.$nextTick();

// selected all initially
expect(wrapper.vm.allSelected).toBe(true);

// deselect everything
const selectAllBadge = wrapper.find('.bg-dark.tag-badge');
await selectAllBadge.trigger('click');
expect(wrapper.vm.selectedTags.length).toBe(0);
expect(wrapper.vm.allSelected).toBe(false);

// all cards should be hidden
const cards = wrapper.findAllComponents(Card);
cards.forEach((card) => {
if (card.props('tag') === 'Short') {
expect(card.vm.disableTag).toBe(true);
}
});

// select all again -> everything should be selected back
await selectAllBadge.trigger('click');
expect(wrapper.vm.allSelected).toBe(true);
expect(wrapper.vm.selectedTags.length).toBeGreaterThan(0);
});

test('Select All checkbox should sync with individual tag clicks', async () => {
const wrapper = mount(CardStack, {
slots: { default: CARDS_CUSTOMISATION },
global: DEFAULT_GLOBAL_MOUNT_OPTIONS,
});
await wrapper.vm.$nextTick();

// uncheck first tag
const firstTagBadge = wrapper.findAll('.tag-badge').at(1);
await firstTagBadge.trigger('click');

// select all should no longer be checked
expect(wrapper.vm.allSelected).toBe(false);
const selectAllIndicator = wrapper.find('.bg-dark.tag-badge .tag-indicator');
expect(selectAllIndicator.text()).not.toContain('✓');

// Check first tag -> select all should be checked again
await firstTagBadge.trigger('click');
expect(wrapper.vm.allSelected).toBe(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ exports[`CardStack markdown in header, content 1`] = `
type="text"
/>
</span>
<!--v-if-->


</div>
Expand Down Expand Up @@ -96,6 +97,18 @@ exports[`CardStack should not hide cards when no filter is provided 1`] = `
type="text"
/>
</span>
<span
class="badge bg-dark tag-badge"
>
Select All 
<span
class="badge bg-light text-dark tag-indicator"
>
<span>
</span>
</span>
</span>

<span
class="badge bg-primary tag-badge"
Expand All @@ -105,7 +118,7 @@ exports[`CardStack should not hide cards when no filter is provided 1`] = `
class="badge bg-light text-dark tag-indicator"
>
<span>
   
</span>
</span>
</span>
Expand Down Expand Up @@ -218,6 +231,7 @@ exports[`CardStack should not hide cards when no filter is provided 2`] = `
type="text"
/>
</span>
<!--v-if-->


</div>
Expand Down
41 changes: 38 additions & 3 deletions packages/vue-components/src/cardstack/CardStack.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@
/>
</template>
</span>
<span
v-if="cardStackRef.tagMapping.length > 0"
class="badge bg-dark tag-badge"
@click="toggleAllTags"
>
Select All&nbsp;
<span class="badge bg-light text-dark tag-indicator">
<span v-if="allSelected">✓</span>
<span v-else>&nbsp;&nbsp;&nbsp;</span>
</span>
</span>
<span
v-for="(key, index) in cardStackRef.tagMapping"
:key="index"
Expand Down Expand Up @@ -61,6 +72,20 @@ export default {
},
},
computed: {
allSelected() {
return this.selectedTags.length === this.cardStackRef.tagMapping.length;
},
},
watch: {
'cardStackRef.tagMapping': {
handler(newMapping) {
// Initialise the selectedTags with all tag names when loading for the first time
if (this.selectedTags.length === 0 && newMapping.length > 0) {
this.selectedTags = newMapping.map(key => key[0]);
}
},
immediate: true,
},
},
provide() {
return {
Expand Down Expand Up @@ -100,7 +125,7 @@ export default {
}

if (this.selectedTags.length === 0) {
this.showAllTags();
this.showAllTags(false);
} else {
this.cardStackRef.children.forEach((child) => {
if (child.$props.disabled) return;
Expand All @@ -111,16 +136,26 @@ export default {
});
}
},
showAllTags() {
showAllTags(showTag) {
this.cardStackRef.children.forEach((child) => {
if (child.$props.disabled) return;

child.$data.disableTag = false;
child.$data.disableTag = !showTag;
});
},
computeShowTag(tagName) {
return this.selectedTags.includes(tagName);
},
toggleAllTags() {
const allTags = this.cardStackRef.tagMapping.map(key => key[0]);
if (this.selectedTags.length === allTags.length) {
this.selectedTags = [];
this.showAllTags(false);
} else {
this.selectedTags = allTags;
this.showAllTags(true);
}
},
},
data() {
return {
Expand Down
Loading