Commit 95eeaa99 authored by Valery Sizov's avatar Valery Sizov

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

parents 7117b4b9 c392b0cc
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
/public/ /public/
/tmp/ /tmp/
/vendor/ /vendor/
/builds/
...@@ -4,7 +4,9 @@ entry. ...@@ -4,7 +4,9 @@ entry.
## 8.14.0 (2016-11-22) ## 8.14.0 (2016-11-22)
- Show correct environment log in admin/logs (@duk3luk3 !7191)
- Fix Milestone dropdown not stay selected for `Upcoming` and `No Milestone` option !7117 - Fix Milestone dropdown not stay selected for `Upcoming` and `No Milestone` option !7117
- Diff collapse won't shift when collapsing.
- Backups do not fail anymore when using tar on annex and custom_hooks only. !5814 - Backups do not fail anymore when using tar on annex and custom_hooks only. !5814
- Adds user project membership expired event to clarify why user was removed (Callum Dryden) - Adds user project membership expired event to clarify why user was removed (Callum Dryden)
- Trim leading and trailing whitespace on project_path (Linus Thiel) - Trim leading and trailing whitespace on project_path (Linus Thiel)
...@@ -12,11 +14,13 @@ entry. ...@@ -12,11 +14,13 @@ entry.
- Adds support for the `token` attribute in project hooks API (Gauvain Pocentek) - Adds support for the `token` attribute in project hooks API (Gauvain Pocentek)
- Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO) - Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO)
- Fix Markdown styling inside reference links (Jan Zdráhal) - Fix Markdown styling inside reference links (Jan Zdráhal)
- Create new issue board list after creating a new label
- Fix extra space on Build sidebar on Firefox !7060 - Fix extra space on Build sidebar on Firefox !7060
- Fail gracefully when creating merge request with non-existing branch (alexsanford) - Fail gracefully when creating merge request with non-existing branch (alexsanford)
- Fix mobile layout issues in admin user overview page !7087 - Fix mobile layout issues in admin user overview page !7087
- Fix HipChat notifications rendering (airatshigapov, eisnerd) - Fix HipChat notifications rendering (airatshigapov, eisnerd)
- Remove 'Edit' button from wiki edit view !7143 (Hiroyuki Sato) - Remove 'Edit' button from wiki edit view !7143 (Hiroyuki Sato)
- Cleaned up global namespace JS !19661 (Jose Ivan Vargas)
- Refactor Jira service to use jira-ruby gem - Refactor Jira service to use jira-ruby gem
- Improved todos empty state - Improved todos empty state
- Add hover to trash icon in notes !7008 (blackst0ne) - Add hover to trash icon in notes !7008 (blackst0ne)
...@@ -26,6 +30,7 @@ entry. ...@@ -26,6 +30,7 @@ entry.
- Fix sidekiq stats in admin area (blackst0ne) - Fix sidekiq stats in admin area (blackst0ne)
- Added label description as tooltip to issue board list title - Added label description as tooltip to issue board list title
- Created cycle analytics bundle JavaScript file - Created cycle analytics bundle JavaScript file
- Hides container registry when repository is disabled
- API: Fix booleans not recognized as such when using the `to_boolean` helper - API: Fix booleans not recognized as such when using the `to_boolean` helper
- Removed delete branch tooltip !6954 - Removed delete branch tooltip !6954
- Stop unauthorized users dragging on milestone page (blackst0ne) - Stop unauthorized users dragging on milestone page (blackst0ne)
...@@ -45,6 +50,8 @@ entry. ...@@ -45,6 +50,8 @@ entry.
- New issue board list dropdown stays open after adding a new list - New issue board list dropdown stays open after adding a new list
- Fix: Backup restore doesn't clear cache - Fix: Backup restore doesn't clear cache
- Optimize Event queries by removing default order - Optimize Event queries by removing default order
- Add new icon for skipped builds
- Show created icon in pipeline mini-graph
- Remove duplicate links from sidebar - Remove duplicate links from sidebar
- API: Fix project deploy keys 400 and 500 errors when adding an existing key. !6784 (Joshua Welsh) - API: Fix project deploy keys 400 and 500 errors when adding an existing key. !6784 (Joshua Welsh)
- Add Rake task to create/repair GitLab Shell hooks symlinks !5634 - Add Rake task to create/repair GitLab Shell hooks symlinks !5634
...@@ -61,12 +68,18 @@ entry. ...@@ -61,12 +68,18 @@ entry.
- In all filterable drop downs, put input field in focus only after load is complete (Ido @leibo) - In all filterable drop downs, put input field in focus only after load is complete (Ido @leibo)
- Improve search query parameter naming in /admin/users !7115 (YarNayar) - Improve search query parameter naming in /admin/users !7115 (YarNayar)
- Fix table pagination to be responsive - Fix table pagination to be responsive
- Fix applying GitHub-imported labels when importing job is interrupted
- Allow to search for user by secondary email address in the admin interface(/admin/users) !7115 (YarNayar) - Allow to search for user by secondary email address in the admin interface(/admin/users) !7115 (YarNayar)
- Updated commit SHA styling on the branches page.
## 8.13.3 (2016-11-02) ## 8.13.3 (2016-11-02)
- Removes any symlinks before importing a project export file. CVE-2016-9086 - Removes any symlinks before importing a project export file. CVE-2016-9086
- Fixed Import/Export foreign key issue to do with project members. - Fixed Import/Export foreign key issue to do with project members.
- Fix relative links in Markdown wiki when displayed in "Project" tab !7218
- Reduce the overhead to calculate number of open/closed issues and merge requests within the group or project
- Fix project features default values
- Changed build dropdown list length to be 6,5 builds long in the pipeline graph
## 8.13.2 (2016-10-31) ## 8.13.2 (2016-10-31)
......
...@@ -110,11 +110,11 @@ gem 'gitlab-elasticsearch-git', '~> 1.0.1', require: "elasticsearch/git" ...@@ -110,11 +110,11 @@ gem 'gitlab-elasticsearch-git', '~> 1.0.1', require: "elasticsearch/git"
# Markdown and HTML processing # Markdown and HTML processing
gem 'html-pipeline', '~> 1.11.0' gem 'html-pipeline', '~> 1.11.0'
gem 'deckar01-task_list', '1.0.5', require: 'task_list/railtie' gem 'deckar01-task_list', '1.0.6', require: 'task_list/railtie'
gem 'gitlab-markup', '~> 1.5.0' gem 'gitlab-markup', '~> 1.5.0'
gem 'redcarpet', '~> 3.3.3' gem 'redcarpet', '~> 3.3.3'
gem 'RedCloth', '~> 4.3.2' gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~>3.6' gem 'rdoc', '~> 4.2'
gem 'org-ruby', '~> 0.9.12' gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0' gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1' gem 'wikicloth', '0.8.1'
...@@ -271,9 +271,6 @@ group :development do ...@@ -271,9 +271,6 @@ group :development do
gem 'better_errors', '~> 1.0.1' gem 'better_errors', '~> 1.0.1'
gem 'binding_of_caller', '~> 0.7.2' gem 'binding_of_caller', '~> 0.7.2'
# Docs generator
gem 'sdoc', '~> 0.3.20'
# thin instead webrick # thin instead webrick
gem 'thin', '~> 1.7.0' gem 'thin', '~> 1.7.0'
end end
......
...@@ -159,7 +159,7 @@ GEM ...@@ -159,7 +159,7 @@ GEM
database_cleaner (1.5.3) database_cleaner (1.5.3)
debug_inspector (0.0.2) debug_inspector (0.0.2)
debugger-ruby_core_source (1.3.8) debugger-ruby_core_source (1.3.8)
deckar01-task_list (1.0.5) deckar01-task_list (1.0.6)
activesupport (~> 4.0) activesupport (~> 4.0)
html-pipeline html-pipeline
rack (~> 1.0) rack (~> 1.0)
...@@ -591,7 +591,7 @@ GEM ...@@ -591,7 +591,7 @@ GEM
ffi (>= 0.5.0) ffi (>= 0.5.0)
rblineprof (0.3.6) rblineprof (0.3.6)
debugger-ruby_core_source (~> 1.3) debugger-ruby_core_source (~> 1.3)
rdoc (3.12.2) rdoc (4.2.2)
json (~> 1.4) json (~> 1.4)
recaptcha (3.0.0) recaptcha (3.0.0)
json json
...@@ -687,9 +687,6 @@ GEM ...@@ -687,9 +687,6 @@ GEM
scss_lint (0.47.1) scss_lint (0.47.1)
rake (>= 0.9, < 11) rake (>= 0.9, < 11)
sass (~> 3.4.15) sass (~> 3.4.15)
sdoc (0.3.20)
json (>= 1.1.3)
rdoc (~> 3.10)
seed-fu (2.3.6) seed-fu (2.3.6)
activerecord (>= 3.1) activerecord (>= 3.1)
activesupport (>= 3.1) activesupport (>= 3.1)
...@@ -870,7 +867,7 @@ DEPENDENCIES ...@@ -870,7 +867,7 @@ DEPENDENCIES
creole (~> 0.5.0) creole (~> 0.5.0)
d3_rails (~> 3.5.0) d3_rails (~> 3.5.0)
database_cleaner (~> 1.5.0) database_cleaner (~> 1.5.0)
deckar01-task_list (= 1.0.5) deckar01-task_list (= 1.0.6)
default_value_for (~> 3.0.0) default_value_for (~> 3.0.0)
devise (~> 4.2) devise (~> 4.2)
devise-two-factor (~> 3.0.0) devise-two-factor (~> 3.0.0)
...@@ -969,7 +966,7 @@ DEPENDENCIES ...@@ -969,7 +966,7 @@ DEPENDENCIES
rails-deprecated_sanitizer (~> 1.0.3) rails-deprecated_sanitizer (~> 1.0.3)
rainbow (~> 2.1.0) rainbow (~> 2.1.0)
rblineprof (~> 0.3.6) rblineprof (~> 0.3.6)
rdoc (~> 3.6) rdoc (~> 4.2)
recaptcha (~> 3.0) recaptcha (~> 3.0)
redcarpet (~> 3.3.3) redcarpet (~> 3.3.3)
redis (~> 3.2) redis (~> 3.2)
...@@ -989,7 +986,6 @@ DEPENDENCIES ...@@ -989,7 +986,6 @@ DEPENDENCIES
sanitize (~> 2.0) sanitize (~> 2.0)
sass-rails (~> 5.0.6) sass-rails (~> 5.0.6)
scss_lint (~> 0.47.0) scss_lint (~> 0.47.0)
sdoc (~> 0.3.20)
seed-fu (~> 2.3.5) seed-fu (~> 2.3.5)
select2-rails (~> 3.5.9) select2-rails (~> 3.5.9)
sentry-raven (~> 2.0.0) sentry-raven (~> 2.0.0)
......
...@@ -110,7 +110,7 @@ GitLab is a Ruby on Rails application that runs on the following software: ...@@ -110,7 +110,7 @@ GitLab is a Ruby on Rails application that runs on the following software:
- Redis 2.8+ - Redis 2.8+
- MySQL or PostgreSQL - MySQL or PostgreSQL
For more information please see the [architecture documentation](http://doc.gitlab.com/ce/development/architecture.html). For more information please see the [architecture documentation](https://docs.gitlab.com/ce/development/architecture.html).
## Third-party applications ## Third-party applications
......
...@@ -56,53 +56,11 @@ ...@@ -56,53 +56,11 @@
/*= require_directory . */ /*= require_directory . */
/*= require fuzzaldrin-plus */ /*= require fuzzaldrin-plus */
(function() { (function () {
window.slugify = function(text) { document.addEventListener('page:fetch', gl.utils.cleanupBeforeFetch);
return text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase(); window.addEventListener('hashchange', gl.utils.shiftWindow);
};
window.ajaxGet = function(url) {
return $.ajax({
type: "GET",
url: url,
dataType: "script"
});
};
window.split = function(val) {
return val.split(/,\s*/);
};
window.extractLast = function(term) {
return split(term).pop();
};
window.rstrip = function(val) {
if (val) {
return val.replace(/\s+$/, '');
} else {
return val;
}
};
// Disable button if text field is empty
window.disableButtonIfEmptyField = function(field_selector, button_selector, event_name) {
event_name = event_name || 'input';
var closest_submit, field;
field = $(field_selector);
closest_submit = field.closest('form').find(button_selector);
if (rstrip(field.val()) === "") {
closest_submit.disable();
}
return field.on(event_name, function() {
if (rstrip($(this).val()) === "") {
return closest_submit.disable();
} else {
return closest_submit.enable();
}
});
};
<<<<<<< HEAD
// Disable button if any input field with given selector is empty // Disable button if any input field with given selector is empty
window.disableButtonIfAnyEmptyField = function(form, form_selector, button_selector) { window.disableButtonIfAnyEmptyField = function(form, form_selector, button_selector) {
var closest_submit, updateButtons; var closest_submit, updateButtons;
...@@ -138,45 +96,51 @@ ...@@ -138,45 +96,51 @@
$.timeago.settings.allowFuture = true; $.timeago.settings.allowFuture = true;
window.onload = function() { window.onload = function() {
=======
window.onload = function () {
>>>>>>> c392b0cc24ba40e3fed920c6c693cb24665193af
// Scroll the window to avoid the topnav bar // Scroll the window to avoid the topnav bar
// https://github.com/twitter/bootstrap/issues/1768 // https://github.com/twitter/bootstrap/issues/1768
if (location.hash) { if (location.hash) {
return setTimeout(shiftWindow, 100); return setTimeout(gl.utils.shiftWindow, 100);
} }
}; };
$(function() { $(function () {
var $body, $document, $sidebarGutterToggle, $window, bootstrapBreakpoint, checkInitialSidebarSize, fitSidebarForSize, flash; var $body = $('body');
$document = $(document); var $document = $(document);
$window = $(window); var $window = $(window);
$body = $('body'); var $sidebarGutterToggle = $('.js-sidebar-toggle');
var $flash = $('.flash-container');
var bootstrapBreakpoint = bp.getBreakpointSize();
var checkInitialSidebarSize;
var fitSidebarForSize;
// Set the default path for all cookies to GitLab's root directory // Set the default path for all cookies to GitLab's root directory
Cookies.defaults.path = gon.relative_url_root || '/'; Cookies.defaults.path = gon.relative_url_root || '/';
gl.utils.preventDisabledButtons(); gl.utils.preventDisabledButtons();
bootstrapBreakpoint = bp.getBreakpointSize(); $('.nav-sidebar').niceScroll({
$(".nav-sidebar").niceScroll({
cursoropacitymax: '0.4', cursoropacitymax: '0.4',
cursorcolor: '#FFF', cursorcolor: '#FFF',
cursorborder: "1px solid #FFF" cursorborder: '1px solid #FFF'
}); });
$(".js-select-on-focus").on("focusin", function() { $('.js-select-on-focus').on('focusin', function () {
return $(this).select().one('mouseup', function(e) { return $(this).select().one('mouseup', function (e) {
return e.preventDefault(); return e.preventDefault();
}); });
// Click a .js-select-on-focus field, select the contents // Click a .js-select-on-focus field, select the contents
// Prevent a mouseup event from deselecting the input // Prevent a mouseup event from deselecting the input
}); });
$('.remove-row').bind('ajax:success', function() { $('.remove-row').bind('ajax:success', function () {
$(this).tooltip('destroy') $(this).tooltip('destroy')
.closest('li') .closest('li')
.fadeOut(); .fadeOut();
}); });
$('.js-remove-tr').bind('ajax:before', function() { $('.js-remove-tr').bind('ajax:before', function () {
return $(this).hide(); return $(this).hide();
}); });
$('.js-remove-tr').bind('ajax:success', function() { $('.js-remove-tr').bind('ajax:success', function () {
return $(this).closest('tr').fadeOut(); return $(this).closest('tr').fadeOut();
}); });
$('select.select2').select2({ $('select.select2').select2({
...@@ -184,8 +148,8 @@ ...@@ -184,8 +148,8 @@
// Initialize select2 selects // Initialize select2 selects
dropdownAutoWidth: true dropdownAutoWidth: true
}); });
$('.js-select2').bind('select2-close', function() { $('.js-select2').bind('select2-close', function () {
return setTimeout((function() { return setTimeout((function () {
$('.select2-container-active').removeClass('select2-container-active'); $('.select2-container-active').removeClass('select2-container-active');
return $(':focus').blur(); return $(':focus').blur();
}), 1); }), 1);
...@@ -195,24 +159,24 @@ ...@@ -195,24 +159,24 @@
$.fn.tooltip.Constructor.DEFAULTS.trigger = 'hover'; $.fn.tooltip.Constructor.DEFAULTS.trigger = 'hover';
$body.tooltip({ $body.tooltip({
selector: '.has-tooltip, [data-toggle="tooltip"]', selector: '.has-tooltip, [data-toggle="tooltip"]',
placement: function(_, el) { placement: function (_, el) {
return $(el).data('placement') || 'bottom'; return $(el).data('placement') || 'bottom';
} }
}); });
$('.trigger-submit').on('change', function() { $('.trigger-submit').on('change', function () {
return $(this).parents('form').submit(); return $(this).parents('form').submit();
// Form submitter // Form submitter
}); });
gl.utils.localTimeAgo($('abbr.timeago, .js-timeago'), true); gl.utils.localTimeAgo($('abbr.timeago, .js-timeago'), true);
// Flash // Flash
if ((flash = $(".flash-container")).length > 0) { if ($flash.length > 0) {
flash.click(function() { $flash.click(function () {
return $(this).fadeOut(); return $(this).fadeOut();
}); });
flash.show(); $flash.show();
} }
// Disable form buttons while a form is submitting // Disable form buttons while a form is submitting
$body.on('ajax:complete, ajax:beforeSend, submit', 'form', function(e) { $body.on('ajax:complete, ajax:beforeSend, submit', 'form', function (e) {
var buttons; var buttons;
buttons = $('[type="submit"]', this); buttons = $('[type="submit"]', this);
switch (e.type) { switch (e.type) {
...@@ -223,36 +187,36 @@ ...@@ -223,36 +187,36 @@
return buttons.enable(); return buttons.enable();
} }
}); });
$(document).ajaxError(function(e, xhrObj, xhrSetting, xhrErrorText) { $(document).ajaxError(function (e, xhrObj) {
var ref; var ref = xhrObj.status;
if (xhrObj.status === 401) { if (xhrObj.status === 401) {
return new Flash('You need to be logged in.', 'alert'); return new Flash('You need to be logged in.', 'alert');
} else if ((ref = xhrObj.status) === 404 || ref === 500) { } else if (ref === 404 || ref === 500) {
return new Flash('Something went wrong on our end.', 'alert'); return new Flash('Something went wrong on our end.', 'alert');
} }
}); });
$('.account-box').hover(function() { $('.account-box').hover(function () {
// Show/Hide the profile menu when hovering the account box // Show/Hide the profile menu when hovering the account box
return $(this).toggleClass('hover'); return $(this).toggleClass('hover');
}); });
$document.on('click', '.diff-content .js-show-suppressed-diff', function() { $document.on('click', '.diff-content .js-show-suppressed-diff', function () {
var $container; var $container;
$container = $(this).parent(); $container = $(this).parent();
$container.next('table').show(); $container.next('table').show();
return $container.remove(); return $container.remove();
// Commit show suppressed diff // Commit show suppressed diff
}); });
$('.navbar-toggle').on('click', function() { $('.navbar-toggle').on('click', function () {
$('.header-content .title').toggle(); $('.header-content .title').toggle();
$('.header-content .header-logo').toggle(); $('.header-content .header-logo').toggle();
$('.header-content .navbar-collapse').toggle(); $('.header-content .navbar-collapse').toggle();
return $('.navbar-toggle').toggleClass('active'); return $('.navbar-toggle').toggleClass('active');
}); });
// Show/hide comments on diff // Show/hide comments on diff
$body.on("click", ".js-toggle-diff-comments", function(e) { $body.on('click', '.js-toggle-diff-comments', function (e) {
var $this = $(this); var $this = $(this);
$this.toggleClass('active');
var notesHolders = $this.closest('.diff-file').find('.notes_holder'); var notesHolders = $this.closest('.diff-file').find('.notes_holder');
$this.toggleClass('active');
if ($this.hasClass('active')) { if ($this.hasClass('active')) {
notesHolders.show().find('.hide').show(); notesHolders.show().find('.hide').show();
} else { } else {
...@@ -261,6 +225,7 @@ ...@@ -261,6 +225,7 @@
$this.trigger('blur'); $this.trigger('blur');
return e.preventDefault(); return e.preventDefault();
}); });
<<<<<<< HEAD
$document.off("click", '.js-confirm-danger'); $document.off("click", '.js-confirm-danger');
$document.on("click", '.js-confirm-danger', function(e) { $document.on("click", '.js-confirm-danger', function(e) {
var btn, form, text, warningMessage; var btn, form, text, warningMessage;
...@@ -272,22 +237,29 @@ ...@@ -272,22 +237,29 @@
return new ConfirmDangerModal(form, text, { return new ConfirmDangerModal(form, text, {
warningMessage: warningMessage warningMessage: warningMessage
}); });
=======
$document.off('click', '.js-confirm-danger');
$document.on('click', '.js-confirm-danger', function (e) {
var btn = $(e.target);
var form = btn.closest('form');
var text = btn.data('confirm-danger-message');
e.preventDefault();
return new ConfirmDangerModal(form, text);
>>>>>>> c392b0cc24ba40e3fed920c6c693cb24665193af
}); });
$document.on('click', 'button', function() { $document.on('click', 'button', function () {
return $(this).blur(); return $(this).blur();
}); });
$('input[type="search"]').each(function() { $('input[type="search"]').each(function () {
var $this; var $this = $(this);
$this = $(this);
$this.attr('value', $this.val()); $this.attr('value', $this.val());
}); });
$document.off('keyup', 'input[type="search"]').on('keyup', 'input[type="search"]', function(e) { $document.off('keyup', 'input[type="search"]').on('keyup', 'input[type="search"]', function () {
var $this; var $this;
$this = $(this); $this = $(this);
return $this.attr('value', $this.val()); return $this.attr('value', $this.val());
}); });
$sidebarGutterToggle = $('.js-sidebar-toggle'); $document.off('breakpoint:change').on('breakpoint:change', function (e, breakpoint) {
$document.off('breakpoint:change').on('breakpoint:change', function(e, breakpoint) {
var $gutterIcon; var $gutterIcon;
if (breakpoint === 'sm' || breakpoint === 'xs') { if (breakpoint === 'sm' || breakpoint === 'xs') {
$gutterIcon = $sidebarGutterToggle.find('i'); $gutterIcon = $sidebarGutterToggle.find('i');
...@@ -296,7 +268,7 @@ ...@@ -296,7 +268,7 @@
} }
} }
}); });
fitSidebarForSize = function() { fitSidebarForSize = function () {
var oldBootstrapBreakpoint; var oldBootstrapBreakpoint;
oldBootstrapBreakpoint = bootstrapBreakpoint; oldBootstrapBreakpoint = bootstrapBreakpoint;
bootstrapBreakpoint = bp.getBreakpointSize(); bootstrapBreakpoint = bp.getBreakpointSize();
...@@ -304,13 +276,13 @@ ...@@ -304,13 +276,13 @@
return $document.trigger('breakpoint:change', [bootstrapBreakpoint]); return $document.trigger('breakpoint:change', [bootstrapBreakpoint]);
} }
}; };
checkInitialSidebarSize = function() { checkInitialSidebarSize = function () {
bootstrapBreakpoint = bp.getBreakpointSize(); bootstrapBreakpoint = bp.getBreakpointSize();
if (bootstrapBreakpoint === "xs" || "sm") { if (bootstrapBreakpoint === 'xs' || 'sm') {
return $document.trigger('breakpoint:change', [bootstrapBreakpoint]); return $document.trigger('breakpoint:change', [bootstrapBreakpoint]);
} }
}; };
$window.off("resize.app").on("resize.app", function(e) { $window.off('resize.app').on('resize.app', function () {
return fitSidebarForSize(); return fitSidebarForSize();
}); });
gl.awardsHandler = new AwardsHandler(); gl.awardsHandler = new AwardsHandler();
......
/* eslint-disable */ /* eslint-disable */
(function() { (function() {
this.AwardsHandler = (function() { this.AwardsHandler = (function() {
const FROM_SENTENCE_REGEX = /(?:, and | and |, )/; //For separating lists produced by ruby's Array#toSentence var FROM_SENTENCE_REGEX = /(?:, and | and |, )/; //For separating lists produced by ruby's Array#toSentence
function AwardsHandler() { function AwardsHandler() {
this.aliases = gl.emojiAliases(); this.aliases = gl.emojiAliases();
$(document).off('click', '.js-add-award').on('click', '.js-add-award', (function(_this) { $(document).off('click', '.js-add-award').on('click', '.js-add-award', (function(_this) {
......
...@@ -2,6 +2,19 @@ ...@@ -2,6 +2,19 @@
$(() => { $(() => {
const Store = gl.issueBoards.BoardsStore; const Store = gl.issueBoards.BoardsStore;
$(document).off('created.label').on('created.label', (e, label) => {
Store.new({
title: label.title,
position: Store.state.lists.length - 2,
list_type: 'label',
label: {
id: label.id,
title: label.title,
color: label.color
}
});
});
$('.js-new-board-list').each(function () { $('.js-new-board-list').each(function () {
const $this = $(this); const $this = $(this);
new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespace-path'), $this.data('project-path')); new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespace-path'), $this.data('project-path'));
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
submit.disable(); submit.disable();
$('.js-confirm-danger-input').off('input'); $('.js-confirm-danger-input').off('input');
$('.js-confirm-danger-input').on('input', function() { $('.js-confirm-danger-input').on('input', function() {
if (rstrip($(this).val()) === project_path) { if (gl.utils.rstrip($(this).val()) === project_path) {
return submit.enable(); return submit.enable();
} else { } else {
return submit.disable(); return submit.disable();
......
...@@ -115,6 +115,8 @@ ...@@ -115,6 +115,8 @@
.show(); .show();
} else { } else {
this.$dropdownBack.trigger('click'); this.$dropdownBack.trigger('click');
$(document).trigger('created.label', label);
} }
}); });
} }
......
/* eslint-disable */ /* global Element */
Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatches; /* eslint-disable consistent-return, max-len */
Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatchesSelector;
Element.prototype.closest = function closest(selector, selectedElement = this) { Element.prototype.closest = function closest(selector, selectedElement = this) {
if (!selectedElement) return; if (!selectedElement) return;
......
...@@ -126,8 +126,8 @@ ...@@ -126,8 +126,8 @@
} }
return { return {
username: m.username, username: m.username,
title: sanitize(title), title: gl.utils.sanitize(title),
search: sanitize(m.username + " " + m.name) search: gl.utils.sanitize(m.username + " " + m.name)
}; };
}); });
} }
...@@ -159,7 +159,7 @@ ...@@ -159,7 +159,7 @@
} }
return { return {
id: i.iid, id: i.iid,
title: sanitize(i.title), title: gl.utils.sanitize(i.title),
search: i.iid + " " + i.title search: i.iid + " " + i.title
}; };
}); });
...@@ -189,7 +189,7 @@ ...@@ -189,7 +189,7 @@
} }
return { return {
id: m.iid, id: m.iid,
title: sanitize(m.title), title: gl.utils.sanitize(m.title),
search: "" + m.title search: "" + m.title
}; };
}); });
...@@ -222,7 +222,7 @@ ...@@ -222,7 +222,7 @@
} }
return { return {
id: m.iid, id: m.iid,
title: sanitize(m.title), title: gl.utils.sanitize(m.title),
search: m.iid + " " + m.title search: m.iid + " " + m.title
}; };
}); });
...@@ -240,9 +240,9 @@ ...@@ -240,9 +240,9 @@
var sanitizeLabelTitle; var sanitizeLabelTitle;
sanitizeLabelTitle = function(title) { sanitizeLabelTitle = function(title) {
if (/[\w\?&]+\s+[\w\?&]+/g.test(title)) { if (/[\w\?&]+\s+[\w\?&]+/g.test(title)) {
return "\"" + (sanitize(title)) + "\""; return "\"" + (gl.utils.sanitize(title)) + "\"";
} else { } else {
return sanitize(title); return gl.utils.sanitize(title);
} }
}; };
return $.map(merges, function(m) { return $.map(merges, function(m) {
......
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
if (isNewForm) { if (isNewForm) {
this.form.find('.div-dropzone').remove(); this.form.find('.div-dropzone').remove();
this.form.addClass('gfm-form'); this.form.addClass('gfm-form');
disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button'));
// remove notify commit author checkbox for non-commit notes // remove notify commit author checkbox for non-commit notes
gl.utils.disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button'));
GitLab.GfmAutoComplete.setup(this.form.find('.js-gfm-input')); GitLab.GfmAutoComplete.setup(this.form.find('.js-gfm-input'));
new DropzoneInput(this.form); new DropzoneInput(this.form);
autosize(this.textarea); autosize(this.textarea);
......
...@@ -24,6 +24,81 @@ ...@@ -24,6 +24,81 @@
return null; return null;
} }
}; };
w.gl.utils.ajaxGet = function(url) {
return $.ajax({
type: "GET",
url: url,
dataType: "script"
});
};
w.gl.utils.split = function(val) {
return val.split(/,\s*/);
};
w.gl.utils.extractLast = function(term) {
return this.split(term).pop();
};
w.gl.utils.rstrip = function rstrip(val) {
if (val) {
return val.replace(/\s+$/, '');
} else {
return val;
}
};
w.gl.utils.disableButtonIfEmptyField = function(field_selector, button_selector, event_name) {
event_name = event_name || 'input';
var closest_submit, field, that;
that = this;
field = $(field_selector);
closest_submit = field.closest('form').find(button_selector);
if (this.rstrip(field.val()) === "") {
closest_submit.disable();
}
return field.on(event_name, function() {
if (that.rstrip($(this).val()) === "") {
return closest_submit.disable();
} else {
return closest_submit.enable();
}
});
};
w.gl.utils.disableButtonIfAnyEmptyField = function(form, form_selector, button_selector) {
var closest_submit, updateButtons;
closest_submit = form.find(button_selector);
updateButtons = function() {
var filled;
filled = true;
form.find('input').filter(form_selector).each(function() {
return filled = this.rstrip($(this).val()) !== "" || !$(this).attr('required');
});
if (filled) {
return closest_submit.enable();
} else {
return closest_submit.disable();
}
};
updateButtons();
return form.keyup(updateButtons);
};
w.gl.utils.sanitize = function(str) {
return str.replace(/<(?:.|\n)*?>/gm, '');
};
w.gl.utils.unbindEvents = function() {
return $(document).off('scroll');
};
w.gl.utils.shiftWindow = function() {
return w.scrollBy(0, -100);
};
gl.utils.updateTooltipTitle = function($tooltipEl, newTitle) { gl.utils.updateTooltipTitle = function($tooltipEl, newTitle) {
return $tooltipEl.tooltip('destroy').attr('title', newTitle).tooltip('fixTitle'); return $tooltipEl.tooltip('destroy').attr('title', newTitle).tooltip('fixTitle');
}; };
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
$('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow); $('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow);
$('.js-member-update-control').off('change').on('change', this.formSubmit); $('.js-member-update-control').off('change').on('change', this.formSubmit);
$('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess); $('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess);
disableButtonIfEmptyField('#user_ids', 'input[name=commit]', 'change'); gl.utils.disableButtonIfEmptyField('#user_ids', 'input[name=commit]', 'change');
} }
removeRow(e) { removeRow(e) {
......
...@@ -45,7 +45,9 @@ ...@@ -45,7 +45,9 @@
}; };
ProjectNew.prototype.toggleRepoVisibility = function () { ProjectNew.prototype.toggleRepoVisibility = function () {
var $repoAccessLevel = $('.js-repo-access-level select'); var $repoAccessLevel = $('.js-repo-access-level select'),
containerRegistry = document.querySelectorAll('.js-container-registry')[0],
containerRegistryCheckbox = document.getElementById('project_container_registry_enabled');
this.$repoSelects.find("option[value='" + $repoAccessLevel.val() + "']") this.$repoSelects.find("option[value='" + $repoAccessLevel.val() + "']")
.nextAll() .nextAll()
...@@ -70,8 +72,17 @@ ...@@ -70,8 +72,17 @@
if (selectedVal) { if (selectedVal) {
this.$repoSelects.removeClass('disabled'); this.$repoSelects.removeClass('disabled');
if (containerRegistry) {
containerRegistry.style.display = '';
}
} else { } else {
this.$repoSelects.addClass('disabled'); this.$repoSelects.addClass('disabled');
if (containerRegistry) {
containerRegistry.style.display = 'none';
containerRegistryCheckbox.checked = false;
}
} }
}.bind(this)); }.bind(this));
}; };
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
$dropdown = $(dropdown); $dropdown = $(dropdown);
options.projectId = $dropdown.data('project-id'); options.projectId = $dropdown.data('project-id');
options.showCurrentUser = $dropdown.data('current-user'); options.showCurrentUser = $dropdown.data('current-user');
options.todoFilter = $dropdown.data('todo-filter');
options.todoStateFilter = $dropdown.data('todo-state-filter');
showNullUser = $dropdown.data('null-user'); showNullUser = $dropdown.data('null-user');
showMenuAbove = $dropdown.data('showMenuAbove'); showMenuAbove = $dropdown.data('showMenuAbove');
showAnyUser = $dropdown.data('any-user'); showAnyUser = $dropdown.data('any-user');
...@@ -394,6 +396,8 @@ ...@@ -394,6 +396,8 @@
project_id: options.projectId || null, project_id: options.projectId || null,
group_id: options.groupId || null, group_id: options.groupId || null,
skip_ldap: options.skipLdap || null, skip_ldap: options.skipLdap || null,
todo_filter: options.todoFilter || null,
todo_state_filter: options.todoStateFilter || null,
current_user: options.showCurrentUser || null, current_user: options.showCurrentUser || null,
push_code_to_protected_branches: options.pushCodeToProtectedBranches || null, push_code_to_protected_branches: options.pushCodeToProtectedBranches || null,
author_id: options.authorId || null, author_id: options.authorId || null,
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
margin-right: $margin-right; margin-right: $margin-right;
} }
.avatar-container { .avatar-circle {
float: left; float: left;
margin-right: 15px; margin-right: 15px;
border-radius: $avatar_radius; border-radius: $avatar_radius;
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
} }
.avatar { .avatar {
@extend .avatar-container; @extend .avatar-circle;
width: 40px; width: 40px;
height: 40px; height: 40px;
padding: 0; padding: 0;
...@@ -64,8 +64,8 @@ ...@@ -64,8 +64,8 @@
&.s160 { font-size: 96px; line-height: 158px; } &.s160 { font-size: 96px; line-height: 158px; }
} }
.image-container { .avatar-container {
@extend .avatar-container; @extend .avatar-circle;
overflow: hidden; overflow: hidden;
display: flex; display: flex;
...@@ -76,4 +76,4 @@ ...@@ -76,4 +76,4 @@
margin: 0; margin: 0;
align-self: center; align-self: center;
} }
} }
\ No newline at end of file
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
color: $dropdown-toggle-color; color: $dropdown-toggle-color;
font-size: 15px; font-size: 15px;
text-align: left; text-align: left;
border: 1px solid $dropdown-toggle-border-color; border: 1px solid $border-color;
border-radius: $border-radius-base; border-radius: $border-radius-base;
outline: 0; outline: 0;
text-overflow: ellipsis; text-overflow: ellipsis;
...@@ -45,11 +45,9 @@ ...@@ -45,11 +45,9 @@
.fa { .fa {
position: absolute; position: absolute;
top: 50%; top: 10px;
right: 6px; right: 8px;
margin-top: -6px;
color: $dropdown-toggle-icon-color; color: $dropdown-toggle-icon-color;
font-size: 10px;
&.fa-spinner { &.fa-spinner {
font-size: 16px; font-size: 16px;
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
height: 0; height: 0;
margin-left: 2px; margin-left: 2px;
vertical-align: middle; vertical-align: middle;
border-top: $caret-width-base dashed; border-top: 5px dashed;
border-right: $caret-width-base solid transparent; border-right: 5px solid transparent;
border-left: $caret-width-base solid transparent; border-left: 5px solid transparent;
color: $gray-darkest; color: $gray-darkest;
} }
} }
......
...@@ -36,9 +36,42 @@ ...@@ -36,9 +36,42 @@
padding: 10px 0; padding: 10px 0;
margin-bottom: 0; margin-bottom: 0;
.commit-options-dropdown-caret { @media (min-width: $screen-sm-min) {
@media (max-width: $screen-sm) { display: flex;
margin-left: 0; align-items: center;
.commit-meta {
flex: 1;
}
}
.commit-hash-full {
@media (max-width: $screen-sm-max) {
width: 80px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
vertical-align: bottom;
}
}
.commit-action-buttons {
i {
color: $gl-icon-color;
font-size: 13px;
margin-right: 3px;
}
@media (max-width: $screen-xs-max) {
.dropdown {
width: 100%;
margin-top: 10px;
}
.dropdown-toggle {
width: 100%;
}
} }
} }
} }
...@@ -188,17 +221,6 @@ ...@@ -188,17 +221,6 @@
} }
} }
.commit-action-buttons {
position: relative;
top: -1px;
i {
color: $gl-icon-color;
font-size: 13px;
margin-right: 3px;
}
}
/* /*
* Commit message textarea for web editor and * Commit message textarea for web editor and
* custom merge request message * custom merge request message
......
...@@ -164,7 +164,22 @@ ...@@ -164,7 +164,22 @@
.branch-commit { .branch-commit {
color: $gl-gray; color: $gl-gray;
.commit-id, .commit-icon {
text-align: center;
display: inline-block;
svg {
height: 14px;
width: 14px;
vertical-align: middle;
fill: $table-text-gray;
}
}
.commit-id {
color: $gl-link-color;
}
.commit-row-message { .commit-row-message {
color: $gl-gray; color: $gl-gray;
} }
......
...@@ -55,6 +55,10 @@ ...@@ -55,6 +55,10 @@
float: left; float: left;
} }
.file-buttons {
font-size: 0;
}
.select2 { .select2 {
float: right; float: right;
} }
......
// CI icon colors
.ci-status-icon {
&-created {
fill: $gray-darkest;
}
&-skipped,
&-canceled {
fill: $gl-text-color;
}
}
...@@ -85,6 +85,11 @@ ...@@ -85,6 +85,11 @@
} }
.commit-link { .commit-link {
a {
&:focus {
text-decoration: none;
}
}
.ci-status { .ci-status {
...@@ -439,7 +444,7 @@ ...@@ -439,7 +444,7 @@
} }
.grouped-pipeline-dropdown { .grouped-pipeline-dropdown {
padding: 8px 0; padding: 0;
width: 186px; width: 186px;
left: auto; left: auto;
right: -197px; right: -197px;
...@@ -448,6 +453,14 @@ ...@@ -448,6 +453,14 @@
ul { ul {
max-height: 245px; max-height: 245px;
overflow: auto; overflow: auto;
li:first-child {
padding-top: 8px;
}
li:last-child {
padding-bottom: 8px;
}
} }
a { a {
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
white-space: nowrap; white-space: nowrap;
border-radius: 4px; border-radius: 4px;
&:hover { &:hover,
&:focus {
text-decoration: none; text-decoration: none;
} }
......
...@@ -132,7 +132,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -132,7 +132,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:elasticsearch_host, :elasticsearch_host,
:elasticsearch_port, :elasticsearch_port,
:usage_ping_enabled, :usage_ping_enabled,
:repository_storage, repository_storages: [],
:enabled_git_access_protocol, :enabled_git_access_protocol,
:repository_size_limit, :repository_size_limit,
restricted_visibility_levels: [], restricted_visibility_levels: [],
......
...@@ -196,9 +196,10 @@ class ApplicationController < ActionController::Base ...@@ -196,9 +196,10 @@ class ApplicationController < ActionController::Base
end end
# JSON for infinite scroll via Pager object # JSON for infinite scroll via Pager object
def pager_json(partial, count) def pager_json(partial, count, locals = {})
html = render_to_string( html = render_to_string(
partial, partial,
locals: locals,
layout: false, layout: false,
formats: [:html] formats: [:html]
) )
......
...@@ -11,9 +11,13 @@ class AutocompleteController < ApplicationController ...@@ -11,9 +11,13 @@ class AutocompleteController < ApplicationController
@users = @users.reorder(:name) @users = @users.reorder(:name)
@users = load_users_by_ability || @users.page(params[:page]) @users = load_users_by_ability || @users.page(params[:page])
if params[:todo_filter].present?
@users = @users.todo_authors(current_user.id, params[:todo_state_filter])
end
if params[:search].blank? if params[:search].blank?
# Include current user if available to filter by "Me" # Include current user if available to filter by "Me"
if params[:current_user] && current_user if params[:current_user].present? && current_user
@users = [*@users, current_user] @users = [*@users, current_user]
end end
......
...@@ -26,8 +26,15 @@ class Projects::CommitsController < Projects::ApplicationController ...@@ -26,8 +26,15 @@ class Projects::CommitsController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html format.html
format.json { pager_json("projects/commits/_commits", @commits.size) }
format.atom { render layout: false } format.atom { render layout: false }
format.json do
pager_json(
'projects/commits/_commits',
@commits.size,
project: @project,
ref: @ref)
end
end end
end end
end end
...@@ -7,7 +7,7 @@ class Projects::GroupLinksController < Projects::ApplicationController ...@@ -7,7 +7,7 @@ class Projects::GroupLinksController < Projects::ApplicationController
@group_links = project.project_group_links.all @group_links = project.project_group_links.all
@skip_groups = @group_links.pluck(:group_id) @skip_groups = @group_links.pluck(:group_id)
@skip_groups << project.group.try(:id) @skip_groups << project.namespace_id unless project.personal?
end end
def create def create
......
...@@ -379,13 +379,23 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -379,13 +379,23 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def branch_from def branch_from
# This is always source # This is always source
@source_project = @merge_request.nil? ? @project : @merge_request.source_project @source_project = @merge_request.nil? ? @project : @merge_request.source_project
@commit = @repository.commit(params[:ref]) if params[:ref].present?
if params[:ref].present?
@ref = params[:ref]
@commit = @repository.commit(@ref)
end
render layout: false render layout: false
end end
def branch_to def branch_to
@target_project = selected_target_project @target_project = selected_target_project
@commit = @target_project.commit(params[:ref]) if params[:ref].present?
if params[:ref].present?
@ref = params[:ref]
@commit = @target_project.commit(@ref)
end
render layout: false render layout: false
end end
......
...@@ -336,6 +336,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -336,6 +336,7 @@ class ProjectsController < Projects::ApplicationController
:visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar,
:build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex,
:public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled, :public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled,
:only_allow_merge_if_all_discussions_are_resolved,
:lfs_enabled, project_feature_attributes, :lfs_enabled, project_feature_attributes,
# EE-only # EE-only
......
...@@ -93,11 +93,11 @@ module ApplicationSettingsHelper ...@@ -93,11 +93,11 @@ module ApplicationSettingsHelper
end end
end end
def repository_storage_options_for_select def repository_storages_options_for_select
options = Gitlab.config.repositories.storages.map do |name, path| options = Gitlab.config.repositories.storages.map do |name, path|
["#{name} - #{path}", name] ["#{name} - #{path}", name]
end end
options_for_select(options, @application_setting.repository_storage) options_for_select(options, @application_setting.repository_storages)
end end
end end
...@@ -47,17 +47,27 @@ module CiStatusHelper ...@@ -47,17 +47,27 @@ module CiStatusHelper
'icon_play' 'icon_play'
when 'created' when 'created'
'icon_status_created' 'icon_status_created'
when 'skipped'
'icon_status_skipped'
else else
'icon_status_cancel' 'icon_status_canceled'
end end
custom_icon(icon_name) custom_icon(icon_name)
end end
def render_commit_status(commit, tooltip_placement: 'auto left') def render_commit_status(commit, ref: nil, tooltip_placement: 'auto left')
project = commit.project project = commit.project
path = pipelines_namespace_project_commit_path(project.namespace, project, commit) path = pipelines_namespace_project_commit_path(
render_status_with_link('commit', commit.status, path, tooltip_placement: tooltip_placement) project.namespace,
project,
commit)
render_status_with_link(
'commit',
commit.status(ref),
path,
tooltip_placement: tooltip_placement)
end end
def render_pipeline_status(pipeline, tooltip_placement: 'auto left') def render_pipeline_status(pipeline, tooltip_placement: 'auto left')
......
...@@ -25,9 +25,11 @@ module CommitsHelper ...@@ -25,9 +25,11 @@ module CommitsHelper
end end
end end
def commit_to_html(commit, project, inline = true) def commit_to_html(commit, ref, project)
template = inline ? "inline_commit" : "commit" render 'projects/commits/commit',
render "projects/commits/#{template}", commit: commit, project: project unless commit.nil? commit: commit,
ref: ref,
project: project
end end
# Breadcrumb links for a Project and, if applicable, a tree path # Breadcrumb links for a Project and, if applicable, a tree path
......
...@@ -47,7 +47,7 @@ module DropdownsHelper ...@@ -47,7 +47,7 @@ module DropdownsHelper
default_label = data_attr[:default_label] default_label = data_attr[:default_label]
content_tag(:button, class: "dropdown-menu-toggle #{options[:toggle_class] if options.has_key?(:toggle_class)}", id: (options[:id] if options.has_key?(:id)), type: "button", data: data_attr) do content_tag(:button, class: "dropdown-menu-toggle #{options[:toggle_class] if options.has_key?(:toggle_class)}", id: (options[:id] if options.has_key?(:id)), type: "button", data: data_attr) do
output = content_tag(:span, toggle_text, class: "dropdown-toggle-text #{'is-default' if toggle_text == default_label}") output = content_tag(:span, toggle_text, class: "dropdown-toggle-text #{'is-default' if toggle_text == default_label}")
output << icon('chevron-down') output << icon('caret-down')
output.html_safe output.html_safe
end end
end end
......
...@@ -18,6 +18,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -18,6 +18,7 @@ class ApplicationSetting < ActiveRecord::Base
serialize :disabled_oauth_sign_in_sources, Array serialize :disabled_oauth_sign_in_sources, Array
serialize :domain_whitelist, Array serialize :domain_whitelist, Array
serialize :domain_blacklist, Array serialize :domain_blacklist, Array
serialize :repository_storages
cache_markdown_field :sign_in_text cache_markdown_field :sign_in_text
cache_markdown_field :help_page_text cache_markdown_field :help_page_text
...@@ -86,9 +87,8 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -86,9 +87,8 @@ class ApplicationSetting < ActiveRecord::Base
presence: { message: "can't be blank when indexing is enabled" }, presence: { message: "can't be blank when indexing is enabled" },
if: :elasticsearch_indexing? if: :elasticsearch_indexing?
validates :repository_storage, validates :repository_storages, presence: true
presence: true, validate :check_repository_storages
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
validates :enabled_git_access_protocol, validates :enabled_git_access_protocol,
inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true } inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true }
...@@ -181,7 +181,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -181,7 +181,7 @@ class ApplicationSetting < ActiveRecord::Base
elasticsearch_host: ENV['ELASTIC_HOST'] || 'localhost', elasticsearch_host: ENV['ELASTIC_HOST'] || 'localhost',
elasticsearch_port: ENV['ELASTIC_PORT'] || '9200', elasticsearch_port: ENV['ELASTIC_PORT'] || '9200',
usage_ping_enabled: true, usage_ping_enabled: true,
repository_storage: 'default', repository_storages: ['default'],
user_default_external: false, user_default_external: false,
) )
end end
...@@ -220,6 +220,29 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -220,6 +220,29 @@ class ApplicationSetting < ActiveRecord::Base
self.domain_blacklist_raw = file.read self.domain_blacklist_raw = file.read
end end
def repository_storages
value = read_attribute(:repository_storages)
value = [value] if value.is_a?(String)
value = [] if value.nil?
value
end
# repository_storage is still required in the API. Remove in 9.0
def repository_storage
repository_storages.first
end
def repository_storage=(value)
self.repository_storages = [value]
end
# Choose one of the available repository storage options. Currently all have
# equal weighting.
def pick_repository_storage
repository_storages.sample
end
def runners_registration_token def runners_registration_token
ensure_runners_registration_token! ensure_runners_registration_token!
end end
...@@ -227,4 +250,12 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -227,4 +250,12 @@ class ApplicationSetting < ActiveRecord::Base
def health_check_access_token def health_check_access_token
ensure_health_check_access_token! ensure_health_check_access_token!
end end
private
def check_repository_storages
invalid = repository_storages - Gitlab.config.repositories.storages.keys
errors.add(:repository_storages, "can't include: #{invalid.join(", ")}") unless
invalid.empty?
end
end end
...@@ -226,12 +226,19 @@ class Commit ...@@ -226,12 +226,19 @@ class Commit
end end
def pipelines def pipelines
@pipeline ||= project.pipelines.where(sha: sha) project.pipelines.where(sha: sha)
end end
def status def status(ref = nil)
return @status if defined?(@status) @statuses ||= {}
@status ||= pipelines.status
if @statuses.key?(ref)
@statuses[ref]
elsif ref
@statuses[ref] = pipelines.where(ref: ref).status
else
@statuses[ref] = pipelines.status
end
end end
def revert_branch_name def revert_branch_name
......
...@@ -448,6 +448,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -448,6 +448,7 @@ class MergeRequest < ActiveRecord::Base
return false if work_in_progress? return false if work_in_progress?
return false if broken? return false if broken?
return false unless skip_ci_check || mergeable_ci_state? return false unless skip_ci_check || mergeable_ci_state?
return false unless mergeable_discussions_state?
true true
end end
...@@ -516,6 +517,12 @@ class MergeRequest < ActiveRecord::Base ...@@ -516,6 +517,12 @@ class MergeRequest < ActiveRecord::Base
discussions_resolvable? && diff_discussions.none?(&:to_be_resolved?) discussions_resolvable? && diff_discussions.none?(&:to_be_resolved?)
end end
def mergeable_discussions_state?
return true unless project.only_allow_merge_if_all_discussions_are_resolved?
discussions_resolved?
end
def hook_attrs def hook_attrs
attrs = { attrs = {
source: source_project.try(:hook_attrs), source: source_project.try(:hook_attrs),
......
...@@ -26,7 +26,7 @@ class Project < ActiveRecord::Base ...@@ -26,7 +26,7 @@ class Project < ActiveRecord::Base
default_value_for :archived, false default_value_for :archived, false
default_value_for :visibility_level, gitlab_config_features.visibility_level default_value_for :visibility_level, gitlab_config_features.visibility_level
default_value_for :container_registry_enabled, gitlab_config_features.container_registry default_value_for :container_registry_enabled, gitlab_config_features.container_registry
default_value_for(:repository_storage) { current_application_settings.repository_storage } default_value_for(:repository_storage) { current_application_settings.pick_repository_storage }
default_value_for(:shared_runners_enabled) { current_application_settings.shared_runners_enabled } default_value_for(:shared_runners_enabled) { current_application_settings.shared_runners_enabled }
default_value_for :issues_enabled, gitlab_config_features.issues default_value_for :issues_enabled, gitlab_config_features.issues
default_value_for :merge_requests_enabled, gitlab_config_features.merge_requests default_value_for :merge_requests_enabled, gitlab_config_features.merge_requests
...@@ -1177,10 +1177,6 @@ class Project < ActiveRecord::Base ...@@ -1177,10 +1177,6 @@ class Project < ActiveRecord::Base
forks.count forks.count
end end
def find_label(name)
labels.find_by(name: name)
end
def origin_merge_requests def origin_merge_requests
merge_requests.where(source_project_id: self.id) merge_requests.where(source_project_id: self.id)
end end
......
...@@ -163,6 +163,21 @@ class JiraService < IssueTrackerService ...@@ -163,6 +163,21 @@ class JiraService < IssueTrackerService
add_comment(data, issue_key) add_comment(data, issue_key)
end end
# reason why service cannot be tested
def disabled_title
"Please fill in Password and Username."
end
def can_test?
username.present? && password.present?
end
# JIRA does not need test data.
# We are requesting the project that belongs to the project key.
def test_data(user = nil, project = nil)
nil
end
def test_settings def test_settings
return unless url.present? return unless url.present?
# Test settings by getting the project # Test settings by getting the project
......
...@@ -187,6 +187,7 @@ class User < ActiveRecord::Base ...@@ -187,6 +187,7 @@ class User < ActiveRecord::Base
scope :with_provider, ->(provider) do scope :with_provider, ->(provider) do
joins(:identities).where(identities: { provider: provider }) joins(:identities).where(identities: { provider: provider })
end end
scope :todo_authors, ->(user_id, state) { where(id: Todo.where(user_id: user_id, state: state).select(:author_id)) }
def self.with_two_factor def self.with_two_factor
joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id"). joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id").
......
class BaseSerializer
def initialize(parameters = {})
@request = EntityRequest.new(parameters)
end
def represent(resource, opts = {})
self.class.entity_class
.represent(resource, opts.merge(request: @request))
end
def self.entity(entity_class)
@entity_class ||= entity_class
end
def self.entity_class
@entity_class
end
end
class BuildEntity < Grape::Entity
include RequestAwareEntity
expose :id
expose :name
expose :build_url do |build|
url_to(:namespace_project_build, build)
end
expose :retry_url do |build|
url_to(:retry_namespace_project_build, build)
end
expose :play_url, if: ->(build, _) { build.manual? } do |build|
url_to(:play_namespace_project_build, build)
end
private
def url_to(route, build)
send("#{route}_url", build.project.namespace, build.project, build)
end
end
class CommitEntity < API::Entities::RepoCommit
include RequestAwareEntity
expose :author, using: UserEntity
expose :commit_url do |commit|
namespace_project_tree_url(
request.project.namespace,
request.project,
id: commit.id)
end
end
class DeploymentEntity < Grape::Entity
include RequestAwareEntity
expose :id
expose :iid
expose :sha
expose :ref do
expose :name do |deployment|
deployment.ref
end
expose :ref_url do |deployment|
namespace_project_tree_url(
deployment.project.namespace,
deployment.project,
id: deployment.ref)
end
end
expose :tag
expose :last?
expose :user, using: UserEntity
expose :commit, using: CommitEntity
expose :deployable, using: BuildEntity
expose :manual_actions, using: BuildEntity
end
class EntityRequest
# We use EntityRequest object to collect parameters and variables
# from the controller. Because options that are being passed to the entity
# do appear in each entity object in the chain, we need a way to pass data
# that is present in the controller (see #20045).
#
def initialize(parameters)
parameters.each do |key, value|
define_singleton_method(key) { value }
end
end
end
class EnvironmentEntity < Grape::Entity
include RequestAwareEntity
expose :id
expose :name
expose :state
expose :external_url
expose :environment_type
expose :last_deployment, using: DeploymentEntity
expose :stoppable?
expose :environment_url do |environment|
namespace_project_environment_url(
environment.project.namespace,
environment.project,
environment)
end
expose :created_at, :updated_at
end
class EnvironmentSerializer < BaseSerializer
entity EnvironmentEntity
end
module RequestAwareEntity
extend ActiveSupport::Concern
included do
include Gitlab::Routing.url_helpers
end
def request
@options.fetch(:request)
end
end
class UserEntity < API::Entities::UserBasic
end
...@@ -374,9 +374,9 @@ ...@@ -374,9 +374,9 @@
%fieldset %fieldset
%legend Repository Storage %legend Repository Storage
.form-group .form-group
= f.label :repository_storage, 'Storage path for new projects', class: 'control-label col-sm-2' = f.label :repository_storages, 'Storage paths for new projects', class: 'control-label col-sm-2'
.col-sm-10 .col-sm-10
= f.select :repository_storage, repository_storage_options_for_select, {}, class: 'form-control' = f.select :repository_storages, repository_storages_options_for_select, {include_hidden: false}, multiple: true, class: 'form-control'
.help-block .help-block
Manage repository storage paths. Learn more in the Manage repository storage paths. Learn more in the
= succeed "." do = succeed "." do
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
%span.visibility-icon.has-tooltip{data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group)} %span.visibility-icon.has-tooltip{data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group)}
= visibility_level_icon(group.visibility_level, fw: false) = visibility_level_icon(group.visibility_level, fw: false)
.image-container.s40 .avatar-container.s40
= image_tag group_icon(group), class: "avatar s40 hidden-xs" = image_tag group_icon(group), class: "avatar s40 hidden-xs"
.title .title
= link_to [:admin, group], class: 'group-name' do = link_to [:admin, group], class: 'group-name' do
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
Group info: Group info:
%ul.well-list %ul.well-list
%li %li
.image-container.s60 .avatar-container.s60
= image_tag group_icon(@group), class: "avatar s60" = image_tag group_icon(@group), class: "avatar s60"
%li %li
%span.light Name: %span.light Name:
......
- @no_container = true - @no_container = true
- page_title "Logs" - page_title "Logs"
- loggers = [Gitlab::GitLogger, Gitlab::AppLogger, - loggers = [Gitlab::GitLogger, Gitlab::AppLogger,
Gitlab::ProductionLogger, Gitlab::SidekiqLogger, Gitlab::EnvironmentLogger, Gitlab::SidekiqLogger,
Gitlab::RepositoryCheckLogger] Gitlab::RepositoryCheckLogger]
= render 'admin/background_jobs/head' = render 'admin/background_jobs/head'
......
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
.title .title
= link_to [:admin, project.namespace.becomes(Namespace), project] do = link_to [:admin, project.namespace.becomes(Namespace), project] do
.dash-project-avatar .dash-project-avatar
.image-container.s40 .avatar-container.s40
= project_icon(project, alt: '', class: 'avatar project-avatar s40') = project_icon(project, alt: '', class: 'avatar project-avatar s40')
%span.project-full-name %span.project-full-name
%span.namespace-name %span.namespace-name
......
xml.instruct! xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.title "#{current_user.name} issues" xml.title "#{current_user.name} issues"
xml.link href: issues_dashboard_url(format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: url_for(params), rel: "self", type: "application/atom+xml"
xml.link href: issues_dashboard_url, rel: "alternate", type: "text/html" xml.link href: issues_dashboard_url, rel: "alternate", type: "text/html"
xml.id issues_dashboard_url xml.id issues_dashboard_url
xml.updated @issues.first.created_at.xmlschema if @issues.reorder(nil).any? xml.updated @issues.first.created_at.xmlschema if @issues.reorder(nil).any?
......
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
- header_title "Issues", issues_dashboard_path(assignee_id: current_user.id) - header_title "Issues", issues_dashboard_path(assignee_id: current_user.id)
= content_for :meta_tags do = content_for :meta_tags do
- if current_user - if current_user
= auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues") = auto_discovery_link_tag(:atom, url_for(params.merge(format: :atom, private_token: current_user.private_token)), title: "#{current_user.name} issues")
.top-area .top-area
= render 'shared/issuable/nav', type: :issues = render 'shared/issuable/nav', type: :issues
.nav-controls .nav-controls
- if current_user - if current_user
= link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do = link_to url_for(params.merge(format: :atom, private_token: current_user.private_token)), class: 'btn' do
= icon('rss') = icon('rss')
%span.icon-label %span.icon-label
Subscribe Subscribe
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
- if params[:author_id].present? - if params[:author_id].present?
= hidden_field_tag(:author_id, params[:author_id]) = hidden_field_tag(:author_id, params[:author_id])
= dropdown_tag(user_dropdown_label(params[:author_id], 'Author'), options: { toggle_class: 'js-user-search js-filter-submit js-author-search', title: 'Filter by author', filter: true, filterInput: 'input#author-search', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit', = dropdown_tag(user_dropdown_label(params[:author_id], 'Author'), options: { toggle_class: 'js-user-search js-filter-submit js-author-search', title: 'Filter by author', filter: true, filterInput: 'input#author-search', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit',
placeholder: 'Search authors', data: { any_user: 'Any Author', first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: 'author_id', default_label: 'Author' } }) placeholder: 'Search authors', data: { any_user: 'Any Author', first_user: (current_user.username if current_user), project_id: (@project.id if @project), selected: params[:author_id], field_name: 'author_id', default_label: 'Author', todo_filter: true, todo_state_filter: params[:state] || 'pending' } })
.filter-item.inline .filter-item.inline
- if params[:type].present? - if params[:type].present?
= hidden_field_tag(:type, params[:type]) = hidden_field_tag(:type, params[:type])
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
.form-group .form-group
.col-sm-offset-2.col-sm-10 .col-sm-offset-2.col-sm-10
.image-container.s160 .avatar-container.s160
= image_tag group_icon(@group), alt: '', class: 'avatar group-avatar s160' = image_tag group_icon(@group), alt: '', class: 'avatar group-avatar s160'
%p.light %p.light
- if @group.avatar? - if @group.avatar?
......
xml.instruct! xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.title "#{@group.name} issues" xml.title "#{@group.name} issues"
xml.link href: issues_group_url(format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: url_for(params), rel: "self", type: "application/atom+xml"
xml.link href: issues_group_url, rel: "alternate", type: "text/html" xml.link href: issues_group_url, rel: "alternate", type: "text/html"
xml.id issues_group_url xml.id issues_group_url
xml.updated @issues.first.created_at.xmlschema if @issues.reorder(nil).any? xml.updated @issues.first.created_at.xmlschema if @issues.reorder(nil).any?
......
- page_title "Issues" - page_title "Issues"
= content_for :meta_tags do = content_for :meta_tags do
- if current_user - if current_user
= auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues") = auto_discovery_link_tag(:atom, url_for(params.merge(format: :atom, private_token: current_user.private_token)), title: "#{@group.name} issues")
.top-area .top-area
= render 'shared/issuable/nav', type: :issues = render 'shared/issuable/nav', type: :issues
.nav-controls .nav-controls
- if current_user - if current_user
= link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do = link_to url_for(params.merge(format: :atom, private_token: current_user.private_token)), class: 'btn' do
= icon('rss') = icon('rss')
%span.icon-label %span.icon-label
Subscribe Subscribe
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.cover-block.groups-cover-block .cover-block.groups-cover-block
%div{ class: container_class } %div{ class: container_class }
.image-container.s70.group-avatar .avatar-container.s70.group-avatar
= image_tag group_icon(@group), class: "avatar s70 avatar-tile" = image_tag group_icon(@group), class: "avatar s70 avatar-tile"
.group-info .group-info
.cover-title .cover-title
......
...@@ -26,13 +26,13 @@ ...@@ -26,13 +26,13 @@
Perform code reviews and enhance collaboration with merge requests. Perform code reviews and enhance collaboration with merge requests.
Each project can also have an issue tracker and a wiki. Each project can also have an issue tracker and a wiki.
- if current_application_settings.sign_in_text.present? - if current_application_settings.sign_in_text.present?
= markdown_field(current_application_settings, :sign_in_text) = markdown_field(current_application_settings, :sign_in_text)
- if current_application_settings.help_text.present? - if current_application_settings.help_text.present?
%h3 Need help? %h3 Need help?
%hr %hr
%p.slead %p.slead
= markdown(current_application_settings.help_text) = markdown(current_application_settings.help_text)
%hr.footer-fixed %hr.footer-fixed
.container.footer-container .container.footer-container
......
- empty_repo = @project.empty_repo? - empty_repo = @project.empty_repo?
.project-home-panel.text-center{ class: ("empty-project" if empty_repo) } .project-home-panel.text-center{ class: ("empty-project" if empty_repo) }
%div{ class: container_class } %div{ class: container_class }
.image-container.s70.project-avatar .avatar-container.s70.project-avatar
= project_icon(@project, alt: @project.name, class: 'avatar s70 avatar-tile') = project_icon(@project, alt: @project.name, class: 'avatar s70 avatar-tile')
%h1.project-title %h1.project-title
= @project.name = @project.name
......
- if commit.status - ref = local_assigns.fetch(:ref)
= link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{commit.status}" do - status = commit.status(ref)
= ci_icon_for_status(commit.status) - if status
= ci_label_for_status(commit.status) = link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do
= ci_icon_for_status(status)
= ci_label_for_status(status)
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
= link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message" = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message"
......
<<<<<<< HEAD
%fieldset.merge-requests-feature.append-bottom-default %fieldset.merge-requests-feature.append-bottom-default
%h5.prepend-top-0 %h5.prepend-top-0
Merge requests Merge requests
...@@ -102,3 +103,23 @@ ...@@ -102,3 +103,23 @@
:javascript :javascript
new UsersSelect(); new UsersSelect();
new GroupsSelect(); new GroupsSelect();
=======
.merge-requests-feature
%fieldset.builds-feature
%hr
%h5.prepend-top-0
Merge Requests
.form-group
.checkbox
= f.label :only_allow_merge_if_build_succeeds do
= f.check_box :only_allow_merge_if_build_succeeds
%strong Only allow merge requests to be merged if the build succeeds
%br
%span.descr
Builds need to be configured to enable this feature.
= link_to icon('question-circle'), help_page_path('user/project/merge_requests/merge_when_build_succeeds', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds')
.checkbox
= f.label :only_allow_merge_if_all_discussions_are_resolved do
= f.check_box :only_allow_merge_if_all_discussions_are_resolved
%strong Only allow merge requests to be merged if all discussions are resolved
>>>>>>> c392b0cc24ba40e3fed920c6c693cb24665193af
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
%ul.blob-commit-info.hidden-xs %ul.blob-commit-info.hidden-xs
- blob_commit = @repository.last_commit_for_path(@commit.id, blob.path) - blob_commit = @repository.last_commit_for_path(@commit.id, blob.path)
= render blob_commit, project: @project = render blob_commit, project: @project, ref: @ref
%div#blob-content-holder.blob-content-holder %div#blob-content-holder.blob-content-holder
%article.file-holder %article.file-holder
......
...@@ -14,13 +14,13 @@ ...@@ -14,13 +14,13 @@
= text_field_tag 'file_name', params[:file_name], placeholder: "File name", = text_field_tag 'file_name', params[:file_name], placeholder: "File name",
required: true, class: 'form-control new-file-name' required: true, class: 'form-control new-file-name'
.pull-right .pull-right.file-buttons
.license-selector.js-license-selector-wrap.hidden .license-selector.js-license-selector-wrap.hidden
= dropdown_tag("Choose a License template", options: { toggle_class: 'js-license-selector', title: "Choose a license", filter: true, placeholder: "Filter", data: { data: licenses_for_select, project: @project.name, fullname: @project.namespace.human_name } } ) = dropdown_tag("Choose a License template", options: { toggle_class: 'btn js-license-selector', title: "Choose a license", filter: true, placeholder: "Filter", data: { data: licenses_for_select, project: @project.name, fullname: @project.namespace.human_name } } )
.gitignore-selector.js-gitignore-selector-wrap.hidden .gitignore-selector.js-gitignore-selector-wrap.hidden
= dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } ) = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'btn js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } )
.gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden
= dropdown_tag("Choose a GitLab CI Yaml template", options: { toggle_class: 'js-gitlab-ci-yml-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } ) = dropdown_tag("Choose a GitLab CI Yaml template", options: { toggle_class: 'btn js-gitlab-ci-yml-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } )
= button_tag class: 'soft-wrap-toggle btn', type: 'button' do = button_tag class: 'soft-wrap-toggle btn', type: 'button' do
%span.no-wrap %span.no-wrap
= custom_icon('icon_no_wrap') = custom_icon('icon_no_wrap')
......
...@@ -26,6 +26,6 @@ ...@@ -26,6 +26,6 @@
:javascript :javascript
disableButtonIfEmptyField($('.js-upload-blob-form').find('.js-commit-message'), '.btn-upload-file'); gl.utils.disableButtonIfEmptyField($('.js-upload-blob-form').find('.js-commit-message'), '.btn-upload-file');
new BlobFileDropzone($('.js-upload-blob-form'), '#{method}'); new BlobFileDropzone($('.js-upload-blob-form'), '#{method}');
new NewCommitForm($('.js-upload-blob-form')) new NewCommitForm($('.js-upload-blob-form'))
.branch-commit .branch-commit
.icon-container.commit-icon
= custom_icon("icon_commit")
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-id monospace" = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-id monospace"
&middot; &middot;
%span.str-truncated %span.str-truncated
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
- else - else
Cant find HEAD commit for this branch Cant find HEAD commit for this branch
- stages_status = pipeline.statuses.relevant.latest.stages_status - stages_status = pipeline.statuses.latest.stages_status
%td.stage-cell %td.stage-cell
- stages.each do |stage| - stages.each do |stage|
- status = stages_status[stage] - status = stages_status[stage]
......
.commit-info-row.commit-info-row-header .commit-info-row.commit-info-row-header
%span.hidden-xs.hidden-sm Commit .commit-meta
= link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace js-details-short" %strong Commit
= link_to("#", class: "js-details-expand hidden-xs hidden-sm") do %strong.monospace.js-details-short= @commit.short_id
%span.text-expander = link_to("#", class: "js-details-expand hidden-xs hidden-sm") do
\... %span.text-expander
%span.js-details-content.hide \...
= link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace hidden-xs hidden-sm" %span.js-details-content.hide
= clipboard_button(clipboard_text: @commit.id) %strong.monospace.commit-hash-full= @commit.id
%span.hidden-xs authored = clipboard_button(clipboard_text: @commit.id)
#{time_ago_with_tooltip(@commit.authored_date)} %span.hidden-xs authored
%span by #{time_ago_with_tooltip(@commit.authored_date)}
= author_avatar(@commit, size: 24) %span by
%strong = author_avatar(@commit, size: 24)
= commit_author_link(@commit, avatar: true, size: 24)
- if @commit.different_committer?
%span.light Committed by
%strong %strong
= commit_committer_link(@commit, avatar: true, size: 24) = commit_author_link(@commit, avatar: true, size: 24)
#{time_ago_with_tooltip(@commit.committed_date)} - if @commit.different_committer?
%span.light Committed by
.pull-right.commit-action-buttons %strong
= commit_committer_link(@commit, avatar: true, size: 24)
#{time_ago_with_tooltip(@commit.committed_date)}
.commit-action-buttons
- if defined?(@notes_count) && @notes_count > 0 - if defined?(@notes_count) && @notes_count > 0
%span.btn.disabled.btn-grouped.hidden-xs.append-right-10 %span.btn.disabled.btn-grouped.hidden-xs.append-right-10
= icon('comment') = icon('comment')
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
Browse Files Browse Files
.dropdown.inline .dropdown.inline
%a.btn.btn-default.dropdown-toggle{ data: { toggle: "dropdown" } } %a.btn.btn-default.dropdown-toggle{ data: { toggle: "dropdown" } }
%span.hidden-xs Options %span Options
= icon('caret-down', class: ".commit-options-dropdown-caret") = icon('caret-down')
%ul.dropdown-menu.dropdown-menu-align-right %ul.dropdown-menu.dropdown-menu-align-right
%li.visible-xs-block.visible-sm-block %li.visible-xs-block.visible-sm-block
= link_to namespace_project_tree_path(@project.namespace, @project, @commit) do = link_to namespace_project_tree_path(@project.namespace, @project, @commit) do
......
- ref = local_assigns.fetch(:ref)
- if @note_counts - if @note_counts
- note_count = @note_counts.fetch(commit.id, 0) - note_count = @note_counts.fetch(commit.id, 0)
- else - else
...@@ -20,15 +21,15 @@ ...@@ -20,15 +21,15 @@
%span.commit-row-message.visible-xs-inline %span.commit-row-message.visible-xs-inline
&middot; &middot;
= commit.short_id = commit.short_id
- if commit.status - if commit.status(ref)
.visible-xs-inline .visible-xs-inline
= render_commit_status(commit) = render_commit_status(commit, ref: ref)
- if commit.description? - if commit.description?
%a.text-expander.hidden-xs.js-toggle-button ... %a.text-expander.hidden-xs.js-toggle-button ...
.commit-actions.hidden-xs .commit-actions.hidden-xs
- if commit.status - if commit.status(ref)
= render_commit_status(commit) = render_commit_status(commit, ref: ref)
= clipboard_button(clipboard_text: commit.id) = clipboard_button(clipboard_text: commit.id)
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent" = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent"
= link_to_browse_code(project, commit) = link_to_browse_code(project, commit)
......
...@@ -11,4 +11,4 @@ ...@@ -11,4 +11,4 @@
%li.warning-row.unstyled %li.warning-row.unstyled
#{number_with_delimiter(hidden)} additional commits have been omitted to prevent performance issues. #{number_with_delimiter(hidden)} additional commits have been omitted to prevent performance issues.
- else - else
%ul.content-list= render commits, project: @project %ul.content-list= render commits, project: @project, ref: @ref
- unless defined?(project) - ref = local_assigns.fetch(:ref)
- project = @project
- commits, hidden = limited_commits(@commits) - commits, hidden = limited_commits(@commits)
- commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits| - commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits|
%li.commit-header= "#{day.strftime('%d %b, %Y')} #{pluralize(commits.count, 'commit')}" %li.commit-header= "#{day.strftime('%d %b, %Y')} #{pluralize(commits.count, 'commit')}"
%li.commits-row %li.commits-row
%ul.list-unstyled.commit-list %ul.list-unstyled.commit-list
= render commits, project: project = render commits, project: project, ref: ref
- if hidden > 0 - if hidden > 0
%li.alert.alert-warning %li.alert.alert-warning
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
%div{id: dom_id(@project)} %div{id: dom_id(@project)}
%ol#commits-list.list-unstyled.content_list %ol#commits-list.list-unstyled.content_list
= render "commits", project: @project = render 'commits', project: @project, ref: @ref
= spinner = spinner
:javascript :javascript
......
%i.fa.diff-toggle-caret %i.fa.diff-toggle-caret.fa-fw
- if defined?(blob) && blob && diff_file.submodule? - if defined?(blob) && blob && diff_file.submodule?
%span %span
= icon('archive fw') = icon('archive fw')
......
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
= link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
- if Gitlab.config.registry.enabled - if Gitlab.config.registry.enabled
.form-group .form-group.js-container-registry{ style: ("display: none;" if @project.project_feature.send(:repository_access_level) == 0) }
.checkbox .checkbox
= f.label :container_registry_enabled do = f.label :container_registry_enabled do
= f.check_box :container_registry_enabled = f.check_box :container_registry_enabled
...@@ -130,7 +130,7 @@ ...@@ -130,7 +130,7 @@
Project avatar Project avatar
.form-group .form-group
- if @project.avatar? - if @project.avatar?
.image-container.s160 .avatar-container.s160
= project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160') = project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160')
%p.light %p.light
- if @project.avatar_in_git - if @project.avatar_in_git
......
xml.instruct! xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.title "#{@project.name} issues" xml.title "#{@project.name} issues"
xml.link href: namespace_project_issues_url(@project.namespace, @project, format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: url_for(params), rel: "self", type: "application/atom+xml"
xml.link href: namespace_project_issues_url(@project.namespace, @project), rel: "alternate", type: "text/html" xml.link href: namespace_project_issues_url(@project.namespace, @project), rel: "alternate", type: "text/html"
xml.id namespace_project_issues_url(@project.namespace, @project) xml.id namespace_project_issues_url(@project.namespace, @project)
xml.updated @issues.first.created_at.xmlschema if @issues.reorder(nil).any? xml.updated @issues.first.created_at.xmlschema if @issues.reorder(nil).any?
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
= content_for :meta_tags do = content_for :meta_tags do
- if current_user - if current_user
= auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") = auto_discovery_link_tag(:atom, url_for(params.merge(format: :atom, private_token: current_user.private_token)), title: "#{@project.name} issues")
%div{ class: (container_class) } %div{ class: (container_class) }
- if @project.issues.any? - if @project.issues.any?
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
= render 'shared/issuable/nav', type: :issues = render 'shared/issuable/nav', type: :issues
.nav-controls .nav-controls
- if current_user - if current_user
= link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do = link_to url_for(params.merge(format: :atom, private_token: current_user.private_token)), class: 'btn append-right-10' do
= icon('rss') = icon('rss')
%span.icon-label %span.icon-label
Subscribe Subscribe
......
= commit_to_html(@commit, @source_project, false) - if @commit
= commit_to_html(@commit, @ref, @source_project)
= commit_to_html(@commit, @target_project, false) - if @commit
= commit_to_html(@commit, @ref, @target_project)
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
Most recent commits displayed first Most recent commits displayed first
%ol#commits-list.list-unstyled %ol#commits-list.list-unstyled
= render "projects/commits/commits", project: @merge_request.source_project = render "projects/commits/commits", project: @merge_request.source_project, ref: @merge_request.source_branch
...@@ -29,10 +29,12 @@ ...@@ -29,10 +29,12 @@
= render 'projects/merge_requests/widget/open/merge_when_build_succeeds' = render 'projects/merge_requests/widget/open/merge_when_build_succeeds'
- elsif !@merge_request.can_be_merged_by?(current_user) - elsif !@merge_request.can_be_merged_by?(current_user)
= render 'projects/merge_requests/widget/open/not_allowed' = render 'projects/merge_requests/widget/open/not_allowed'
- elsif !@merge_request.mergeable_ci_state? && @pipeline && @pipeline.failed? - elsif !@merge_request.mergeable_ci_state?
= render 'projects/merge_requests/widget/open/build_failed' = render 'projects/merge_requests/widget/open/build_failed'
- elsif @merge_request.should_be_rebased? - elsif @merge_request.should_be_rebased?
= render 'projects/merge_requests/widget/open/rebase' = render 'projects/merge_requests/widget/open/rebase'
- elsif !@merge_request.mergeable_discussions_state?
= render 'projects/merge_requests/widget/open/unresolved_discussions'
- elsif @merge_request.can_be_merged? || resolved_conflicts - elsif @merge_request.can_be_merged? || resolved_conflicts
= render 'projects/merge_requests/widget/open/accept' = render 'projects/merge_requests/widget/open/accept'
......
%h4
= icon('exclamation-triangle')
This merge request has unresolved discussions
%p
Please resolve these discussions to allow this merge request to be merged.
\ No newline at end of file
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
= form.submit 'Save changes', class: 'btn btn-save' = form.submit 'Save changes', class: 'btn btn-save'
&nbsp; &nbsp;
- if @service.valid? && @service.activated? - if @service.valid? && @service.activated?
- disabled = @service.can_test? ? '':'disabled' - unless @service.can_test?
= link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service), class: "btn #{disabled}", title: @service.disabled_title - disabled_class = 'disabled'
- disabled_title = @service.disabled_title
= link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service), class: "btn #{disabled_class}", title: disabled_title
= link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel" = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel"
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
= render 'projects/last_push' = render 'projects/last_push'
= render "home_panel" = render "home_panel"
- if @project.feature_available?(:repository, current_user) - if current_user && can?(current_user, :download_code, @project)
%nav.project-stats{ class: container_class } %nav.project-stats{ class: container_class }
%ul.nav %ul.nav
%li %li
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
= render 'shared/notifications/button', notification_setting: @notification_setting = render 'shared/notifications/button', notification_setting: @notification_setting
- if @repository.commit - if @repository.commit
.project-last-commit{ class: container_class } .project-last-commit{ class: container_class }
= render 'projects/last_commit', commit: @repository.commit, project: @project = render 'projects/last_commit', commit: @repository.commit, ref: current_ref, project: @project
%div{ class: container_class } %div{ class: container_class }
- if @project.archived? - if @project.archived?
......
...@@ -46,5 +46,5 @@ ...@@ -46,5 +46,5 @@
:javascript :javascript
// Load last commit log for each file in tree // Load last commit log for each file in tree
$('#tree-slider').waitForImages(function() { $('#tree-slider').waitForImages(function() {
ajaxGet("#{escape_javascript(@logs_path)}"); gl.utils.ajaxGet("#{escape_javascript(@logs_path)}");
}); });
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
%span.visibility-icon.has-tooltip{data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group)} %span.visibility-icon.has-tooltip{data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group)}
= visibility_level_icon(group.visibility_level, fw: false) = visibility_level_icon(group.visibility_level, fw: false)
.image-container.s40 .avatar-container.s40
= image_tag group_icon(group), class: "avatar s40 hidden-xs" = image_tag group_icon(group), class: "avatar s40 hidden-xs"
.title .title
= link_to group, class: 'group-name' do = link_to group, class: 'group-name' do
......
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" class="ci-status-icon-canceled" viewBox="0 0 14 14">
<g fill="#5C5C5C" fill-rule="evenodd"> <g fill="#5C5C5C" fill-rule="evenodd">
<path d="M12.5,7 C12.5,3.96243388 10.0375661,1.5 7,1.5 C3.96243388,1.5 1.5,3.96243388 1.5,7 C1.5,10.0375661 3.96243388,12.5 7,12.5 C10.0375661,12.5 12.5,10.0375661 12.5,7 Z M0,7 C0,3.13400675 3.13400675,0 7,0 C10.8659932,0 14,3.13400675 14,7 C14,10.8659932 10.8659932,14 7,14 C3.13400675,14 0,10.8659932 0,7 Z"/> <path d="M12.5,7 C12.5,3.96243388 10.0375661,1.5 7,1.5 C3.96243388,1.5 1.5,3.96243388 1.5,7 C1.5,10.0375661 3.96243388,12.5 7,12.5 C10.0375661,12.5 12.5,10.0375661 12.5,7 Z M0,7 C0,3.13400675 3.13400675,0 7,0 C10.8659932,0 14,3.13400675 14,7 C14,10.8659932 10.8659932,14 7,14 C3.13400675,14 0,10.8659932 0,7 Z"/>
<rect width="8" height="2" x="3" y="6" transform="rotate(45 7 7)" rx=".5"/> <rect width="8" height="2" x="3" y="6" transform="rotate(45 7 7)" rx=".5"/>
......
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" enable-background="new 0 0 14 14"><path d="M12.5,7 C12.5,4 10,1.5 7,1.5 C4,1.5 1.5,4 1.5,7 C1.5,10 4,12.5 7,12.5 C10,12.5 12.5,10 12.5,7 L12.5,7 Z M0,7 C0,3.1 3.1,0 7,0 C10.9,0 14,3.1 14,7 C14,10.9 10.9,14 7,14 C3.1,14 0,10.9 0,7 L0,7 Z" /><circle cx="7" cy="7" r="3.25"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" class="ci-status-icon-created" viewBox="0 0 14 14" enable-background="new 0 0 14 14"><path d="M12.5,7 C12.5,4 10,1.5 7,1.5 C4,1.5 1.5,4 1.5,7 C1.5,10 4,12.5 7,12.5 C10,12.5 12.5,10 12.5,7 L12.5,7 Z M0,7 C0,3.1 3.1,0 7,0 C10.9,0 14,3.1 14,7 C14,10.9 10.9,14 7,14 C3.1,14 0,10.9 0,7 L0,7 Z" /><circle cx="7" cy="7" r="3.25"/></svg>
<svg width="20" height="20" class="ci-status-icon-skipped" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><title>Group Copy 31</title><g fill="#5C5C5C" fill-rule="evenodd"><path d="M10 17.857c4.286 0 7.857-3.571 7.857-7.857S14.286 2.143 10 2.143 2.143 5.714 2.143 10 5.714 17.857 10 17.857M10 0c5.571 0 10 4.429 10 10s-4.429 10-10 10S0 15.571 0 10 4.429 0 10 0"/><path d="M10.986 11l-1.293 1.293a1 1 0 0 0 1.414 1.414l2.644-2.644a1.505 1.505 0 0 0 0-2.126l-2.644-2.644a1 1 0 0 0-1.414 1.414L10.986 9H6.4a1 1 0 0 0 0 2h4.586z"/></g></svg>
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
%button.dropdown-menu-toggle.js-label-select.js-multiselect{class: classes.join(' '), type: "button", data: dropdown_data} %button.dropdown-menu-toggle.js-label-select.js-multiselect{class: classes.join(' '), type: "button", data: dropdown_data}
%span.dropdown-toggle-text{ class: ("is-default" if selected.nil? || selected.empty?) } %span.dropdown-toggle-text{ class: ("is-default" if selected.nil? || selected.empty?) }
= multi_label_name(selected, "Labels") = multi_label_name(selected, "Labels")
= icon('chevron-down') = icon('caret-down')
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
= render partial: "shared/issuable/label_page_default", locals: { title: dropdown_title, show_footer: show_footer, show_create: show_create } = render partial: "shared/issuable/label_page_default", locals: { title: dropdown_title, show_footer: show_footer, show_create: show_create }
- if show_create && project && can?(current_user, :admin_label, project) - if show_create && project && can?(current_user, :admin_label, project)
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
= link_to project_path(project), class: dom_class(project) do = link_to project_path(project), class: dom_class(project) do
- if avatar - if avatar
.dash-project-avatar .dash-project-avatar
.image-container.s40 .avatar-container.s40
- if use_creator_avatar - if use_creator_avatar
= image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:'' = image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:''
- else - else
......
.clearfix .clearfix
- groups.each do |group| - groups.each do |group|
= link_to group, class: 'profile-groups-avatars inline', title: group.name do = link_to group, class: 'profile-groups-avatars inline', title: group.name do
.image-container.s40 .avatar-container.s40
= image_tag group_icon(group), class: 'avatar group-avatar s40' = image_tag group_icon(group), class: 'avatar group-avatar s40'
---
title: Add setting to only allow merge requests to be merged when all discussions are resolved
merge_request: 7125
author: Rodolfo Arruda
---
title: 'Fix: Todos Filter Shows All Users'
merge_request:
author:
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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