Commit 76e772e7 authored by Valery Sizov's avatar Valery Sizov Committed by Alfredo Sumaran

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ee into ce_upstream

parents 0f455038 7df466f7
import Vue from 'vue';
import Visibility from 'visibilityjs';
import PipelinesTableComponent from '../../vue_shared/components/pipelines_table';
import PipelinesService from '../../vue_pipelines_index/services/pipelines_service';
import PipelineStore from '../../vue_pipelines_index/stores/pipelines_store';
import eventHub from '../../vue_pipelines_index/event_hub';
import EmptyState from '../../vue_pipelines_index/components/empty_state.vue';
import ErrorState from '../../vue_pipelines_index/components/error_state.vue';
import PipelinesService from '../../pipelines/services/pipelines_service';
import PipelineStore from '../../pipelines/stores/pipelines_store';
import eventHub from '../../pipelines/event_hub';
import EmptyState from '../../pipelines/components/empty_state.vue';
import ErrorState from '../../pipelines/components/error_state.vue';
import '../../lib/utils/common_utils';
import '../../vue_shared/vue_resource_interceptor';
import Poll from '../../lib/utils/poll';
......
......@@ -3,8 +3,7 @@
import Vue from 'vue';
(() => {
const CommentAndResolveBtn = Vue.extend({
const CommentAndResolveBtn = Vue.extend({
props: {
discussionId: String,
},
......@@ -61,7 +60,6 @@ import Vue from 'vue';
$(`.js-discussion-note-form[data-discussion-id=${this.discussionId}] .note-textarea`).off('input.comment-and-resolve-btn');
}
});
});
Vue.component('comment-and-resolve-btn', CommentAndResolveBtn);
})(window);
Vue.component('comment-and-resolve-btn', CommentAndResolveBtn);
......@@ -4,8 +4,7 @@
import Vue from 'vue';
import collapseIcon from '../icons/collapse_icon.svg';
(() => {
const DiffNoteAvatars = Vue.extend({
const DiffNoteAvatars = Vue.extend({
props: ['discussionId'],
data() {
return {
......@@ -152,7 +151,6 @@ import collapseIcon from '../icons/collapse_icon.svg';
this.isVisible = $(`.diffs .notes[data-discussion-id="${this.discussion.id}"]`).is(':visible');
},
},
});
});
Vue.component('diff-note-avatars', DiffNoteAvatars);
})();
Vue.component('diff-note-avatars', DiffNoteAvatars);
......@@ -4,8 +4,7 @@
import Vue from 'vue';
(() => {
const JumpToDiscussion = Vue.extend({
const JumpToDiscussion = Vue.extend({
mixins: [DiscussionMixins],
props: {
discussionId: String
......@@ -189,7 +188,6 @@ import Vue from 'vue';
created() {
this.discussion = this.discussions[this.discussionId];
},
});
});
Vue.component('jump-to-discussion', JumpToDiscussion);
})();
Vue.component('jump-to-discussion', JumpToDiscussion);
......@@ -2,8 +2,7 @@
import Vue from 'vue';
(() => {
const NewIssueForDiscussion = Vue.extend({
const NewIssueForDiscussion = Vue.extend({
props: {
discussionId: {
type: String,
......@@ -24,7 +23,6 @@ import Vue from 'vue';
return false;
},
},
});
});
Vue.component('new-issue-for-discussion-btn', NewIssueForDiscussion);
})();
Vue.component('new-issue-for-discussion-btn', NewIssueForDiscussion);
......@@ -5,8 +5,7 @@
import Vue from 'vue';
(() => {
const ResolveBtn = Vue.extend({
const ResolveBtn = Vue.extend({
props: {
noteId: Number,
discussionId: String,
......@@ -20,7 +19,7 @@ import Vue from 'vue';
data: function () {
return {
discussions: CommentsStore.state,
loading: false
loading: false,
};
},
watch: {
......@@ -115,7 +114,6 @@ import Vue from 'vue';
noteTruncated: this.noteTruncated,
});
}
});
});
Vue.component('resolve-btn', ResolveBtn);
})();
Vue.component('resolve-btn', ResolveBtn);
......@@ -4,8 +4,7 @@
import Vue from 'vue';
((w) => {
w.ResolveCount = Vue.extend({
window.ResolveCount = Vue.extend({
mixins: [DiscussionMixins],
props: {
loggedOut: Boolean
......@@ -23,5 +22,4 @@ import Vue from 'vue';
return this.discussionCount === 1 ? 'discussion' : 'discussions';
}
}
});
})(window);
});
......@@ -4,8 +4,7 @@
import Vue from 'vue';
(() => {
const ResolveDiscussionBtn = Vue.extend({
const ResolveDiscussionBtn = Vue.extend({
props: {
discussionId: String,
mergeRequestId: Number,
......@@ -56,7 +55,6 @@ import Vue from 'vue';
this.discussion = CommentsStore.state[this.discussionId];
}
});
});
Vue.component('resolve-discussion-btn', ResolveDiscussionBtn);
})();
Vue.component('resolve-discussion-btn', ResolveDiscussionBtn);
/* eslint-disable object-shorthand, func-names, guard-for-in, no-restricted-syntax, comma-dangle, no-param-reassign, max-len */
((w) => {
w.DiscussionMixins = {
window.DiscussionMixins = {
computed: {
discussionCount: function () {
return Object.keys(this.discussions).length;
......@@ -33,5 +32,4 @@
return unresolvedCount;
}
}
};
})(window);
};
......@@ -9,10 +9,9 @@ require('../../vue_shared/vue_resource_interceptor');
Vue.use(VueResource);
(() => {
window.gl = window.gl || {};
window.gl = window.gl || {};
class ResolveServiceClass {
class ResolveServiceClass {
constructor(root) {
this.noteResource = Vue.resource(`${root}/notes{/noteId}/resolve`);
this.discussionResource = Vue.resource(`${root}/merge_requests{/mergeRequestId}/discussions{/discussionId}/resolve`);
......@@ -78,7 +77,6 @@ Vue.use(VueResource);
discussionId
}, {});
}
}
}
gl.DiffNotesResolveServiceClass = ResolveServiceClass;
})();
gl.DiffNotesResolveServiceClass = ResolveServiceClass;
......@@ -3,8 +3,7 @@
import Vue from 'vue';
((w) => {
w.CommentsStore = {
window.CommentsStore = {
state: {},
get: function (discussionId, noteId) {
return this.state[discussionId].getNote(noteId);
......@@ -54,5 +53,4 @@ import Vue from 'vue';
return ids;
}
};
})(window);
};
......@@ -130,13 +130,17 @@ window.DropzoneInput = (function() {
var afterSelection, beforeSelection, caretEnd, caretStart, textEnd;
var formattedText = text;
if (shouldPad) formattedText += "\n\n";
caretStart = $(child)[0].selectionStart;
caretEnd = $(child)[0].selectionEnd;
const textarea = child.get(0);
caretStart = textarea.selectionStart;
caretEnd = textarea.selectionEnd;
caretStart = textarea.selectionStart;
caretEnd = textarea.selectionEnd;
textEnd = $(child).val().length;
beforeSelection = $(child).val().substring(0, caretStart);
afterSelection = $(child).val().substring(caretEnd, textEnd);
$(child).val(beforeSelection + formattedText + afterSelection);
child.get(0).setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length);
textarea.setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length);
textarea.style.height = `${textarea.scrollHeight}px`;
return form_textarea.trigger("input");
};
getFilename = function(e) {
......@@ -180,7 +184,7 @@ window.DropzoneInput = (function() {
};
insertToTextArea = function(filename, url) {
return $(child).val(function(index, val) {
return val.replace("{{" + filename + "}}", url + "\n");
return val.replace("{{" + filename + "}}", url);
});
};
appendToTextArea = function(url) {
......@@ -215,6 +219,7 @@ window.DropzoneInput = (function() {
form.find(".markdown-selector").click(function(e) {
e.preventDefault();
$(this).closest('.gfm-form').find('.div-dropzone').click();
form_textarea.focus();
});
}
......
......@@ -5,7 +5,6 @@ export default {
avatarUrl: {
type: String,
required: false,
default: '/assets/no_avatar.png',
},
profileUrl: {
type: String,
......
/* eslint-disable no-param-reassign */
import AsyncButtonComponent from '../../vue_pipelines_index/components/async_button.vue';
import PipelinesActionsComponent from '../../vue_pipelines_index/components/pipelines_actions';
import PipelinesArtifactsComponent from '../../vue_pipelines_index/components/pipelines_artifacts';
import PipelinesStatusComponent from '../../vue_pipelines_index/components/status';
import PipelinesStageComponent from '../../vue_pipelines_index/components/stage';
import PipelinesUrlComponent from '../../vue_pipelines_index/components/pipeline_url';
import PipelinesTimeagoComponent from '../../vue_pipelines_index/components/time_ago';
import AsyncButtonComponent from '../../pipelines/components/async_button.vue';
import PipelinesActionsComponent from '../../pipelines/components/pipelines_actions';
import PipelinesArtifactsComponent from '../../pipelines/components/pipelines_artifacts';
import PipelinesStatusComponent from '../../pipelines/components/status';
import PipelinesStageComponent from '../../pipelines/components/stage';
import PipelinesUrlComponent from '../../pipelines/components/pipeline_url';
import PipelinesTimeagoComponent from '../../pipelines/components/time_ago';
import CommitComponent from './commit';
/**
......
......@@ -9,19 +9,20 @@ module Search
end
def execute
group = Group.find_by(id: params[:group_id]) if params[:group_id].present?
projects = ProjectsFinder.new(current_user: current_user).execute
if current_application_settings.elasticsearch_search?
Gitlab::Elastic::SearchResults.new(current_user, params[:search], elastic_projects, elastic_global)
else
Gitlab::SearchResults.new(current_user, projects, params[:search])
end
end
if group
projects = projects.inside_path(group.full_path)
def projects
@projects ||= ProjectsFinder.new(current_user: current_user).execute
end
if current_application_settings.elasticsearch_search?
projects_spec =
if group
projects.pluck(:id)
else
if current_user && current_user.admin_or_auditor?
def elastic_projects
@elastic_projects ||=
if current_user.try(:admin_or_auditor?)
:any
elsif current_user
current_user.authorized_projects.pluck(:id)
......@@ -30,15 +31,8 @@ module Search
end
end
Gitlab::Elastic::SearchResults.new(
current_user,
params[:search],
projects_spec,
!group # Ignore public projects outside of the group if provided
)
else
Gitlab::SearchResults.new(current_user, projects, params[:search])
end
def elastic_global
true
end
def scope
......
module Search
class GroupService < Search::GlobalService
attr_accessor :group
def initialize(user, group, params)
super(user, params)
@group = group
end
def projects
return Project.none unless group
return @projects if defined? @projects
@projects = super.inside_path(group.full_path)
end
def elastic_projects
@elastic_projects ||= projects.pluck(:id)
end
def elastic_global
false
end
end
end
......@@ -54,6 +54,8 @@ class SearchService
Search::ProjectService.new(project, current_user, params)
elsif show_snippets?
Search::SnippetService.new(current_user, params)
elsif group
Search::GroupService.new(current_user, group, params)
else
Search::GlobalService.new(current_user, params)
end
......
......@@ -21,4 +21,4 @@
"ci-lint-path" => ci_lint_path } }
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('vue_pipelines')
= page_specific_javascript_bundle_tag('pipelines')
---
title: refocus textarea after attaching a file
merge_request:
author:
......@@ -19,13 +19,12 @@ var WEBPACK_REPORT = process.env.WEBPACK_REPORT;
var config = {
context: path.join(ROOT_PATH, 'app/assets/javascripts'),
entry: {
common: './commons/index.js',
common_vue: ['vue', './vue_shared/common_vue.js'],
common_d3: ['d3'],
main: './main.js',
blob: './blob_edit/blob_bundle.js',
boards: './boards/boards_bundle.js',
burndown_chart: './burndown_chart/index.js',
common: './commons/index.js',
common_vue: ['vue', './vue_shared/common_vue.js'],
common_d3: ['d3'],
cycle_analytics: './cycle_analytics/cycle_analytics_bundle.js',
commit_pipelines: './commit/pipelines/pipelines_bundle.js',
diff_notes: './diff_notes/diff_notes_bundle.js',
......@@ -33,28 +32,29 @@ var config = {
environments_folder: './environments/folder/environments_folder_bundle.js',
filtered_search: './filtered_search/filtered_search_bundle.js',
graphs: './graphs/graphs_bundle.js',
group: './group.js',
groups_list: './groups_list.js',
issues: './issues/issues_bundle.js',
issuable: './issuable/issuable_bundle.js',
issue_show: './issue_show/index.js',
main: './main.js',
merge_conflicts: './merge_conflicts/merge_conflicts_bundle.js',
merge_request_widget: './merge_request_widget/ci_bundle.js',
mr_widget_ee: './merge_request_widget/widget_bundle.js',
monitoring: './monitoring/monitoring_bundle.js',
network: './network/network_bundle.js',
notebook_viewer: './blob/notebook_viewer.js',
sketch_viewer: './blob/sketch_viewer.js',
pdf_viewer: './blob/pdf_viewer.js',
pipelines: './pipelines/index.js',
profile: './profile/profile_bundle.js',
protected_branches: './protected_branches/protected_branches_bundle.js',
protected_tags: './protected_tags',
snippet: './snippet/snippet_bundle.js',
sketch_viewer: './blob/sketch_viewer.js',
stl_viewer: './blob/stl_viewer.js',
terminal: './terminal/terminal_bundle.js',
u2f: ['vendor/u2f'],
users: './users/users_bundle.js',
vue_pipelines: './vue_pipelines_index/index.js',
issue_show: './issue_show/index.js',
group: './group.js',
},
output: {
......@@ -124,10 +124,11 @@ var config = {
'environments',
'environments_folder',
'issuable',
'issue_show',
'merge_conflicts',
'notebook_viewer',
'pdf_viewer',
'vue_pipelines',
'pipelines',
'mr_widget_ee',
'issue_show'
],
......
......@@ -5,8 +5,7 @@ require('~/diff_notes/models/discussion');
require('~/diff_notes/models/note');
require('~/diff_notes/stores/comments');
(() => {
function createDiscussion(noteId = 1, resolved = true) {
function createDiscussion(noteId = 1, resolved = true) {
CommentsStore.create({
discussionId: 'a',
noteId,
......@@ -17,13 +16,13 @@ require('~/diff_notes/stores/comments');
authorAvatar: 'test',
noteTruncated: 'test...',
});
}
}
beforeEach(() => {
beforeEach(() => {
CommentsStore.state = {};
});
});
describe('New discussion', () => {
describe('New discussion', () => {
it('creates new discussion', () => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -37,9 +36,9 @@ require('~/diff_notes/stores/comments');
const discussion = CommentsStore.state['a'];
expect(Object.keys(discussion.notes).length).toBe(2);
});
});
});
describe('Get note', () => {
describe('Get note', () => {
beforeEach(() => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -50,9 +49,9 @@ require('~/diff_notes/stores/comments');
expect(note).toBeDefined();
expect(note.id).toBe(1);
});
});
});
describe('Delete discussion', () => {
describe('Delete discussion', () => {
beforeEach(() => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -73,9 +72,9 @@ require('~/diff_notes/stores/comments');
CommentsStore.delete('a', 2);
expect(Object.keys(CommentsStore.state).length).toBe(0);
});
});
});
describe('Update note', () => {
describe('Update note', () => {
beforeEach(() => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -87,9 +86,9 @@ require('~/diff_notes/stores/comments');
const note = CommentsStore.get('a', 1);
expect(note.resolved).toBe(false);
});
});
});
describe('Discussion resolved', () => {
describe('Discussion resolved', () => {
beforeEach(() => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -129,5 +128,4 @@ require('~/diff_notes/stores/comments');
discussion.unResolveAllNotes();
expect(discussion.isResolved()).toBe(false);
});
});
})();
});
import Vue from 'vue';
import asyncButtonComp from '~/vue_pipelines_index/components/async_button.vue';
import asyncButtonComp from '~/pipelines/components/async_button.vue';
describe('Pipelines Async Button', () => {
let component;
......
import Vue from 'vue';
import emptyStateComp from '~/vue_pipelines_index/components/empty_state.vue';
import emptyStateComp from '~/pipelines/components/empty_state.vue';
describe('Pipelines Empty State', () => {
let component;
......
import Vue from 'vue';
import errorStateComp from '~/vue_pipelines_index/components/error_state.vue';
import errorStateComp from '~/pipelines/components/error_state.vue';
describe('Pipelines Error State', () => {
let component;
......
import Vue from 'vue';
import navControlsComp from '~/vue_pipelines_index/components/nav_controls';
import navControlsComp from '~/pipelines/components/nav_controls';
describe('Pipelines Nav Controls', () => {
let NavControlsComponent;
......
import Vue from 'vue';
import pipelineUrlComp from '~/vue_pipelines_index/components/pipeline_url';
import pipelineUrlComp from '~/pipelines/components/pipeline_url';
describe('Pipeline Url Component', () => {
let PipelineUrlComponent;
......
import Vue from 'vue';
import pipelinesActionsComp from '~/vue_pipelines_index/components/pipelines_actions';
import pipelinesActionsComp from '~/pipelines/components/pipelines_actions';
describe('Pipelines Actions dropdown', () => {
let component;
......
import Vue from 'vue';
import artifactsComp from '~/vue_pipelines_index/components/pipelines_artifacts';
import artifactsComp from '~/pipelines/components/pipelines_artifacts';
describe('Pipelines Artifacts dropdown', () => {
let component;
......
import Vue from 'vue';
import pipelinesComp from '~/vue_pipelines_index/pipelines';
import Store from '~/vue_pipelines_index/stores/pipelines_store';
import pipelinesComp from '~/pipelines/pipelines';
import Store from '~/pipelines/stores/pipelines_store';
import pipelinesData from './mock_data';
describe('Pipelines', () => {
......
import PipelineStore from '~/vue_pipelines_index/stores/pipelines_store';
import PipelineStore from '~/pipelines/stores/pipelines_store';
describe('Pipelines Store', () => {
let store;
......
......@@ -40,27 +40,6 @@ describe Search::GlobalService, services: true do
expect(results.objects('projects')).to match_array [found_project]
end
context 'nested group' do
let!(:nested_group) { create(:group, :nested) }
let!(:project) { create(:empty_project, namespace: nested_group) }
before do
project.add_master(user)
end
it 'returns result from nested group' do
results = Search::GlobalService.new(user, search: project.path).execute
expect(results.objects('projects')).to match_array [project]
end
it 'returns result from descendants when search inside group' do
results = Search::GlobalService.new(user, search: project.path, group_id: nested_group.parent).execute
expect(results.objects('projects')).to match_array [project]
end
end
end
end
end
require 'spec_helper'
describe Search::GroupService, services: true do
shared_examples_for 'group search' do
context 'finding projects by name' do
let(:user) { create(:user) }
let(:term) { "Project Name" }
let(:nested_group) { create(:group, :nested) }
# These projects shouldn't be found
let!(:outside_project) { create(:empty_project, :public, name: "Outside #{term}") }
let!(:private_project) { create(:empty_project, :private, namespace: nested_group, name: "Private #{term}" )}
let!(:other_project) { create(:empty_project, :public, namespace: nested_group, name: term.reverse) }
# These projects should be found
let!(:project1) { create(:empty_project, :internal, namespace: nested_group, name: "Inner #{term} 1") }
let!(:project2) { create(:empty_project, :internal, namespace: nested_group, name: "Inner #{term} 2") }
let!(:project3) { create(:empty_project, :internal, namespace: nested_group.parent, name: "Outer #{term}") }
let(:results) { Search::GroupService.new(user, search_group, search: term).execute }
subject { results.objects('projects') }
context 'in parent group' do
let(:search_group) { nested_group.parent }
it { is_expected.to match_array([project1, project2, project3]) }
end
context 'in subgroup' do
let(:search_group) { nested_group }
it { is_expected.to match_array([project1, project2]) }
end
end
end
describe 'basic search' do
include_examples 'group search'
end
describe 'elasticsearch' do
before(:each) do
stub_application_setting(elasticsearch_search: true, elasticsearch_indexing: true)
Gitlab::Elastic::Helper.create_empty_index
# Ensure these are present when the index is refreshed
_ = [
outside_project, private_project, other_project,
project1, project2, project3,
]
Gitlab::Elastic::Helper.refresh_index
end
after(:each) do
Gitlab::Elastic::Helper.delete_index
end
include_examples 'group search'
end
end
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