Merge branch 'kp-label-select-vue' into 'master'
Port Labels Select dropdown to Vue See merge request gitlab-org/gitlab-ce!17411
This commit is contained in:
commit
0fc80c54f0
|
@ -5,12 +5,12 @@ import Vue from 'vue';
|
|||
|
||||
import Flash from '~/flash';
|
||||
import { __ } from '~/locale';
|
||||
import '~/vue_shared/models/label';
|
||||
|
||||
import FilteredSearchBoards from './filtered_search_boards';
|
||||
import eventHub from './eventhub';
|
||||
import sidebarEventHub from '~/sidebar/event_hub'; // eslint-disable-line import/first
|
||||
import './models/issue';
|
||||
import './models/label';
|
||||
import './models/list';
|
||||
import './models/milestone';
|
||||
import './models/assignee';
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
<script>
|
||||
import LabelsSelect from '~/labels_select';
|
||||
import LoadingIcon from '../../loading_icon.vue';
|
||||
|
||||
import DropdownTitle from './dropdown_title.vue';
|
||||
import DropdownValue from './dropdown_value.vue';
|
||||
import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
|
||||
import DropdownButton from './dropdown_button.vue';
|
||||
import DropdownHiddenInput from './dropdown_hidden_input.vue';
|
||||
import DropdownHeader from './dropdown_header.vue';
|
||||
import DropdownSearchInput from './dropdown_search_input.vue';
|
||||
import DropdownFooter from './dropdown_footer.vue';
|
||||
import DropdownCreateLabel from './dropdown_create_label.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LoadingIcon,
|
||||
DropdownTitle,
|
||||
DropdownValue,
|
||||
DropdownValueCollapsed,
|
||||
DropdownButton,
|
||||
DropdownHiddenInput,
|
||||
DropdownHeader,
|
||||
DropdownSearchInput,
|
||||
DropdownFooter,
|
||||
DropdownCreateLabel,
|
||||
},
|
||||
props: {
|
||||
showCreate: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
abilityName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
context: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
namespace: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatePath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
labelsPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
labelsWebUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
labelFilterBasePath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
canEdit: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hiddenInputName() {
|
||||
return this.showCreate ? `${this.abilityName}[label_names][]` : 'label_id[]';
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.labelsDropdown = new LabelsSelect(this.$refs.dropdownButton, {
|
||||
handleClick: this.handleClick,
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
handleClick(label) {
|
||||
this.$emit('onLabelClick', label);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="block labels">
|
||||
<dropdown-value-collapsed
|
||||
v-if="showCreate"
|
||||
:labels="context.labels"
|
||||
/>
|
||||
<dropdown-title
|
||||
:can-edit="canEdit"
|
||||
/>
|
||||
<dropdown-value
|
||||
:labels="context.labels"
|
||||
:label-filter-base-path="labelFilterBasePath"
|
||||
>
|
||||
<slot></slot>
|
||||
</dropdown-value>
|
||||
<div
|
||||
v-if="canEdit"
|
||||
class="selectbox"
|
||||
style="display: none;"
|
||||
>
|
||||
<dropdown-hidden-input
|
||||
v-for="label in context.labels"
|
||||
:key="label.id"
|
||||
:name="hiddenInputName"
|
||||
:label="label"
|
||||
/>
|
||||
<div class="dropdown">
|
||||
<dropdown-button
|
||||
:ability-name="abilityName"
|
||||
:field-name="hiddenInputName"
|
||||
:update-path="updatePath"
|
||||
:labels-path="labelsPath"
|
||||
:namespace="namespace"
|
||||
:labels="context.labels"
|
||||
:show-extra-options="!showCreate"
|
||||
/>
|
||||
<div
|
||||
class="dropdown-menu dropdown-select dropdown-menu-paging
|
||||
dropdown-menu-labels dropdown-menu-selectable"
|
||||
>
|
||||
<div class="dropdown-page-one">
|
||||
<dropdown-header v-if="showCreate" />
|
||||
<dropdown-search-input/>
|
||||
<div class="dropdown-content"></div>
|
||||
<div class="dropdown-loading">
|
||||
<loading-icon />
|
||||
</div>
|
||||
<dropdown-footer
|
||||
v-if="showCreate"
|
||||
:labels-web-url="labelsWebUrl"
|
||||
/>
|
||||
</div>
|
||||
<dropdown-create-label
|
||||
v-if="showCreate"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,78 @@
|
|||
<script>
|
||||
import { __, s__, sprintf } from '~/locale';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
abilityName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
fieldName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
updatePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
labelsPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
namespace: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
labels: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
showExtraOptions: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
dropdownToggleText() {
|
||||
if (this.labels.length === 0) {
|
||||
return __('Label');
|
||||
}
|
||||
|
||||
if (this.labels.length > 1) {
|
||||
return sprintf(s__('LabelSelect|%{firstLabelName} +%{remainingLabelCount} more'), {
|
||||
firstLabelName: this.labels[0].title,
|
||||
remainingLabelCount: this.labels.length - 1,
|
||||
});
|
||||
}
|
||||
|
||||
return this.labels[0].title;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
type="button"
|
||||
ref="dropdownButton"
|
||||
class="dropdown-menu-toggle wide js-label-select js-multiselect js-context-config-modal"
|
||||
data-toggle="dropdown"
|
||||
:class="{ 'js-extra-options': showExtraOptions }"
|
||||
:data-ability-name="abilityName"
|
||||
:data-field-name="fieldName"
|
||||
:data-issue-update="updatePath"
|
||||
:data-labels="labelsPath"
|
||||
:data-namespace-path="namespace"
|
||||
:data-show-any="showExtraOptions"
|
||||
>
|
||||
<span class="dropdown-toggle-text">
|
||||
{{ dropdownToggleText }}
|
||||
</span>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-chevron-down"
|
||||
data-hidden="true"
|
||||
>
|
||||
</i>
|
||||
</button>
|
||||
</template>
|
|
@ -0,0 +1,84 @@
|
|||
<script>
|
||||
export default {
|
||||
created() {
|
||||
this.suggestedColors = gon.suggested_label_colors;
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dropdown-page-two dropdown-new-label">
|
||||
<div class="dropdown-title">
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-title-button dropdown-menu-back"
|
||||
:aria-label="__('Go back')"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-arrow-left"
|
||||
data-hidden="true"
|
||||
>
|
||||
</i>
|
||||
</button>
|
||||
{{ __('Create new label') }}
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-title-button dropdown-menu-close"
|
||||
:aria-label="__('Close')"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-times dropdown-menu-close-icon"
|
||||
data-hidden="true"
|
||||
>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-content">
|
||||
<div class="dropdown-labels-error js-label-error"></div>
|
||||
<input
|
||||
id="new_label_name"
|
||||
type="text"
|
||||
class="default-dropdown-input"
|
||||
:placeholder="__('Name new label')"
|
||||
/>
|
||||
<div class="suggest-colors suggest-colors-dropdown">
|
||||
<a
|
||||
v-for="(color, index) in suggestedColors"
|
||||
href="#"
|
||||
:key="index"
|
||||
:data-color="color"
|
||||
:style="{
|
||||
backgroundColor: color,
|
||||
}"
|
||||
>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
<div class="dropdown-label-color-input">
|
||||
<div class="dropdown-label-color-preview js-dropdown-label-color-preview"></div>
|
||||
<input
|
||||
id="new_label_color"
|
||||
type="text"
|
||||
class="default-dropdown-input"
|
||||
:placeholder="__('Assign custom color like #FF0000')"
|
||||
/>
|
||||
</div>
|
||||
<div class="clearfix">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary pull-left js-new-label-btn disabled"
|
||||
>
|
||||
{{ __('Create') }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default pull-right js-cancel-label-btn"
|
||||
>
|
||||
{{ __('Cancel') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,34 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
labelsWebUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dropdown-footer">
|
||||
<ul class="dropdown-footer-list">
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle-page"
|
||||
>
|
||||
{{ __('Create new label') }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
data-is-link="true"
|
||||
class="dropdown-external-link"
|
||||
:href="labelsWebUrl"
|
||||
>
|
||||
{{ __('Manage labels') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,21 @@
|
|||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dropdown-title">
|
||||
<span>{{ __('Assign labels') }}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-title-button dropdown-menu-close"
|
||||
:aria-label="__('Close')"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-times dropdown-menu-close-icon"
|
||||
data-hidden="true"
|
||||
>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,22 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
label: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<input
|
||||
type="hidden"
|
||||
:name="name"
|
||||
:value="label.id"
|
||||
/>
|
||||
</template>
|
|
@ -0,0 +1,27 @@
|
|||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dropdown-input">
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="dropdown-input-field"
|
||||
type="search"
|
||||
:placeholder="__('Search')"
|
||||
/>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-search dropdown-input-search"
|
||||
data-hidden="true"
|
||||
>
|
||||
</i>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-times dropdown-input-clear js-dropdown-input-clear"
|
||||
data-hidden="true"
|
||||
role="button"
|
||||
>
|
||||
</i>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,30 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
canEdit: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="title hide-collapsed append-bottom-10">
|
||||
{{ __('Labels') }}
|
||||
<template v-if="canEdit">
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-spinner fa-spin block-loading"
|
||||
data-hidden="true"
|
||||
>
|
||||
</i>
|
||||
<button
|
||||
type="button"
|
||||
class="edit-link btn btn-blank pull-right js-sidebar-dropdown-toggle"
|
||||
>
|
||||
{{ __('Edit') }}
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,63 @@
|
|||
<script>
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
|
||||
export default {
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
labels: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
labelFilterBasePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isEmpty() {
|
||||
return this.labels.length === 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
labelFilterUrl(label) {
|
||||
return `${this.labelFilterBasePath}?label_name[]=${encodeURIComponent(label.title)}`;
|
||||
},
|
||||
labelStyle(label) {
|
||||
return {
|
||||
color: label.textColor,
|
||||
backgroundColor: label.color,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="hide-collapsed value issuable-show-labels">
|
||||
<span
|
||||
v-if="isEmpty"
|
||||
class="text-secondary"
|
||||
>
|
||||
<slot>{{ __('None') }}</slot>
|
||||
</span>
|
||||
<a
|
||||
v-else
|
||||
v-for="label in labels"
|
||||
:key="label.id"
|
||||
:href="labelFilterUrl(label)"
|
||||
>
|
||||
<span
|
||||
v-tooltip
|
||||
class="label color-label"
|
||||
data-placement="bottom"
|
||||
data-container="body"
|
||||
:style="labelStyle(label)"
|
||||
:title="label.description"
|
||||
>
|
||||
{{ label.title }}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,48 @@
|
|||
<script>
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
|
||||
export default {
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
labels: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
labelsList() {
|
||||
const labelsString = this.labels.slice(0, 5).map(label => label.title).join(', ');
|
||||
|
||||
if (this.labels.length > 5) {
|
||||
return sprintf(s__('LabelSelect|%{labelsString}, and %{remainingLabelCount} more'), {
|
||||
labelsString,
|
||||
remainingLabelCount: this.labels.length - 5,
|
||||
});
|
||||
}
|
||||
|
||||
return labelsString;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-tooltip
|
||||
class="sidebar-collapsed-icon"
|
||||
data-placement="left"
|
||||
data-container="body"
|
||||
:title="labelsList"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
data-hidden="true"
|
||||
class="fa fa-tags"
|
||||
>
|
||||
</i>
|
||||
<span>{{ labels.length }}</span>
|
||||
</div>
|
||||
</template>
|
|
@ -1,7 +1,5 @@
|
|||
/* eslint-disable no-unused-vars, space-before-function-paren */
|
||||
|
||||
class ListLabel {
|
||||
constructor (obj) {
|
||||
constructor(obj) {
|
||||
this.id = obj.id;
|
||||
this.title = obj.title;
|
||||
this.type = obj.type;
|
|
@ -1,4 +1,5 @@
|
|||
module LabelsHelper
|
||||
extend self
|
||||
include ActionView::Helpers::TagHelper
|
||||
|
||||
def show_label_issuables_link?(label, issuables_type, current_user: nil, project: nil)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Port Labels Select dropdown to Vue
|
||||
merge_request: 17411
|
||||
author:
|
||||
type: other
|
|
@ -20,6 +20,7 @@ module Gitlab
|
|||
gon.sprite_icons = IconsHelper.sprite_icon_path
|
||||
gon.sprite_file_icons = IconsHelper.sprite_file_icons_path
|
||||
gon.test_env = Rails.env.test?
|
||||
gon.suggested_label_colors = LabelsHelper.suggested_colors
|
||||
|
||||
if current_user
|
||||
gon.current_user_id = current_user.id
|
||||
|
|
|
@ -9,8 +9,8 @@ import axios from '~/lib/utils/axios_utils';
|
|||
import '~/boards/models/assignee';
|
||||
|
||||
import eventHub from '~/boards/eventhub';
|
||||
import '~/vue_shared/models/label';
|
||||
import '~/boards/models/list';
|
||||
import '~/boards/models/label';
|
||||
import '~/boards/stores/boards_store';
|
||||
import boardCard from '~/boards/components/board_card.vue';
|
||||
import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
|
||||
|
|
|
@ -7,8 +7,8 @@ import MockAdapter from 'axios-mock-adapter';
|
|||
import axios from '~/lib/utils/axios_utils';
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
import '~/vue_shared/models/label';
|
||||
import '~/boards/models/issue';
|
||||
import '~/boards/models/label';
|
||||
import '~/boards/models/list';
|
||||
import '~/boards/models/assignee';
|
||||
import '~/boards/services/board_service';
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
import '~/vue_shared/models/label';
|
||||
import '~/boards/models/issue';
|
||||
import '~/boards/models/label';
|
||||
import '~/boards/models/list';
|
||||
import '~/boards/models/assignee';
|
||||
import '~/boards/stores/boards_store';
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
/* global ListIssue */
|
||||
|
||||
import Vue from 'vue';
|
||||
import '~/vue_shared/models/label';
|
||||
import '~/boards/models/issue';
|
||||
import '~/boards/models/label';
|
||||
import '~/boards/models/list';
|
||||
import '~/boards/models/assignee';
|
||||
import '~/boards/services/board_service';
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import _ from 'underscore';
|
||||
import '~/vue_shared/models/label';
|
||||
import '~/boards/models/issue';
|
||||
import '~/boards/models/label';
|
||||
import '~/boards/models/list';
|
||||
import '~/boards/models/assignee';
|
||||
import '~/boards/services/board_service';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* global ListIssue */
|
||||
|
||||
import '~/vue_shared/models/label';
|
||||
import '~/boards/models/issue';
|
||||
import '~/boards/models/label';
|
||||
import '~/boards/models/list';
|
||||
import '~/boards/models/assignee';
|
||||
import '~/boards/stores/modal_store';
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import LabelsSelect from '~/labels_select';
|
||||
import baseComponent from '~/vue_shared/components/sidebar/labels_select/base.vue';
|
||||
|
||||
import { mockConfig, mockLabels } from './mock_data';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const createComponent = (config = mockConfig) => {
|
||||
const Component = Vue.extend(baseComponent);
|
||||
|
||||
return mountComponent(Component, config);
|
||||
};
|
||||
|
||||
describe('BaseComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('computed', () => {
|
||||
describe('hiddenInputName', () => {
|
||||
it('returns correct string when showCreate prop is `true`', () => {
|
||||
expect(vm.hiddenInputName).toBe('issue[label_names][]');
|
||||
});
|
||||
|
||||
it('returns correct string when showCreate prop is `false`', () => {
|
||||
const mockConfigNonEditable = Object.assign({}, mockConfig, { showCreate: false });
|
||||
const vmNonEditable = createComponent(mockConfigNonEditable);
|
||||
expect(vmNonEditable.hiddenInputName).toBe('label_id[]');
|
||||
vmNonEditable.$destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
describe('handleClick', () => {
|
||||
it('emits onLabelClick event with label and list of labels as params', () => {
|
||||
spyOn(vm, '$emit');
|
||||
vm.handleClick(mockLabels[0]);
|
||||
expect(vm.$emit).toHaveBeenCalledWith('onLabelClick', mockLabels[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('mounted', () => {
|
||||
it('creates LabelsSelect object and assigns it to `labelsDropdon` as prop', () => {
|
||||
expect(vm.labelsDropdown instanceof LabelsSelect).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders component container element with classes `block labels`', () => {
|
||||
expect(vm.$el.classList.contains('block')).toBe(true);
|
||||
expect(vm.$el.classList.contains('labels')).toBe(true);
|
||||
});
|
||||
|
||||
it('renders `.selectbox` element', () => {
|
||||
expect(vm.$el.querySelector('.selectbox')).not.toBeNull();
|
||||
expect(vm.$el.querySelector('.selectbox').getAttribute('style')).toBe('display: none;');
|
||||
});
|
||||
|
||||
it('renders `.dropdown` element', () => {
|
||||
expect(vm.$el.querySelector('.dropdown')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders `.dropdown-menu` element', () => {
|
||||
const dropdownMenuEl = vm.$el.querySelector('.dropdown-menu');
|
||||
expect(dropdownMenuEl).not.toBeNull();
|
||||
expect(dropdownMenuEl.querySelector('.dropdown-page-one')).not.toBeNull();
|
||||
expect(dropdownMenuEl.querySelector('.dropdown-content')).not.toBeNull();
|
||||
expect(dropdownMenuEl.querySelector('.dropdown-loading')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import dropdownButtonComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_button.vue';
|
||||
|
||||
import { mockConfig, mockLabels } from './mock_data';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const componentConfig = Object.assign({}, mockConfig, {
|
||||
fieldName: 'label_id[]',
|
||||
labels: mockLabels,
|
||||
showExtraOptions: false,
|
||||
});
|
||||
|
||||
const createComponent = (config = componentConfig) => {
|
||||
const Component = Vue.extend(dropdownButtonComponent);
|
||||
|
||||
return mountComponent(Component, config);
|
||||
};
|
||||
|
||||
describe('DropdownButtonComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('computed', () => {
|
||||
describe('dropdownToggleText', () => {
|
||||
it('returns text as `Label` when `labels` prop is empty array', () => {
|
||||
const mockEmptyLabels = Object.assign({}, componentConfig, { labels: [] });
|
||||
const vmEmptyLabels = createComponent(mockEmptyLabels);
|
||||
expect(vmEmptyLabels.dropdownToggleText).toBe('Label');
|
||||
vmEmptyLabels.$destroy();
|
||||
});
|
||||
|
||||
it('returns first label name with remaining label count when `labels` prop has more than one item', () => {
|
||||
const mockMoreLabels = Object.assign({}, componentConfig, {
|
||||
labels: mockLabels.concat(mockLabels),
|
||||
});
|
||||
const vmMoreLabels = createComponent(mockMoreLabels);
|
||||
expect(vmMoreLabels.dropdownToggleText).toBe('Foo Label +1 more');
|
||||
vmMoreLabels.$destroy();
|
||||
});
|
||||
|
||||
it('returns first label name when `labels` prop has only one item present', () => {
|
||||
expect(vm.dropdownToggleText).toBe('Foo Label');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders component container element of type `button`', () => {
|
||||
expect(vm.$el.nodeName).toBe('BUTTON');
|
||||
});
|
||||
|
||||
it('renders component container element with required data attributes', () => {
|
||||
expect(vm.$el.dataset.abilityName).toBe(vm.abilityName);
|
||||
expect(vm.$el.dataset.fieldName).toBe(vm.fieldName);
|
||||
expect(vm.$el.dataset.issueUpdate).toBe(vm.updatePath);
|
||||
expect(vm.$el.dataset.labels).toBe(vm.labelsPath);
|
||||
expect(vm.$el.dataset.namespacePath).toBe(vm.namespace);
|
||||
expect(vm.$el.dataset.showAny).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('renders dropdown toggle text element', () => {
|
||||
const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
|
||||
expect(dropdownToggleTextEl).not.toBeNull();
|
||||
expect(dropdownToggleTextEl.innerText.trim()).toBe('Foo Label');
|
||||
});
|
||||
|
||||
it('renders dropdown button icon', () => {
|
||||
const dropdownIconEl = vm.$el.querySelector('i.fa');
|
||||
expect(dropdownIconEl).not.toBeNull();
|
||||
expect(dropdownIconEl.classList.contains('fa-chevron-down')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,84 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import dropdownCreateLabelComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue';
|
||||
|
||||
import { mockSuggestedColors } from './mock_data';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const createComponent = () => {
|
||||
const Component = Vue.extend(dropdownCreateLabelComponent);
|
||||
|
||||
return mountComponent(Component);
|
||||
};
|
||||
|
||||
describe('DropdownCreateLabelComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
gon.suggested_label_colors = mockSuggestedColors;
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('created', () => {
|
||||
it('initializes `suggestedColors` prop on component from `gon.suggested_color_labels` object', () => {
|
||||
expect(vm.suggestedColors.length).toBe(mockSuggestedColors.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders component container element with classes `dropdown-page-two dropdown-new-label`', () => {
|
||||
expect(vm.$el.classList.contains('dropdown-page-two', 'dropdown-new-label')).toBe(true);
|
||||
});
|
||||
|
||||
it('renders `Go back` button on component header', () => {
|
||||
const backButtonEl = vm.$el.querySelector('.dropdown-title button.dropdown-title-button.dropdown-menu-back');
|
||||
expect(backButtonEl).not.toBe(null);
|
||||
expect(backButtonEl.querySelector('.fa-arrow-left')).not.toBe(null);
|
||||
});
|
||||
|
||||
it('renders component header element', () => {
|
||||
const headerEl = vm.$el.querySelector('.dropdown-title');
|
||||
expect(headerEl.innerText.trim()).toContain('Create new label');
|
||||
});
|
||||
|
||||
it('renders `Close` button on component header', () => {
|
||||
const closeButtonEl = vm.$el.querySelector('.dropdown-title button.dropdown-title-button.dropdown-menu-close');
|
||||
expect(closeButtonEl).not.toBe(null);
|
||||
expect(closeButtonEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBe(null);
|
||||
});
|
||||
|
||||
it('renders `Name new label` input element', () => {
|
||||
expect(vm.$el.querySelector('.dropdown-labels-error.js-label-error')).not.toBe(null);
|
||||
expect(vm.$el.querySelector('input#new_label_name.default-dropdown-input')).not.toBe(null);
|
||||
});
|
||||
|
||||
it('renders suggested colors list elements', () => {
|
||||
const colorsListContainerEl = vm.$el.querySelector('.suggest-colors.suggest-colors-dropdown');
|
||||
expect(colorsListContainerEl).not.toBe(null);
|
||||
expect(colorsListContainerEl.querySelectorAll('a').length).toBe(mockSuggestedColors.length);
|
||||
|
||||
const colorItemEl = colorsListContainerEl.querySelectorAll('a')[0];
|
||||
expect(colorItemEl.dataset.color).toBe(vm.suggestedColors[0]);
|
||||
expect(colorItemEl.getAttribute('style')).toBe('background-color: rgb(0, 51, 204);');
|
||||
});
|
||||
|
||||
it('renders color input element', () => {
|
||||
expect(vm.$el.querySelector('.dropdown-label-color-input')).not.toBe(null);
|
||||
expect(vm.$el.querySelector('.dropdown-label-color-preview.js-dropdown-label-color-preview')).not.toBe(null);
|
||||
expect(vm.$el.querySelector('input#new_label_color.default-dropdown-input')).not.toBe(null);
|
||||
});
|
||||
|
||||
it('renders component action buttons', () => {
|
||||
const createBtnEl = vm.$el.querySelector('button.js-new-label-btn');
|
||||
const cancelBtnEl = vm.$el.querySelector('button.js-cancel-label-btn');
|
||||
expect(createBtnEl).not.toBe(null);
|
||||
expect(createBtnEl.innerText.trim()).toBe('Create');
|
||||
expect(cancelBtnEl.innerText.trim()).toBe('Cancel');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,42 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import dropdownFooterComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_footer.vue';
|
||||
|
||||
import { mockConfig } from './mock_data';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const createComponent = (labelsWebUrl = mockConfig.labelsWebUrl) => {
|
||||
const Component = Vue.extend(dropdownFooterComponent);
|
||||
|
||||
return mountComponent(Component, {
|
||||
labelsWebUrl,
|
||||
});
|
||||
};
|
||||
|
||||
describe('DropdownFooterComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders `Create new label` link element', () => {
|
||||
const createLabelEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-toggle-page');
|
||||
expect(createLabelEl).not.toBeNull();
|
||||
expect(createLabelEl.innerText.trim()).toBe('Create new label');
|
||||
});
|
||||
|
||||
it('renders `Manage labels` link element', () => {
|
||||
const manageLabelsEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-external-link');
|
||||
expect(manageLabelsEl).not.toBeNull();
|
||||
expect(manageLabelsEl.getAttribute('href')).toBe(vm.labelsWebUrl);
|
||||
expect(manageLabelsEl.innerText.trim()).toBe('Manage labels');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import dropdownHeaderComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_header.vue';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const createComponent = () => {
|
||||
const Component = Vue.extend(dropdownHeaderComponent);
|
||||
|
||||
return mountComponent(Component);
|
||||
};
|
||||
|
||||
describe('DropdownHeaderComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders header text element', () => {
|
||||
const headerEl = vm.$el.querySelector('.dropdown-title span');
|
||||
expect(headerEl.innerText.trim()).toBe('Assign labels');
|
||||
});
|
||||
|
||||
it('renders `Close` button element', () => {
|
||||
const closeBtnEl = vm.$el.querySelector('.dropdown-title button.dropdown-title-button.dropdown-menu-close');
|
||||
expect(closeBtnEl).not.toBeNull();
|
||||
expect(closeBtnEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import dropdownHiddenInputComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_hidden_input.vue';
|
||||
|
||||
import { mockLabels } from './mock_data';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const createComponent = (name = 'label_id[]', label = mockLabels[0]) => {
|
||||
const Component = Vue.extend(dropdownHiddenInputComponent);
|
||||
|
||||
return mountComponent(Component, {
|
||||
name,
|
||||
label,
|
||||
});
|
||||
};
|
||||
|
||||
describe('DropdownHiddenInputComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders input element of type `hidden`', () => {
|
||||
expect(vm.$el.nodeName).toBe('INPUT');
|
||||
expect(vm.$el.getAttribute('type')).toBe('hidden');
|
||||
expect(vm.$el.getAttribute('name')).toBe(vm.name);
|
||||
expect(vm.$el.getAttribute('value')).toBe(`${vm.label.id}`);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import dropdownSearchInputComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const createComponent = () => {
|
||||
const Component = Vue.extend(dropdownSearchInputComponent);
|
||||
|
||||
return mountComponent(Component);
|
||||
};
|
||||
|
||||
describe('DropdownSearchInputComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders input element with type `search`', () => {
|
||||
const inputEl = vm.$el.querySelector('input.dropdown-input-field');
|
||||
expect(inputEl).not.toBeNull();
|
||||
expect(inputEl.getAttribute('type')).toBe('search');
|
||||
});
|
||||
|
||||
it('renders search icon element', () => {
|
||||
expect(vm.$el.querySelector('.fa-search.dropdown-input-search')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders clear search icon element', () => {
|
||||
expect(vm.$el.querySelector('.fa-times.dropdown-input-clear.js-dropdown-input-clear')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,42 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import dropdownTitleComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_title.vue';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const createComponent = (canEdit = true) => {
|
||||
const Component = Vue.extend(dropdownTitleComponent);
|
||||
|
||||
return mountComponent(Component, {
|
||||
canEdit,
|
||||
});
|
||||
};
|
||||
|
||||
describe('DropdownTitleComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders title text', () => {
|
||||
expect(vm.$el.classList.contains('title', 'hide-collapsed')).toBe(true);
|
||||
expect(vm.$el.innerText.trim()).toContain('Labels');
|
||||
});
|
||||
|
||||
it('renders spinner icon element', () => {
|
||||
expect(vm.$el.querySelector('.fa-spinner.fa-spin.block-loading')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders `Edit` button element', () => {
|
||||
const editBtnEl = vm.$el.querySelector('button.edit-link.js-sidebar-dropdown-toggle');
|
||||
expect(editBtnEl).not.toBeNull();
|
||||
expect(editBtnEl.innerText.trim()).toBe('Edit');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,74 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import dropdownValueCollapsedComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue';
|
||||
|
||||
import { mockLabels } from './mock_data';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const createComponent = (labels = mockLabels) => {
|
||||
const Component = Vue.extend(dropdownValueCollapsedComponent);
|
||||
|
||||
return mountComponent(Component, {
|
||||
labels,
|
||||
});
|
||||
};
|
||||
|
||||
describe('DropdownValueCollapsedComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('computed', () => {
|
||||
describe('labelsList', () => {
|
||||
it('returns empty text when `labels` prop is empty array', () => {
|
||||
const vmEmptyLabels = createComponent([]);
|
||||
expect(vmEmptyLabels.labelsList).toBe('');
|
||||
vmEmptyLabels.$destroy();
|
||||
});
|
||||
|
||||
it('returns labels names separated by coma when `labels` prop has more than one item', () => {
|
||||
const vmMoreLabels = createComponent(mockLabels.concat(mockLabels));
|
||||
expect(vmMoreLabels.labelsList).toBe('Foo Label, Foo Label');
|
||||
vmMoreLabels.$destroy();
|
||||
});
|
||||
|
||||
it('returns labels names separated by coma with remaining labels count and `and more` phrase when `labels` prop has more than five items', () => {
|
||||
const mockMoreLabels = Object.assign([], mockLabels);
|
||||
for (let i = 0; i < 6; i += 1) {
|
||||
mockMoreLabels.unshift(mockLabels[0]);
|
||||
}
|
||||
|
||||
const vmMoreLabels = createComponent(mockMoreLabels);
|
||||
expect(vmMoreLabels.labelsList).toBe('Foo Label, Foo Label, Foo Label, Foo Label, Foo Label, and 2 more');
|
||||
vmMoreLabels.$destroy();
|
||||
});
|
||||
|
||||
it('returns first label name when `labels` prop has only one item present', () => {
|
||||
expect(vm.labelsList).toBe('Foo Label');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders component container element with tooltip`', () => {
|
||||
expect(vm.$el.dataset.placement).toBe('left');
|
||||
expect(vm.$el.dataset.container).toBe('body');
|
||||
expect(vm.$el.dataset.originalTitle).toBe(vm.labelsList);
|
||||
});
|
||||
|
||||
it('renders tags icon element', () => {
|
||||
expect(vm.$el.querySelector('.fa-tags')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders labels count', () => {
|
||||
expect(vm.$el.querySelector('span').innerText.trim()).toBe(`${vm.labels.length}`);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,94 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import dropdownValueComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value.vue';
|
||||
|
||||
import { mockConfig, mockLabels } from './mock_data';
|
||||
|
||||
import mountComponent from '../../../../helpers/vue_mount_component_helper';
|
||||
|
||||
const createComponent = (
|
||||
labels = mockLabels,
|
||||
labelFilterBasePath = mockConfig.labelFilterBasePath,
|
||||
) => {
|
||||
const Component = Vue.extend(dropdownValueComponent);
|
||||
|
||||
return mountComponent(Component, {
|
||||
labels,
|
||||
labelFilterBasePath,
|
||||
});
|
||||
};
|
||||
|
||||
describe('DropdownValueComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('computed', () => {
|
||||
describe('isEmpty', () => {
|
||||
it('returns true if `labels` prop is empty', () => {
|
||||
const vmEmptyLabels = createComponent([]);
|
||||
expect(vmEmptyLabels.isEmpty).toBe(true);
|
||||
vmEmptyLabels.$destroy();
|
||||
});
|
||||
|
||||
it('returns false if `labels` prop is empty', () => {
|
||||
expect(vm.isEmpty).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
describe('labelFilterUrl', () => {
|
||||
it('returns URL string starting with labelFilterBasePath and encoded label.title', () => {
|
||||
expect(vm.labelFilterUrl({
|
||||
title: 'Foo bar',
|
||||
})).toBe('/gitlab-org/my-project/issues?label_name[]=Foo%20bar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('labelStyle', () => {
|
||||
it('returns object with `color` & `backgroundColor` properties from label.textColor & label.color', () => {
|
||||
const label = {
|
||||
textColor: '#FFFFFF',
|
||||
color: '#BADA55',
|
||||
};
|
||||
const styleObj = vm.labelStyle(label);
|
||||
|
||||
expect(styleObj.color).toBe(label.textColor);
|
||||
expect(styleObj.backgroundColor).toBe(label.color);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
it('renders component container element with classes `hide-collapsed value issuable-show-labels`', () => {
|
||||
expect(vm.$el.classList.contains('hide-collapsed', 'value', 'issuable-show-labels')).toBe(true);
|
||||
});
|
||||
|
||||
it('render slot content inside component when `labels` prop is empty', () => {
|
||||
const vmEmptyLabels = createComponent([]);
|
||||
expect(vmEmptyLabels.$el.querySelector('.text-secondary').innerText.trim()).toBe(mockConfig.emptyValueText);
|
||||
vmEmptyLabels.$destroy();
|
||||
});
|
||||
|
||||
it('renders label element with filter URL', () => {
|
||||
expect(vm.$el.querySelector('a').getAttribute('href')).toBe('/gitlab-org/my-project/issues?label_name[]=Foo%20Label');
|
||||
});
|
||||
|
||||
it('renders label element with tooltip and styles based on label details', () => {
|
||||
const labelEl = vm.$el.querySelector('a span.label.color-label');
|
||||
expect(labelEl).not.toBeNull();
|
||||
expect(labelEl.dataset.placement).toBe('bottom');
|
||||
expect(labelEl.dataset.container).toBe('body');
|
||||
expect(labelEl.dataset.originalTitle).toBe(mockLabels[0].description);
|
||||
expect(labelEl.getAttribute('style')).toBe('background-color: rgb(186, 218, 85);');
|
||||
expect(labelEl.innerText.trim()).toBe(mockLabels[0].title);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,49 @@
|
|||
export const mockLabels = [
|
||||
{
|
||||
id: 26,
|
||||
title: 'Foo Label',
|
||||
description: 'Foobar',
|
||||
color: '#BADA55',
|
||||
text_color: '#FFFFFF',
|
||||
},
|
||||
];
|
||||
|
||||
export const mockSuggestedColors = [
|
||||
'#0033CC',
|
||||
'#428BCA',
|
||||
'#44AD8E',
|
||||
'#A8D695',
|
||||
'#5CB85C',
|
||||
'#69D100',
|
||||
'#004E00',
|
||||
'#34495E',
|
||||
'#7F8C8D',
|
||||
'#A295D6',
|
||||
'#5843AD',
|
||||
'#8E44AD',
|
||||
'#FFECDB',
|
||||
'#AD4363',
|
||||
'#D10069',
|
||||
'#CC0033',
|
||||
'#FF0000',
|
||||
'#D9534F',
|
||||
'#D1D100',
|
||||
'#F0AD4E',
|
||||
'#AD8D43',
|
||||
];
|
||||
|
||||
export const mockConfig = {
|
||||
showCreate: true,
|
||||
abilityName: 'issue',
|
||||
context: {
|
||||
labels: mockLabels,
|
||||
},
|
||||
namespace: 'gitlab-org',
|
||||
updatePath: '/gitlab-org/my-project/issue/1',
|
||||
labelsPath: '/gitlab-org/my-project/labels.json',
|
||||
labelsWebUrl: '/gitlab-org/my-project/labels',
|
||||
labelFilterBasePath: '/gitlab-org/my-project/issues',
|
||||
canEdit: true,
|
||||
suggestedColors: mockSuggestedColors,
|
||||
emptyValueText: 'None',
|
||||
};
|
Loading…
Reference in New Issue