Commit 554e2c37 authored by Nick Thomas's avatar Nick Thomas

Merge branch 'ce-to-ee-2018-03-12' into 'master'

CE upstream - 2018-03-12 12:25 UTC

Closes #4281 and gitlab-ce#4281

See merge request gitlab-org/gitlab-ee!4931
parents 92c68eb9 492a2bee
......@@ -7,7 +7,7 @@ import Flash from '../../flash';
import { __ } from '../../locale';
import Sidebar from '../../right_sidebar';
import eventHub from '../../sidebar/event_hub';
import assigneeTitle from '../../sidebar/components/assignees/assignee_title';
import assigneeTitle from '../../sidebar/components/assignees/assignee_title.vue';
import assignees from '../../sidebar/components/assignees/assignees.vue';
import DueDateSelectors from '../../due_date_select';
import './sidebar/remove_issue';
......
......@@ -65,20 +65,6 @@ export function capitalizeFirstCharacter(text) {
return `${text[0].toUpperCase()}${text.slice(1)}`;
}
export function camelCase(str) {
return str.replace(/_+([a-z])/gi, ($1, $2) => $2.toUpperCase());
}
export function camelCaseKeys(obj = {}) {
return Object.keys(obj).reduce((acc, key) => {
const camelKey = camelCase(key);
return {
...acc,
[camelKey]: obj[key],
};
}, {});
}
/**
* Replaces all html tags from a string with the given replacement.
*
......
<script>
export default {
name: 'AssigneeTitle',
props: {
......@@ -26,14 +27,18 @@ export default {
return assignees > 1 ? `${assignees} Assignees` : 'Assignee';
},
},
template: `
};
</script>
<template>
<div class="title hide-collapsed">
{{assigneeTitle}}
{{ assigneeTitle }}
<i
v-if="loading"
aria-hidden="true"
class="fa fa-spinner fa-spin block-loading"
/>
>
</i>
<a
v-if="editable"
class="js-sidebar-dropdown-toggle edit-link pull-right"
......@@ -52,8 +57,8 @@ export default {
aria-hidden="true"
data-hidden="true"
class="fa fa-angle-double-right"
/>
>
</i>
</a>
</div>
`,
};
</template>
<script>
import Flash from '../../../flash';
import AssigneeTitle from './assignee_title';
import AssigneeTitle from './assignee_title.vue';
import Assignees from './assignees.vue';
import Store from '../../stores/sidebar_store';
import eventHub from '../../event_hub';
......
......@@ -63,7 +63,7 @@
};
this.isRemovingSourceBranch = true;
this.service.mergeResource.save(options)
this.service.merge(options)
.then(res => res.data)
.then((data) => {
if (data.status === 'merge_when_pipeline_succeeds') {
......
<script>
import { __ } from '~/locale';
import LabelsSelect from '~/labels_select';
import LoadingIcon from '../../loading_icon.vue';
......@@ -31,6 +32,11 @@ export default {
required: false,
default: false,
},
isProject: {
type: Boolean,
required: false,
default: false,
},
abilityName: {
type: String,
required: true,
......@@ -73,6 +79,20 @@ export default {
hiddenInputName() {
return this.showCreate ? `${this.abilityName}[label_names][]` : 'label_id[]';
},
createLabelTitle() {
if (this.isProject) {
return __('Create project label');
}
return __('Create group label');
},
manageLabelsTitle() {
if (this.isProject) {
return __('Manage project labels');
}
return __('Manage group labels');
},
},
mounted() {
this.labelsDropdown = new LabelsSelect(this.$refs.dropdownButton, {
......@@ -137,10 +157,14 @@ dropdown-menu-labels dropdown-menu-selectable"
<dropdown-footer
v-if="showCreate"
:labels-web-url="labelsWebUrl"
:create-label-title="createLabelTitle"
:manage-labels-title="manageLabelsTitle"
/>
</div>
<dropdown-create-label
v-if="showCreate"
:is-project="isProject"
:header-title="createLabelTitle"
/>
</div>
</div>
......
<script>
import { __ } from '~/locale';
export default {
props: {
headerTitle: {
type: String,
required: false,
default: () => __('Create new label'),
},
},
created() {
this.suggestedColors = gon.suggested_label_colors;
},
......@@ -21,7 +30,7 @@ export default {
>
</i>
</button>
{{ __('Create new label') }}
{{ headerTitle }}
<button
type="button"
class="dropdown-title-button dropdown-menu-close"
......
<script>
import { __ } from '~/locale';
export default {
props: {
labelsWebUrl: {
type: String,
required: true,
},
createLabelTitle: {
type: String,
required: false,
default: () => __('Create new label'),
},
manageLabelsTitle: {
type: String,
required: false,
default: () => __('Manage labels'),
},
},
};
</script>
......@@ -17,7 +29,7 @@ export default {
href="#"
class="dropdown-toggle-page"
>
{{ __('Create new label') }}
{{ createLabelTitle }}
</a>
</li>
<li>
......@@ -26,7 +38,7 @@ export default {
class="dropdown-external-link"
:href="labelsWebUrl"
>
{{ __('Manage labels') }}
{{ manageLabelsTitle }}
</a>
</li>
</ul>
......
......@@ -174,6 +174,39 @@ module LabelsHelper
end
end
def create_label_title(subject)
case subject
when Group
_('Create group label')
when Project
_('Create project label')
else
_('Create new label')
end
end
def manage_labels_title(subject)
case subject
when Group
_('Manage group labels')
when Project
_('Manage project labels')
else
_('Manage labels')
end
end
def view_labels_title(subject)
case subject
when Group
_('View group labels')
when Project
_('View project labels')
else
_('View labels')
end
end
# Required for Banzai::Filter::LabelReferenceFilter
module_function :render_colored_label, :text_color_for_bg, :escape_once
end
- subject = @project || @group
.dropdown-page-two.dropdown-new-label
= dropdown_title("Create new label", options: { back: true })
= dropdown_title(create_label_title(subject), options: { back: true })
= dropdown_content do
.dropdown-labels-error.js-label-error
%input#new_label_name.default-dropdown-input{ type: "text", placeholder: _('Name new label') }
......
......@@ -3,6 +3,7 @@
- show_footer = local_assigns.fetch(:show_footer, true)
- filter_placeholder = local_assigns.fetch(:filter_placeholder, 'Search')
- show_boards_content = local_assigns.fetch(:show_boards_content, false)
- subject = @project || @group
.dropdown-page-one
= dropdown_title(title)
- if show_boards_content
......@@ -17,11 +18,11 @@
- if can?(current_user, :admin_label, current_board_parent)
%li
%a.dropdown-toggle-page{ href: "#" }
= _('Create new label')
= create_label_title(subject)
%li
= link_to labels_path, :"data-is-link" => true do
- if show_create && can?(current_user, :admin_label, current_board_parent)
= _('Manage labels')
= manage_labels_title(subject)
- else
= _('View labels')
= view_labels_title(subject)
= dropdown_loading
---
title: Fix "Remove source branch" button in Merge request widget during merge when pipeline
succeeds state
merge_request: 17192
author:
type: fixed
---
title: Update wording to specify create/manage project vs group labels in labels dropdown
merge_request: 17640
author:
type: changed
---
title: Move AssigneeTitle vue component
merge_request: 17397
author: George Tsiolis
type: performance
......@@ -21,13 +21,13 @@ describe 'label issues', :js do
wait_for_requests
end
it 'adds a new label from sidebar' do
it 'adds a new group label from sidebar' do
card = find('.board:nth-child(2)').first('.card')
click_card(card)
page.within '.right-sidebar .labels' do
click_link 'Edit'
click_link 'Create new label'
click_link 'Create group label'
fill_in 'new_label_name', with: 'test label'
first('.suggest-colors-dropdown a').click
click_button 'Create'
......
......@@ -345,7 +345,7 @@ describe 'Issue Boards', :js do
wait_for_requests
click_link 'Create new label'
click_link 'Create project label'
fill_in('new_label_name', with: 'Testing New Label')
......
......@@ -313,12 +313,12 @@ describe 'Issue Boards', :js do
expect(card).not_to have_content(stretch.title)
end
it 'creates new label' do
it 'creates project label' do
click_card(card)
page.within('.labels') do
click_link 'Edit'
click_link 'Create new label'
click_link 'Create project label'
fill_in 'new_label_name', with: 'test label'
first('.suggest-colors-dropdown a').click
click_button 'Create'
......
......@@ -24,7 +24,7 @@ describe 'Sub-group project issue boards', :js do
page.within '.labels' do
click_link 'Edit'
click_link 'Create new label'
click_link 'Create project label'
end
page.within '.dropdown-new-label' do
......
......@@ -310,10 +310,10 @@ describe 'New/edit issue', :js do
visit new_project_issue_path(sub_group_project)
end
it 'creates new label from dropdown' do
it 'creates project label from dropdown' do
click_button 'Labels'
click_link 'Create new label'
click_link 'Create project label'
page.within '.dropdown-new-label' do
fill_in 'new_label_name', with: 'test label'
......
......@@ -117,22 +117,22 @@ feature 'Issue Sidebar' do
end
end
it 'shows option to create a new label' do
it 'shows option to create a project label' do
page.within('.block.labels') do
expect(page).to have_content 'Create new'
expect(page).to have_content 'Create project'
end
end
context 'creating a new label', :js do
context 'creating a project label', :js do
before do
page.within('.block.labels') do
click_link 'Create new'
click_link 'Create project'
end
end
it 'shows dropdown switches to "create label" section' do
page.within('.block.labels') do
expect(page).to have_content 'Create new label'
expect(page).to have_content 'Create project label'
end
end
......
......@@ -125,6 +125,12 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
expect(page).to have_content "canceled the automatic merge"
end
it 'allows to remove source branch' do
click_link "Remove source branch"
expect(page).to have_content "The source branch will be removed"
end
context 'when pipeline succeeds' do
before do
build.success
......
......@@ -139,4 +139,76 @@ describe LabelsHelper do
expect(text_color_for_bg('#000')).to eq '#FFFFFF'
end
end
describe 'create_label_title' do
set(:group) { create(:group) }
context 'with a group as subject' do
it 'returns "Create group label"' do
expect(create_label_title(group)).to eq 'Create group label'
end
end
context 'with a project as subject' do
set(:project) { create(:project, namespace: group) }
it 'returns "Create project label"' do
expect(create_label_title(project)).to eq 'Create project label'
end
end
context 'with no subject' do
it 'returns "Create new label"' do
expect(create_label_title(nil)).to eq 'Create new label'
end
end
end
describe 'manage_labels_title' do
set(:group) { create(:group) }
context 'with a group as subject' do
it 'returns "Manage group labels"' do
expect(manage_labels_title(group)).to eq 'Manage group labels'
end
end
context 'with a project as subject' do
set(:project) { create(:project, namespace: group) }
it 'returns "Manage project labels"' do
expect(manage_labels_title(project)).to eq 'Manage project labels'
end
end
context 'with no subject' do
it 'returns "Manage labels"' do
expect(manage_labels_title(nil)).to eq 'Manage labels'
end
end
end
describe 'view_labels_title' do
set(:group) { create(:group) }
context 'with a group as subject' do
it 'returns "View group labels"' do
expect(view_labels_title(group)).to eq 'View group labels'
end
end
context 'with a project as subject' do
set(:project) { create(:project, namespace: group) }
it 'returns "View project labels"' do
expect(view_labels_title(project)).to eq 'View project labels'
end
end
context 'with no subject' do
it 'returns "View labels"' do
expect(view_labels_title(nil)).to eq 'View labels'
end
end
end
end
import Vue from 'vue';
import AssigneeTitle from '~/sidebar/components/assignees/assignee_title';
import AssigneeTitle from '~/sidebar/components/assignees/assignee_title.vue';
describe('AssigneeTitle component', () => {
let component;
......
import Vue from 'vue';
import mwpsComponent from '~/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
import eventHub from '~/vue_merge_request_widget/event_hub';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
......@@ -25,12 +26,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
targetBranchPath,
targetBranch,
},
service: {
cancelAutomaticMerge() {},
mergeResource: {
save() {},
},
},
service: new MRWidgetService({}),
});
});
......@@ -90,18 +86,16 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
describe('removeSourceBranch', () => {
it('should set flag and call service then request main component to update the widget', (done) => {
spyOn(vm.service.mergeResource, 'save').and.returnValue(new Promise((resolve) => {
resolve({
spyOn(vm.service, 'merge').and.returnValue(Promise.resolve({
data: {
status: 'merge_when_pipeline_succeeds',
},
});
}));
vm.removeSourceBranch();
setTimeout(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
expect(vm.service.mergeResource.save).toHaveBeenCalledWith({
expect(vm.service.merge).toHaveBeenCalledWith({
sha,
merge_when_pipeline_succeeds: true,
should_remove_source_branch: true,
......
......@@ -37,6 +37,32 @@ describe('BaseComponent', () => {
vmNonEditable.$destroy();
});
});
describe('createLabelTitle', () => {
it('returns `Create project label` when `isProject` prop is true', () => {
expect(vm.createLabelTitle).toBe('Create project label');
});
it('return `Create group label` when `isProject` prop is false', () => {
const mockConfigGroup = Object.assign({}, mockConfig, { isProject: false });
const vmGroup = createComponent(mockConfigGroup);
expect(vmGroup.createLabelTitle).toBe('Create group label');
vmGroup.$destroy();
});
});
describe('manageLabelsTitle', () => {
it('returns `Manage project labels` when `isProject` prop is true', () => {
expect(vm.manageLabelsTitle).toBe('Manage project labels');
});
it('return `Manage group labels` when `isProject` prop is false', () => {
const mockConfigGroup = Object.assign({}, mockConfig, { isProject: false });
const vmGroup = createComponent(mockConfigGroup);
expect(vmGroup.manageLabelsTitle).toBe('Manage group labels');
vmGroup.$destroy();
});
});
});
describe('methods', () => {
......
......@@ -6,10 +6,12 @@ import { mockSuggestedColors } from './mock_data';
import mountComponent from '../../../../helpers/vue_mount_component_helper';
const createComponent = () => {
const createComponent = (headerTitle) => {
const Component = Vue.extend(dropdownCreateLabelComponent);
return mountComponent(Component);
return mountComponent(Component, {
headerTitle,
});
};
describe('DropdownCreateLabelComponent', () => {
......@@ -41,11 +43,19 @@ describe('DropdownCreateLabelComponent', () => {
expect(backButtonEl.querySelector('.fa-arrow-left')).not.toBe(null);
});
it('renders component header element', () => {
it('renders component header element as `Create new label` when `headerTitle` prop is not provided', () => {
const headerEl = vm.$el.querySelector('.dropdown-title');
expect(headerEl.innerText.trim()).toContain('Create new label');
});
it('renders component header element with value of `headerTitle` prop', () => {
const headerTitle = 'Create project label';
const vmWithHeaderTitle = createComponent(headerTitle);
const headerEl = vmWithHeaderTitle.$el.querySelector('.dropdown-title');
expect(headerEl.innerText.trim()).toContain(headerTitle);
vmWithHeaderTitle.$destroy();
});
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);
......
......@@ -6,15 +6,23 @@ import { mockConfig } from './mock_data';
import mountComponent from '../../../../helpers/vue_mount_component_helper';
const createComponent = (labelsWebUrl = mockConfig.labelsWebUrl) => {
const createComponent = (
labelsWebUrl = mockConfig.labelsWebUrl,
createLabelTitle,
manageLabelsTitle,
) => {
const Component = Vue.extend(dropdownFooterComponent);
return mountComponent(Component, {
labelsWebUrl,
createLabelTitle,
manageLabelsTitle,
});
};
describe('DropdownFooterComponent', () => {
const createLabelTitle = 'Create project label';
const manageLabelsTitle = 'Manage project labels';
let vm;
beforeEach(() => {
......@@ -26,17 +34,35 @@ describe('DropdownFooterComponent', () => {
});
describe('template', () => {
it('renders `Create new label` link element', () => {
it('renders link element with `Create new label` when `createLabelTitle` prop is not provided', () => {
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', () => {
it('renders link element with value of `createLabelTitle` prop', () => {
const vmWithCreateLabelTitle = createComponent(mockConfig.labelsWebUrl, createLabelTitle);
const createLabelEl = vmWithCreateLabelTitle.$el.querySelector('.dropdown-footer-list .dropdown-toggle-page');
expect(createLabelEl.innerText.trim()).toBe(createLabelTitle);
vmWithCreateLabelTitle.$destroy();
});
it('renders link element with `Manage labels` when `manageLabelsTitle` prop is not provided', () => {
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');
});
it('renders link element with value of `manageLabelsTitle` prop', () => {
const vmWithManageLabelsTitle = createComponent(
mockConfig.labelsWebUrl,
createLabelTitle,
manageLabelsTitle,
);
const manageLabelsEl = vmWithManageLabelsTitle.$el.querySelector('.dropdown-footer-list .dropdown-external-link');
expect(manageLabelsEl.innerText.trim()).toBe(manageLabelsTitle);
vmWithManageLabelsTitle.$destroy();
});
});
});
......@@ -34,6 +34,7 @@ export const mockSuggestedColors = [
export const mockConfig = {
showCreate: true,
isProject: true,
abilityName: 'issue',
context: {
labels: mockLabels,
......
......@@ -137,7 +137,7 @@ sast:container:
dast:
stage: dast
allow_failure: true
image: owasp/zap2docker-stable
image: registry.gitlab.com/gitlab-org/security-products/zaproxy
variables:
POSTGRES_DB: "false"
script:
......
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