Skip to content
Snippets Groups Projects
Commit 4e236971 authored by Andriy Dyadyura's avatar Andriy Dyadyura
Browse files

Merge branch 'master' of https://gitlab.com/gitlab-org/gitlab-ce into dropdown-counter-update

parents 3a3637f3 0eef8276
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -4,6 +4,7 @@ v 8.5.0 (unreleased)
- Remove gray background from layout in UI
 
v 8.4.0 (unreleased)
- Add pagination headers to already paginated API resources
- Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages
- Autocomplete data is now always loaded, instead of when focusing a comment text area (Yorick Peterse)
- Improved performance of finding issues for an entire group (Yorick Peterse)
Loading
Loading
@@ -50,6 +51,7 @@ v 8.4.0 (unreleased)
- Fix Encoding::CompatibilityError bug when markdown content has some complex URL (Jason Lee)
- Add API support for managing build variables of project
- Allow broadcast messages to be edited
- Autosize Markdown textareas
- Import GitHub wiki into GitLab
 
v 8.3.4
Loading
Loading
#= require autosize
$ ->
autosize($('.js-autosize'))
#= require autosave
#= require autosize
#= require dropzone
#= require dropzone_input
#= require gfm_auto_complete
Loading
Loading
@@ -246,6 +247,7 @@ class @Notes
else
previewButton.removeClass("turn-on").addClass "turn-off"
 
autosize(textarea)
new Autosave textarea, [
"Note"
form.find("#note_commit_id").val()
Loading
Loading
Loading
Loading
@@ -83,6 +83,7 @@
background: #FFF;
border: 1px solid #ddd;
min-height: 140px;
max-height: 430px;
padding: 5px;
box-shadow: none;
width: 100%;
Loading
Loading
Loading
Loading
@@ -159,6 +159,7 @@
.edit_note {
.markdown-area {
min-height: 140px;
max-height: 430px;
}
.note-form-actions {
background: transparent;
Loading
Loading
.zennable
.zen-backdrop
- classes << ' js-gfm-input markdown-area'
- classes << ' js-gfm-input js-autosize markdown-area'
- if defined?(f) && f
= f.text_area attr, class: classes
- else
Loading
Loading
Loading
Loading
@@ -97,11 +97,9 @@ module API
end
 
def paginate(relation)
per_page = params[:per_page].to_i
paginated = relation.page(params[:page]).per(per_page)
add_pagination_headers(paginated, per_page)
paginated
relation.page(params[:page]).per(params[:per_page].to_i).tap do |data|
add_pagination_headers(data)
end
end
 
def authenticate!
Loading
Loading
@@ -329,16 +327,26 @@ module API
 
private
 
def add_pagination_headers(paginated, per_page)
def add_pagination_headers(paginated_data)
header 'X-Total', paginated_data.total_count.to_s
header 'X-Total-Pages', paginated_data.total_pages.to_s
header 'X-Per-Page', paginated_data.limit_value.to_s
header 'X-Page', paginated_data.current_page.to_s
header 'X-Next-Page', paginated_data.next_page.to_s
header 'X-Prev-Page', paginated_data.prev_page.to_s
header 'Link', pagination_links(paginated_data)
end
def pagination_links(paginated_data)
request_url = request.url.split('?').first
 
links = []
links << %(<#{request_url}?page=#{paginated.current_page - 1}&per_page=#{per_page}>; rel="prev") unless paginated.first_page?
links << %(<#{request_url}?page=#{paginated.current_page + 1}&per_page=#{per_page}>; rel="next") unless paginated.last_page?
links << %(<#{request_url}?page=1&per_page=#{per_page}>; rel="first")
links << %(<#{request_url}?page=#{paginated.total_pages}&per_page=#{per_page}>; rel="last")
links << %(<#{request_url}?page=#{paginated_data.current_page - 1}&per_page=#{paginated_data.limit_value}>; rel="prev") unless paginated_data.first_page?
links << %(<#{request_url}?page=#{paginated_data.current_page + 1}&per_page=#{paginated_data.limit_value}>; rel="next") unless paginated_data.last_page?
links << %(<#{request_url}?page=1&per_page=#{paginated_data.limit_value}>; rel="first")
links << %(<#{request_url}?page=#{paginated_data.total_pages}&per_page=#{paginated_data.limit_value}>; rel="last")
 
header 'Link', links.join(', ')
links.join(', ')
end
 
def abilities
Loading
Loading
require 'spec_helper'
 
describe API::API, api: true do
describe API::CommitStatus, api: true do
include ApiHelpers
let(:user) { create(:user) }
let(:user2) { create(:user) }
Loading
Loading
@@ -12,6 +12,10 @@ describe API::API, api: true do
let(:commit_status) { create(:commit_status, commit: ci_commit) }
 
describe "GET /projects/:id/repository/commits/:sha/statuses" do
it_behaves_like 'a paginated resources' do
let(:request) { get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", user) }
end
context "reporter user" do
let(:statuses_id) { json_response.map { |status| status['id'] } }
 
Loading
Loading
Loading
Loading
@@ -32,6 +32,10 @@ describe API::API, api: true do
before { project.team << [user, :reporter] }
 
describe "GET /projects/:id/noteable/:noteable_id/notes" do
it_behaves_like 'a paginated resources' do
let(:request) { get api("/projects/#{project.id}/issues/#{issue.id}/notes", user) }
end
context "when noteable is an Issue" do
it "should return an array of issue notes" do
get api("/projects/#{project.id}/issues/#{issue.id}/notes", user)
Loading
Loading
# Specs for paginated resources.
#
# Requires an API request:
# let(:request) { get api("/projects/#{project.id}/repository/branches", user) }
shared_examples 'a paginated resources' do
before do
# Fires the request
request
end
it 'has pagination headers' do
expect(response.headers).to include('X-Total')
expect(response.headers).to include('X-Total-Pages')
expect(response.headers).to include('X-Per-Page')
expect(response.headers).to include('X-Page')
expect(response.headers).to include('X-Next-Page')
expect(response.headers).to include('X-Prev-Page')
expect(response.headers).to include('Link')
end
end
/*!
Autosize 3.0.14
license: MIT
http://www.jacklmoore.com/autosize
*/
(function (global, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports', 'module'], factory);
} else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
factory(exports, module);
} else {
var mod = {
exports: {}
};
factory(mod.exports, mod);
global.autosize = mod.exports;
}
})(this, function (exports, module) {
'use strict';
var set = typeof Set === 'function' ? new Set() : (function () {
var list = [];
return {
has: function has(key) {
return Boolean(list.indexOf(key) > -1);
},
add: function add(key) {
list.push(key);
},
'delete': function _delete(key) {
list.splice(list.indexOf(key), 1);
} };
})();
function assign(ta) {
var _ref = arguments[1] === undefined ? {} : arguments[1];
var _ref$setOverflowX = _ref.setOverflowX;
var setOverflowX = _ref$setOverflowX === undefined ? true : _ref$setOverflowX;
var _ref$setOverflowY = _ref.setOverflowY;
var setOverflowY = _ref$setOverflowY === undefined ? true : _ref$setOverflowY;
if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || set.has(ta)) return;
var heightOffset = null;
var overflowY = null;
var clientWidth = ta.clientWidth;
function init() {
var style = window.getComputedStyle(ta, null);
overflowY = style.overflowY;
if (style.resize === 'vertical') {
ta.style.resize = 'none';
} else if (style.resize === 'both') {
ta.style.resize = 'horizontal';
}
if (style.boxSizing === 'content-box') {
heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
} else {
heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
}
// Fix when a textarea is not on document body and heightOffset is Not a Number
if (isNaN(heightOffset)) {
heightOffset = 0;
}
update();
}
function changeOverflow(value) {
{
// Chrome/Safari-specific fix:
// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
// made available by removing the scrollbar. The following forces the necessary text reflow.
var width = ta.style.width;
ta.style.width = '0px';
// Force reflow:
/* jshint ignore:start */
ta.offsetWidth;
/* jshint ignore:end */
ta.style.width = width;
}
overflowY = value;
if (setOverflowY) {
ta.style.overflowY = value;
}
resize();
}
function resize() {
var htmlTop = window.pageYOffset;
var bodyTop = document.body.scrollTop;
var originalHeight = ta.style.height;
ta.style.height = 'auto';
var endHeight = ta.scrollHeight + heightOffset;
if (ta.scrollHeight === 0) {
// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
ta.style.height = originalHeight;
return;
}
ta.style.height = endHeight + 'px';
// used to check if an update is actually necessary on window.resize
clientWidth = ta.clientWidth;
// prevents scroll-position jumping
document.documentElement.scrollTop = htmlTop;
document.body.scrollTop = bodyTop;
}
function update() {
var startHeight = ta.style.height;
resize();
var style = window.getComputedStyle(ta, null);
if (style.height !== ta.style.height) {
if (overflowY !== 'visible') {
changeOverflow('visible');
}
} else {
if (overflowY !== 'hidden') {
changeOverflow('hidden');
}
}
if (startHeight !== ta.style.height) {
var evt = document.createEvent('Event');
evt.initEvent('autosize:resized', true, false);
ta.dispatchEvent(evt);
}
}
var pageResize = function pageResize() {
if (ta.clientWidth !== clientWidth) {
update();
}
};
var destroy = (function (style) {
window.removeEventListener('resize', pageResize, false);
ta.removeEventListener('input', update, false);
ta.removeEventListener('keyup', update, false);
ta.removeEventListener('autosize:destroy', destroy, false);
ta.removeEventListener('autosize:update', update, false);
set['delete'](ta);
Object.keys(style).forEach(function (key) {
ta.style[key] = style[key];
});
}).bind(ta, {
height: ta.style.height,
resize: ta.style.resize,
overflowY: ta.style.overflowY,
overflowX: ta.style.overflowX,
wordWrap: ta.style.wordWrap });
ta.addEventListener('autosize:destroy', destroy, false);
// IE9 does not fire onpropertychange or oninput for deletions,
// so binding to onkeyup to catch most of those events.
// There is no way that I know of to detect something like 'cut' in IE9.
if ('onpropertychange' in ta && 'oninput' in ta) {
ta.addEventListener('keyup', update, false);
}
window.addEventListener('resize', pageResize, false);
ta.addEventListener('input', update, false);
ta.addEventListener('autosize:update', update, false);
set.add(ta);
if (setOverflowX) {
ta.style.overflowX = 'hidden';
ta.style.wordWrap = 'break-word';
}
init();
}
function destroy(ta) {
if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
var evt = document.createEvent('Event');
evt.initEvent('autosize:destroy', true, false);
ta.dispatchEvent(evt);
}
function update(ta) {
if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
var evt = document.createEvent('Event');
evt.initEvent('autosize:update', true, false);
ta.dispatchEvent(evt);
}
var autosize = null;
// Do nothing in Node.js environment and IE8 (or lower)
if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
autosize = function (el) {
return el;
};
autosize.destroy = function (el) {
return el;
};
autosize.update = function (el) {
return el;
};
} else {
autosize = function (el, options) {
if (el) {
Array.prototype.forEach.call(el.length ? el : [el], function (x) {
return assign(x, options);
});
}
return el;
};
autosize.destroy = function (el) {
if (el) {
Array.prototype.forEach.call(el.length ? el : [el], destroy);
}
return el;
};
autosize.update = function (el) {
if (el) {
Array.prototype.forEach.call(el.length ? el : [el], update);
}
return el;
};
}
module.exports = autosize;
});
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment