Commit 4b7741ea authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'winh-epic-tree-form-slot-switch' into 'master'

Use SlotSwitch component for epics tree forms

See merge request gitlab-org/gitlab!17608
parents 9ab20185 b6a89d6b
<script>
/**
* Allows to toggle slots based on an array of slot names.
*/
export default {
name: 'SlotSwitch',
props: {
activeSlotNames: {
type: Array,
required: true,
},
tagName: {
type: String,
required: false,
default: 'div',
},
},
computed: {
allSlotNames() {
return Object.keys(this.$slots);
},
},
};
</script>
<template>
<component :is="tagName">
<template v-for="slotName in allSlotNames">
<slot v-if="activeSlotNames.includes(slotName)" :name="slotName"></slot>
</template>
</component>
</template>
......@@ -5,6 +5,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import { issuableTypesMap } from 'ee/related_issues/constants';
import SlotSwitch from '~/vue_shared/components/slot_switch.vue';
import AddItemForm from 'ee/related_issues/components/add_issuable_form.vue';
import CreateEpicForm from './create_epic_form.vue';
import CreateIssueForm from './create_issue_form.vue';
......@@ -16,8 +17,15 @@ import RelatedItemsTreeBody from './related_items_tree_body.vue';
import { OVERFLOW_AFTER } from '../constants';
const FORM_SLOTS = {
addItem: 'addItem',
createEpic: 'createEpic',
createIssue: 'createIssue',
};
export default {
OVERFLOW_AFTER,
FORM_SLOTS,
components: {
GlLoadingIcon,
RelatedItemsTreeHeader,
......@@ -27,6 +35,7 @@ export default {
TreeItemRemoveModal,
CreateIssueForm,
IssueActionsSplitButton,
SlotSwitch,
},
data() {
return {
......@@ -57,6 +66,21 @@ export default {
createIssueEnabled() {
return gon.features && gon.features.epicNewIssue;
},
visibleForm() {
if (this.showAddItemForm) {
return FORM_SLOTS.addItem;
}
if (this.showCreateEpicForm) {
return FORM_SLOTS.createEpic;
}
if (this.isCreateIssueFormVisible) {
return FORM_SLOTS.createIssue;
}
return null;
},
},
mounted() {
this.fetchItems({
......@@ -144,13 +168,14 @@ export default {
@showCreateIssueForm="showCreateIssueForm"
/>
</related-items-tree-header>
<div
v-if="showAddItemForm || showCreateEpicForm || isCreateIssueFormVisible"
<slot-switch
v-if="visibleForm"
:active-slot-names="[visibleForm]"
class="card-body add-item-form-container"
:class="{ 'border-bottom-0': itemsFetchResultEmpty }"
>
<add-item-form
v-if="showAddItemForm"
:slot="$options.FORM_SLOTS.addItem"
:issuable-type="issuableType"
:input-value="itemInputValue"
:is-submitting="itemAddInProgress"
......@@ -164,16 +189,16 @@ export default {
@addIssuableFormCancel="handleAddItemFormCancel"
/>
<create-epic-form
v-if="showCreateEpicForm"
:slot="$options.FORM_SLOTS.createEpic"
:is-submitting="itemCreateInProgress"
@createEpicFormSubmit="handleCreateEpicFormSubmit"
@createEpicFormCancel="handleCreateEpicFormCancel"
/>
<create-issue-form
v-if="isCreateIssueFormVisible && !showAddItemForm && !showCreateEpicForm"
:slot="$options.FORM_SLOTS.createIssue"
@cancel="isCreateIssueFormVisible = false"
/>
</div>
</slot-switch>
<related-items-tree-body
v-if="!itemsFetchResultEmpty"
:parent-item="parentItem"
......
import { shallowMount } from '@vue/test-utils';
import SlotSwitch from '~/vue_shared/components/slot_switch';
describe('SlotSwitch', () => {
const slots = {
first: '<a>AGP</a>',
second: '<p>PCI</p>',
};
let wrapper;
const createComponent = propsData => {
wrapper = shallowMount(SlotSwitch, {
propsData,
slots,
sync: false,
});
};
const getChildrenHtml = () => wrapper.findAll('* *').wrappers.map(c => c.html());
afterEach(() => {
if (wrapper) {
wrapper.destroy();
}
});
it('throws an error if activeSlotNames is missing', () => {
expect(createComponent).toThrow('[Vue warn]: Missing required prop: "activeSlotNames"');
});
it('renders no slots if activeSlotNames is empty', () => {
createComponent({
activeSlotNames: [],
});
expect(getChildrenHtml().length).toBe(0);
});
it('renders one slot if activeSlotNames contains single slot name', () => {
createComponent({
activeSlotNames: ['first'],
});
expect(getChildrenHtml()).toEqual([slots.first]);
});
it('renders multiple slots if activeSlotNames contains multiple slot names', () => {
createComponent({
activeSlotNames: Object.keys(slots),
});
expect(getChildrenHtml()).toEqual(Object.values(slots));
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment