diff --git a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue
index 93e3cfba309c2555da973b265d6a1bba34ac2e4d..f3209d1a02f050b0be817bf082e68b97ae441b5e 100644
--- a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue
+++ b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue
@@ -1,17 +1,11 @@
+
+
+
diff --git a/app/assets/stylesheets/page_bundles/labels.scss b/app/assets/stylesheets/page_bundles/labels.scss
index bc0bf4bc4903cc90e87cf382c5169dc75a915415..3204e678986278ffbd9c6a0f7496bba3cfe62185 100644
--- a/app/assets/stylesheets/page_bundles/labels.scss
+++ b/app/assets/stylesheets/page_bundles/labels.scss
@@ -1,54 +1,5 @@
@import 'mixins_and_variables_and_functions';
-.suggest-colors {
- padding-top: 3px;
-
- a {
- border-radius: 4px;
- width: 30px;
- height: 30px;
- display: inline-block;
- margin-right: 10px;
- margin-bottom: 10px;
- text-decoration: none;
-
- &:focus,
- &:focus:active {
- position: relative;
- z-index: 1;
- @include gl-focus;
- }
- }
-
- &.suggest-colors-dropdown {
- margin-top: 10px;
- margin-bottom: 10px;
-
- a {
- border-radius: 0;
- width: (100% / 7);
- margin-right: 0;
- margin-bottom: -5px;
-
- &:first-of-type {
- border-top-left-radius: $gl-border-radius-base;
- }
-
- &:nth-of-type(7) {
- border-top-right-radius: $gl-border-radius-base;
- }
-
- &:nth-last-child(7) {
- border-bottom-left-radius: $gl-border-radius-base;
- }
-
- &:last-of-type {
- border-bottom-right-radius: $gl-border-radius-base;
- }
- }
- }
-}
-
.labels-select-contents-create {
.dropdown-input {
margin-bottom: 4px;
diff --git a/app/assets/stylesheets/pages/colors.scss b/app/assets/stylesheets/pages/colors.scss
index 85c1f7da07fdc928327055de0979b33ef722e54e..aeaf2d7c1b348aa616d19970872162361aa61932 100644
--- a/app/assets/stylesheets/pages/colors.scss
+++ b/app/assets/stylesheets/pages/colors.scss
@@ -29,3 +29,52 @@
.danger-title {
color: var(--red-500, $red-500);
}
+
+.suggest-colors {
+ padding-top: 3px;
+
+ a {
+ border-radius: 4px;
+ width: 30px;
+ height: 30px;
+ display: inline-block;
+ margin-right: 10px;
+ margin-bottom: 10px;
+ text-decoration: none;
+
+ &:focus,
+ &:focus:active {
+ position: relative;
+ z-index: 1;
+ @include gl-focus;
+ }
+ }
+
+ &.suggest-colors-dropdown {
+ margin-top: 10px;
+ margin-bottom: 10px;
+
+ a {
+ border-radius: 0;
+ width: (100% / 7);
+ margin-right: 0;
+ margin-bottom: -5px;
+
+ &:first-of-type {
+ border-top-left-radius: $gl-border-radius-base;
+ }
+
+ &:nth-of-type(7) {
+ border-top-right-radius: $gl-border-radius-base;
+ }
+
+ &:nth-last-child(7) {
+ border-bottom-left-radius: $gl-border-radius-base;
+ }
+
+ &:last-of-type {
+ border-bottom-right-radius: $gl-border-radius-base;
+ }
+ }
+ }
+}
diff --git a/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view_spec.js b/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view_spec.js
index 5e2ff73878f98e4944b55e04645264b50513640f..7180e10e7b103f8c1e0177dc0db665444f4d9ea6 100644
--- a/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view_spec.js
+++ b/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view_spec.js
@@ -1,4 +1,4 @@
-import { GlAlert, GlLoadingIcon, GlLink } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
@@ -7,6 +7,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/alert';
import { workspaceLabelsQueries, workspaceCreateLabelMutation } from '~/sidebar/queries/constants';
import DropdownContentsCreateView from '~/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue';
+import SibebarColorPicker from '~/sidebar/components/sidebar_color_picker.vue';
import { DEFAULT_LABEL_COLOR } from '~/sidebar/components/labels/labels_select_widget/constants';
import {
mockCreateLabelResponse as createAbuseReportLabelSuccessfulResponse,
@@ -14,7 +15,6 @@ import {
} from '../../../../admin/abuse_report/mock_data';
import {
mockRegularLabel,
- mockSuggestedColors,
createLabelSuccessfulResponse,
workspaceLabelsQueryResponse,
workspaceLabelsQueryEmptyResponse,
@@ -22,8 +22,6 @@ import {
jest.mock('~/alert');
-const colors = Object.keys(mockSuggestedColors);
-
Vue.use(VueApollo);
const userRecoverableError = {
@@ -51,9 +49,7 @@ const createLabelErrorHandler = jest.fn().mockRejectedValue('Houston, we have a
describe('DropdownContentsCreateView', () => {
let wrapper;
- const findAllColors = () => wrapper.findAllComponents(GlLink);
- const findSelectedColor = () => wrapper.find('[data-testid="selected-color"]');
- const findSelectedColorText = () => wrapper.find('[data-testid="selected-color-text"]');
+ const findSibebarColorPicker = () => wrapper.findComponent(SibebarColorPicker);
const findCreateButton = () => wrapper.find('[data-testid="create-button"]');
const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]');
const findLabelTitleInput = () => wrapper.find('[data-testid="label-title-input"]');
@@ -62,7 +58,7 @@ describe('DropdownContentsCreateView', () => {
const fillLabelAttributes = () => {
findLabelTitleInput().vm.$emit('input', 'Test title');
- findAllColors().at(0).vm.$emit('click', new Event('mouseclick'));
+ findSibebarColorPicker().vm.$emit('input', '#009966');
};
const createComponent = ({
@@ -94,38 +90,9 @@ describe('DropdownContentsCreateView', () => {
});
};
- beforeEach(() => {
- gon.suggested_label_colors = mockSuggestedColors;
- });
-
- it('renders a palette of 21 colors', () => {
- createComponent();
- expect(findAllColors()).toHaveLength(21);
- });
-
- it('selects a color after clicking on colored block', async () => {
- createComponent();
- expect(findSelectedColorText().attributes('value')).toBe(DEFAULT_LABEL_COLOR);
-
- findAllColors().at(0).vm.$emit('click', new Event('mouseclick'));
- await nextTick();
-
- expect(findSelectedColor().attributes('value')).toBe('#009966');
- });
-
- it('shows correct color hex code after selecting a color', async () => {
- createComponent();
- expect(findSelectedColorText().attributes('value')).toBe(DEFAULT_LABEL_COLOR);
-
- findAllColors().at(0).vm.$emit('click', new Event('mouseclick'));
- await nextTick();
-
- expect(findSelectedColorText().attributes('value')).toBe(colors[0]);
- });
-
it('disables a Create button if label title is not set', async () => {
createComponent();
- findAllColors().at(0).vm.$emit('click', new Event('mouseclick'));
+ findSibebarColorPicker().vm.$emit('input', '#fff');
await nextTick();
expect(findCreateButton().props('disabled')).toBe(true);
@@ -134,7 +101,7 @@ describe('DropdownContentsCreateView', () => {
it('disables a Create button if color is not set', async () => {
createComponent();
findLabelTitleInput().vm.$emit('input', 'Test title');
- findSelectedColorText().vm.$emit('input', '');
+ findSibebarColorPicker().vm.$emit('input', '');
await nextTick();
expect(findCreateButton().props('disabled')).toBe(true);
diff --git a/spec/frontend/sidebar/components/labels/labels_select_widget/mock_data.js b/spec/frontend/sidebar/components/labels/labels_select_widget/mock_data.js
index 5039f00fe4b2d6b71d64788a8b7ed7b3765b6be8..eb7ab2953c6eb9ed3719b73fde911b7f309eb2be 100644
--- a/spec/frontend/sidebar/components/labels/labels_select_widget/mock_data.js
+++ b/spec/frontend/sidebar/components/labels/labels_select_widget/mock_data.js
@@ -58,30 +58,6 @@ export const mockConfig = {
attrWorkspacePath: 'test',
};
-export const mockSuggestedColors = {
- '#009966': 'Green-cyan',
- '#8fbc8f': 'Dark sea green',
- '#3cb371': 'Medium sea green',
- '#00b140': 'Green screen',
- '#013220': 'Dark green',
- '#6699cc': 'Blue-gray',
- '#0000ff': 'Blue',
- '#e6e6fa': 'Lavender',
- '#9400d3': 'Dark violet',
- '#330066': 'Deep violet',
- '#808080': 'Gray',
- '#36454f': 'Charcoal grey',
- '#f7e7ce': 'Champagne',
- '#c21e56': 'Rose red',
- '#cc338b': 'Magenta-pink',
- '#dc143c': 'Crimson',
- '#ff0000': 'Red',
- '#cd5b45': 'Dark coral',
- '#eee600': 'Titanium yellow',
- '#ed9121': 'Carrot orange',
- '#c39953': 'Aztec Gold',
-};
-
export const createLabelSuccessfulResponse = {
data: {
labelCreate: {
diff --git a/spec/frontend/sidebar/components/mock_data.js b/spec/frontend/sidebar/components/mock_data.js
index a9a00b3cfdf1e1653591b8c64b1558ac5c2612bb..b1b52674eb5061af89504738e8e01eaaa6167e8b 100644
--- a/spec/frontend/sidebar/components/mock_data.js
+++ b/spec/frontend/sidebar/components/mock_data.js
@@ -56,3 +56,27 @@ export const issueCrmContactsUpdateResponse = {
},
},
};
+
+export const mockSuggestedColors = {
+ '#009966': 'Green-cyan',
+ '#8fbc8f': 'Dark sea green',
+ '#3cb371': 'Medium sea green',
+ '#00b140': 'Green screen',
+ '#013220': 'Dark green',
+ '#6699cc': 'Blue-gray',
+ '#0000ff': 'Blue',
+ '#e6e6fa': 'Lavender',
+ '#9400d3': 'Dark violet',
+ '#330066': 'Deep violet',
+ '#808080': 'Gray',
+ '#36454f': 'Charcoal grey',
+ '#f7e7ce': 'Champagne',
+ '#c21e56': 'Rose red',
+ '#cc338b': 'Magenta-pink',
+ '#dc143c': 'Crimson',
+ '#ff0000': 'Red',
+ '#cd5b45': 'Dark coral',
+ '#eee600': 'Titanium yellow',
+ '#ed9121': 'Carrot orange',
+ '#c39953': 'Aztec Gold',
+};
diff --git a/spec/frontend/sidebar/components/sidebar_color_picker_spec.js b/spec/frontend/sidebar/components/sidebar_color_picker_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ce556fe36899a2a3b6571623545c598d9bc6475
--- /dev/null
+++ b/spec/frontend/sidebar/components/sidebar_color_picker_spec.js
@@ -0,0 +1,58 @@
+import { GlFormInput, GlLink } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import SibebarColorPicker from '~/sidebar/components/sidebar_color_picker.vue';
+import { mockSuggestedColors } from './mock_data';
+
+describe('SibebarColorPicker', () => {
+ let wrapper;
+ const findAllColors = () => wrapper.findAllComponents(GlLink);
+ const findFirstColor = () => findAllColors().at(0);
+ const findColorPicker = () => wrapper.findComponent(GlFormInput);
+ const findColorPickerText = () => wrapper.findByTestId('selected-color-text');
+
+ const createComponent = ({ value = '' } = {}) => {
+ wrapper = shallowMountExtended(SibebarColorPicker, {
+ propsData: {
+ value,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ gon.suggested_label_colors = mockSuggestedColors;
+ });
+
+ it('renders a palette of 21 colors', () => {
+ createComponent();
+ expect(findAllColors()).toHaveLength(21);
+ });
+
+ it('renders value of the color in textbox', () => {
+ createComponent({ value: '#343434' });
+ expect(findColorPickerText().attributes('value')).toBe('#343434');
+ });
+
+ describe('color picker', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('emits color on click of suggested color link', () => {
+ findFirstColor().vm.$emit('click', new Event('mouseclick'));
+
+ expect(wrapper.emitted('input')).toEqual([['#009966']]);
+ });
+
+ it('emits color on selecting color from picker', () => {
+ findColorPicker().vm.$emit('input', '#ffffff');
+
+ expect(wrapper.emitted('input')).toEqual([['#ffffff']]);
+ });
+
+ it('emits color on typing the hex code in the input', () => {
+ findColorPickerText().vm.$emit('input', '#000000');
+
+ expect(wrapper.emitted('input')).toEqual([['#000000']]);
+ });
+ });
+});