Commit 1af3f3b6 by James Edwards-Jones

Merge branch 'master' into jej-pages-picked-from-ee

parents 67c85260 bd8f2b15
Pipeline #6279257 failed with stages
in 93 minutes 44 seconds
......@@ -17,6 +17,7 @@ AllCops:
# Exclude some GitLab files
Exclude:
- 'vendor/**/*'
- 'node_modules/**/*'
- 'db/*'
- 'db/fixtures/**/*'
- 'tmp/**/*'
......
......@@ -112,7 +112,7 @@ gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.2'
gem 'asciidoctor-plantuml', '0.0.6'
gem 'asciidoctor-plantuml', '0.0.7'
gem 'rouge', '~> 2.0'
gem 'truncato', '~> 0.7.8'
......
......@@ -54,7 +54,7 @@ GEM
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0)
asciidoctor (1.5.3)
asciidoctor-plantuml (0.0.6)
asciidoctor-plantuml (0.0.7)
asciidoctor (~> 1.5)
ast (2.3.0)
attr_encrypted (3.0.3)
......@@ -844,7 +844,7 @@ DEPENDENCIES
allocations (~> 1.0)
asana (~> 0.4.0)
asciidoctor (~> 1.5.2)
asciidoctor-plantuml (= 0.0.6)
asciidoctor-plantuml (= 0.0.7)
attr_encrypted (~> 3.0.0)
awesome_print (~> 1.2.0)
babosa (~> 1.0.2)
......
/* eslint-disable wrap-iife, func-names, space-before-function-paren, prefer-arrow-callback, vars-on-top, no-var, max-len */
(function(w) {
$(function() {
var toggleContainer = function(container, /* optional */toggleState) {
var $container = $(container);
$container
.find('.js-toggle-button .fa')
.toggleClass('fa-chevron-up', toggleState)
.toggleClass('fa-chevron-down', toggleState !== undefined ? !toggleState : undefined);
$container
.find('.js-toggle-content')
.toggle(toggleState);
};
// Toggle button. Show/hide content inside parent container.
// Button does not change visibility. If button has icon - it changes chevron style.
//
......@@ -10,14 +23,7 @@
//
$('body').on('click', '.js-toggle-button', function(e) {
e.preventDefault();
$(this)
.find('.fa')
.toggleClass('fa-chevron-down fa-chevron-up')
.end()
.closest('.js-toggle-container')
.find('.js-toggle-content')
.toggle()
;
toggleContainer($(this).closest('.js-toggle-container'));
});
// If we're accessing a permalink, ensure it is not inside a
......@@ -26,8 +32,8 @@
var anchor = hash && document.getElementById(hash);
var container = anchor && $(anchor).closest('.js-toggle-container');
if (container && container.find('.js-toggle-content').is(':hidden')) {
container.find('.js-toggle-button').trigger('click');
if (container) {
toggleContainer(container, true);
anchor.scrollIntoView();
}
});
......
......@@ -180,9 +180,9 @@
<tr>
<th class="environments-name">Environment</th>
<th class="environments-deploy">Last deployment</th>
<th class="environments-build">Build</th>
<th class="environments-build">Job</th>
<th class="environments-commit">Commit</th>
<th class="environments-date">Created</th>
<th class="environments-date">Updated</th>
<th class="hidden-xs environments-actions"></th>
</tr>
</thead>
......
......@@ -39,8 +39,15 @@
getSearchInput() {
const query = gl.DropdownUtils.getSearchInput(this.input);
const { lastToken } = gl.FilteredSearchTokenizer.processTokens(query);
let value = lastToken.value || '';
return lastToken.value || '';
// Removes the first character if it is a quotation so that we can search
// with multiple words
if (value[0] === '"' || value[0] === '\'') {
value = value.slice(1);
}
return value;
}
init() {
......
......@@ -83,12 +83,12 @@
_a = decodeURI("%C3%80");
_y = decodeURI("%C3%BF");
regexp = new RegExp("^(?:\\B|[^a-zA-Z0-9_" + atSymbolsWithoutBar + "]|\\s)" + flag + "(?![" + atSymbolsWithBar + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi');
regexp = new RegExp("^(?:\\B|[^a-zA-Z0-9_" + atSymbolsWithoutBar + "]|\\s)" + flag + "(?![" + atSymbolsWithBar + "])(([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]|[^\\x00-\\x7a])*)$", 'gi');
match = regexp.exec(subtext);
if (match) {
return match[2] || match[1];
return (match[1] || match[1] === "") ? match[1] : match[2];
} else {
return null;
}
......
......@@ -249,7 +249,7 @@
_this.fullData = data;
_this.parseData(_this.fullData);
_this.focusTextInput();
if (_this.options.filterable && _this.filter && _this.filter.input && _this.filter.input.val().trim() !== '') {
if (_this.options.filterable && _this.filter && _this.filter.input && _this.filter.input.val() && _this.filter.input.val().trim() !== '') {
return _this.filter.input.trigger('input');
}
};
......
......@@ -162,6 +162,7 @@
w.gl.utils.getSelectedFragment = () => {
const selection = window.getSelection();
if (selection.rangeCount === 0) return null;
const documentFragment = selection.getRangeAt(0).cloneContents();
if (documentFragment.textContent.length === 0) return null;
......
......@@ -110,9 +110,8 @@
};
MergeRequest.prototype.initCommitMessageListeners = function() {
var textarea = $('textarea.js-commit-message');
$('a.js-with-description-link').on('click', function(e) {
$(document).on('click', 'a.js-with-description-link', function(e) {
var textarea = $('textarea.js-commit-message');
e.preventDefault();
textarea.val(textarea.data('messageWithDescription'));
......@@ -120,7 +119,8 @@
$('p.js-without-description-hint').show();
});
$('a.js-without-description-link').on('click', function(e) {
$(document).on('click', 'a.js-without-description-link', function(e) {
var textarea = $('textarea.js-commit-message');
e.preventDefault();
textarea.val(textarea.data('messageWithoutDescription'));
......
......@@ -154,12 +154,22 @@
return;
}
if (data.environments && data.environments.length) _this.renderEnvironments(data.environments);
if (data.status !== _this.opts.ci_status && (data.status != null)) {
if (data.status !== _this.opts.ci_status ||
data.sha !== _this.opts.ci_sha ||
data.pipeline !== _this.opts.ci_pipeline) {
_this.opts.ci_status = data.status;
_this.showCIStatus(data.status);
if (data.coverage) {
_this.showCICoverage(data.coverage);
}
if (data.pipeline) {
_this.opts.ci_pipeline = data.pipeline;
_this.updatePipelineUrls(data.pipeline);
}
if (data.sha) {
_this.opts.ci_sha = data.sha;
_this.updateCommitUrls(data.sha);
}
if (showNotification) {
status = _this.ciLabelForStatus(data.status);
if (status === "preparing") {
......@@ -248,6 +258,16 @@
return $('.js-merge-button,.accept-action .dropdown-toggle').removeClass('btn-danger btn-info btn-create').addClass(css_class);
};
MergeRequestWidget.prototype.updatePipelineUrls = function(id) {
const pipelineUrl = this.opts.pipeline_path;
$('.pipeline').text(`#${id}`).attr('href', [pipelineUrl, id].join('/'));
};
MergeRequestWidget.prototype.updateCommitUrls = function(id) {
const commitsUrl = this.opts.commits_path;
$('.js-commit-link').text(`#${id}`).attr('href', [commitsUrl, id].join('/'));
};
return MergeRequestWidget;
})();
})(window.gl || (window.gl = {}));
......@@ -58,6 +58,11 @@
};
Project.prototype.initRefSwitcher = function() {
var refListItem = document.createElement('li'),
refLink = document.createElement('a');
refLink.href = '#';
return $('.js-project-refs-dropdown').each(function() {
var $dropdown, selected;
$dropdown = $(this);
......@@ -67,7 +72,8 @@
return $.ajax({
url: $dropdown.data('refs-url'),
data: {
ref: $dropdown.data('ref')
ref: $dropdown.data('ref'),
search: term
},
dataType: "json"
}).done(function(refs) {
......@@ -76,16 +82,29 @@
},
selectable: true,
filterable: true,
filterRemote: true,
filterByText: true,
fieldName: $dropdown.data('field-name'),
renderRow: function(ref) {
var link;
var li = refListItem.cloneNode(false);
if (ref.header != null) {
return $('<li />').addClass('dropdown-header').text(ref.header);
li.className = 'dropdown-header';
li.textContent = ref.header;
} else {
link = $('<a />').attr('href', '#').addClass(ref === selected ? 'is-active' : '').text(ref).attr('data-ref', ref);
return $('<li />').append(link);
var link = refLink.cloneNode(false);
if (ref === selected) {
link.className = 'is-active';
}
link.textContent = ref;
link.dataset.ref = ref;
li.appendChild(link);
}
return li;
},
id: function(obj, $el) {
return $el.attr('data-ref');
......
......@@ -49,7 +49,7 @@ class ProtectedBranchDropdown {
onClickCreateWildcard() {
// Refresh the dropdown's data, which ends up calling `getProtectedBranches`
this.$dropdown.data('glDropdown').remote.execute();
this.$dropdown.data('glDropdown').selectRowAtIndex(0);
this.$dropdown.data('glDropdown').selectRowAtIndex();
}
getProtectedBranches(term, callback) {
......
......@@ -39,17 +39,20 @@
}
ShortcutsIssuable.prototype.replyWithSelectedText = function() {
var quote, replyField, documentFragment, selected, separator;
var quote, documentFragment, selected, separator;
var replyField = $('.js-main-target-form #note_note');
documentFragment = window.gl.utils.getSelectedFragment();
if (!documentFragment) return;
if (!documentFragment) {
replyField.focus();
return;
}
// If the documentFragment contains more than just Markdown, don't copy as GFM.
if (documentFragment.querySelector('.md, .wiki')) return;
selected = window.gl.CopyAsGFM.nodeToGFM(documentFragment);
replyField = $('.js-main-target-form #note_note');
if (selected.trim() === "") {
return;
}
......
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, camelcase, vars-on-top, object-shorthand, comma-dangle, eqeqeq, no-mixed-operators, no-return-assign, newline-per-chained-call, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, prefer-template, quotes, no-unused-vars, no-else-return, max-len */
/* global d3 */
/* global dateFormat */
(function() {
var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; };
......@@ -33,7 +32,7 @@
date.setDate(date.getDate() + i);
var day = date.getDay();
var count = timestamps[dateFormat(date, 'yyyy-mm-dd')];
var count = timestamps[date.format('yyyy-mm-dd')];
// Create a new group array if this is the first day of the week
// or if is first object
......@@ -122,7 +121,7 @@
if (stamp.count > 0) {
contribText = stamp.count + " contribution" + (stamp.count > 1 ? 's' : '');
}
dateText = dateFormat(date, 'mmm d, yyyy');
dateText = date.format('mmm d, yyyy');
return contribText + "<br />" + (gl.utils.getDayName(date)) + " " + dateText;
};
})(this)).attr('class', 'user-contrib-cell js-tooltip').attr('fill', (function(_this) {
......
......@@ -26,10 +26,9 @@
v-if='actions'
class="dropdown-toggle btn btn-default has-tooltip js-pipeline-dropdown-manual-actions"
data-toggle="dropdown"
title="Manual build"
title="Manual job"
data-placement="top"
data-toggle="dropdown"
aria-label="Manual build"
aria-label="Manual job"
>
<span v-html='svgs.iconPlay' aria-hidden="true"></span>
<i class="fa fa-caret-down" aria-hidden="true"></i>
......@@ -54,7 +53,6 @@
data-toggle="dropdown"
title="Artifacts"
data-placement="top"
data-toggle="dropdown"
aria-label="Artifacts"
>
<i class="fa fa-download" aria-hidden="true"></i>
......
......@@ -330,10 +330,6 @@
}
}
.btn-file-option {
background: linear-gradient(180deg, $white-light 25%, $gray-light 100%);
}
.btn-build {
margin-left: 10px;
......
......@@ -56,15 +56,24 @@
&.right {
float: right;
padding-right: 0;
}
a {
color: $gl-text-color;
}
.modify-merge-commit-link {
color: $gl-text-color;
}
.remove_source_checkbox {
.merge-param-checkbox {
margin: 0;
}
a .fa-question-circle {
color: $gl-text-color-secondary;
&:hover,
&:focus {
color: $link-hover-color;
}
}
}
}
......
......@@ -467,7 +467,7 @@ ul.notes {
}
.add-diff-note {
margin-top: -4px;
margin-top: -8px;
border-radius: 40px;
background: $white-light;
padding: 4px;
......
......@@ -201,7 +201,8 @@
.stage-container {
display: inline-block;
position: relative;
margin-right: 6px;
height: 22px;
margin: 3px 6px 3px 0;
.tooltip {
white-space: nowrap;
......
......@@ -45,7 +45,7 @@ class Admin::ProjectsController < Admin::ApplicationController
protected
def project
@project = Project.find_with_namespace(
@project = Project.find_by_full_path(
[params[:namespace_id], '/', params[:id]].join('')
)
@project || render_404
......
......@@ -24,7 +24,7 @@ class Admin::RunnerProjectsController < Admin::ApplicationController
private
def project
@project = Project.find_with_namespace(
@project = Project.find_by_full_path(
[params[:namespace_id], '/', params[:project_id]].join('')
)
@project || render_404
......
......@@ -4,13 +4,15 @@ module CreatesCommit
def create_commit(service, success_path:, failure_path:, failure_view: nil, success_notice: nil)
set_commit_variables
start_branch = @mr_target_branch unless initial_commit?
commit_params = @commit_params.merge(
source_project: @project,
source_branch: @ref,
target_branch: @target_branch
start_project: @mr_target_project,
start_branch: start_branch,
target_branch: @mr_source_branch
)
result = service.new(@tree_edit_project, current_user, commit_params).execute
result = service.new(
@mr_source_project, current_user, commit_params).execute
if result[:status] == :success
update_flash_notice(success_notice)
......@@ -89,20 +91,18 @@ module CreatesCommit
@mr_source_project != @mr_target_project
end
def different_branch?
@mr_source_branch != @mr_target_branch || different_project?
end
def create_merge_request?
params[:create_merge_request].present? && different_branch?
# XXX: Even if the field is set, if we're checking the same branch
# as the target branch in the same project,
# we don't want to create a merge request.
params[:create_merge_request].present? &&
(different_project? || @ref != @target_branch)
end
# TODO: We should really clean this up
def set_commit_variables
@mr_source_branch ||= @target_branch
if can?(current_user, :push_code, @project)
# Edit file in this project
@tree_edit_project = @project
@mr_source_project = @project
if @project.forked?
......@@ -112,15 +112,34 @@ module CreatesCommit
else
# Merge request to this project
@mr_target_project = @project
@mr_target_branch ||= @ref
@mr_target_branch = @ref || @target_branch
end
else
# Edit file in fork
@tree_edit_project = current_user.fork_of(@project)
# Merge request from fork to this project
@mr_source_project = @tree_edit_project
@mr_source_project = current_user.fork_of(@project)
@mr_target_project = @project
@mr_target_branch ||= @ref
@mr_target_branch = @ref || @target_branch
end
@mr_source_branch = guess_mr_source_branch
end
def initial_commit?
@mr_target_branch.nil? ||
!@mr_target_project.repository.branch_exists?(@mr_target_branch)
end
def guess_mr_source_branch
# XXX: Happens when viewing a commit without a branch. In this case,
# @target_branch would be the default branch for @mr_source_project,
# however we want a generated new branch here. Thus we can't use
# @target_branch, but should pass nil to indicate that we want a new
# branch instead of @target_branch.
return if
create_merge_request? &&
# XXX: Don't understand why rubocop prefers this indention
@mr_source_project.repository.branch_exists?(@target_branch)
@target_branch
end
end
......@@ -7,7 +7,7 @@ module SpammableActions
def mark_as_spam
if SpamService.new(spammable).mark_as_spam!
redirect_to spammable, notice: "#{spammable.class} was submitted to Akismet successfully."
redirect_to spammable, notice: "#{spammable.spammable_entity_type.titlecase} was submitted to Akismet successfully."
else
redirect_to spammable, alert: 'Error with Akismet. Please check the logs for more info.'
end
......
......@@ -10,10 +10,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page])
@last_push = current_user.recent_push
respond_to do |format|
format.html
format.html { @last_push = current_user.recent_push }
format.atom do
event_filter
load_events
......
......@@ -84,7 +84,7 @@ class GroupsController < Groups::ApplicationController
if Groups::UpdateService.new(@group, current_user, group_params).execute
redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated."
else
@group.reset_path!
@group.restore_path!
render action: "edit"
end
......
......@@ -24,7 +24,7 @@ class Projects::ApplicationController < ApplicationController
end
project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path)
@project = Project.find_by_full_path(project_path)
if can?(current_user, :read_project, @project) && !@project.pending_delete?
if @project.path_with_namespace != project_path
......
......@@ -50,7 +50,7 @@ class Projects::CommitController < Projects::ApplicationController
end
def revert
assign_change_commit_vars(@commit.revert_branch_name)
assign_change_commit_vars
return render_404 if @target_branch.blank?
......@@ -59,7 +59,7 @@ class Projects::CommitController < Projects::ApplicationController
end
def cherry_pick
assign_change_commit_vars(@commit.cherry_pick_branch_name)
assign_change_commit_vars
return render_404 if @target_branch.blank?
......@@ -116,11 +116,9 @@ class Projects::CommitController < Projects::ApplicationController
}
end
def assign_change_commit_vars(mr_source_branch)
def assign_change_commit_vars
@commit = project.commit(params[:id])
@target_branch = params[:target_branch]
@mr_source_branch = mr_source_branch
@mr_target_branch = @target_branch
@commit_params = {
commit: @commit,
create_merge_request: params[:create_merge_request].present? || different_project?
......
......@@ -46,7 +46,8 @@ class Projects::CompareController < Projects::ApplicationController
end
def define_diff_vars
@compare = CompareService.new.execute(@project, @head_ref, @project, @start_ref)
@compare = CompareService.new(@project, @head_ref)
.execute(@project, @start_ref)
if @compare
@commits = @compare.commits
......
......@@ -79,7 +79,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController
if project_id.blank?
@project = nil
else
@project = Project.find_with_namespace("#{params[:namespace_id]}/#{project_id}")
@project = Project.find_by_full_path("#{params[:namespace_id]}/#{project_id}")
end
end
......
......@@ -434,7 +434,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
title: merge_request.title,
sha: (merge_request.diff_head_commit.short_id if merge_request.diff_head_sha),
status: status,
coverage: coverage
coverage: coverage,
pipeline: pipeline.try(:id)
}
render json: response
......
class Projects::SnippetsController < Projects::ApplicationController
include ToggleAwardEmoji
include SpammableActions