Commit 127e299f authored by Sean McGivern's avatar Sean McGivern

Merge branch 'ce-to-ee' into 'master'

Ce to ee

See merge request !1037
parents f8b5d4e2 680915d2
......@@ -7,10 +7,10 @@ exclude:
linters:
AltText:
enabled: false
enabled: true
ClassAttributeWithStaticValue:
enabled: false
enabled: true
ClassesBeforeIds:
enabled: false
......@@ -29,14 +29,14 @@ linters:
enabled: true
FinalNewline:
enabled: false
enabled: true
present: true
HtmlAttributes:
enabled: false
enabled: true
ImplicitDiv:
enabled: false
enabled: true
LeadingCommentSpace:
enabled: false
......@@ -80,10 +80,10 @@ linters:
enabled: false
SpaceBeforeScript:
enabled: false
enabled: true
SpaceInsideHashAttributes:
enabled: false
enabled: true
style: space
Indentation:
......@@ -94,7 +94,7 @@ linters:
enabled: true
TrailingWhitespace:
enabled: false
enabled: true
UnnecessaryInterpolation:
enabled: false
......
......@@ -89,10 +89,14 @@ gem 'dropzonejs-rails', '~> 0.7.1'
# for backups
gem 'fog-aws', '~> 0.9'
gem 'fog-core', '~> 1.40'
gem 'fog-google', '~> 0.5'
gem 'fog-local', '~> 0.3'
gem 'fog-openstack', '~> 0.1'
gem 'fog-rackspace', '~> 0.1.1'
# for Google storage
gem 'google-api-client', '~> 0.8.6'
# for aws storage
gem 'unf', '~> 0.1.4'
......@@ -337,7 +341,7 @@ end
gem 'newrelic_rpm', '~> 3.16'
gem 'octokit', '~> 4.3.0'
gem 'octokit', '~> 4.6.2'
gem 'mail_room', '~> 0.9.0'
......
......@@ -58,6 +58,10 @@ GEM
attr_encrypted (3.0.3)
encryptor (~> 3.0.0)
attr_required (1.0.0)
autoparse (0.3.3)
addressable (>= 2.3.1)
extlib (>= 0.9.15)
multi_json (>= 1.0.0)
autoprefixer-rails (6.2.3)
execjs
json
......@@ -192,6 +196,7 @@ GEM
excon (0.52.0)
execjs (2.6.0)
expression_parser (0.9.0)
extlib (0.9.16)
factory_girl (4.7.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.7.0)
......@@ -221,6 +226,10 @@ GEM
builder
excon (~> 0.49)
formatador (~> 0.2)
fog-google (0.5.0)
fog-core
fog-json
fog-xml
fog-json (1.0.2)
fog-core (~> 1.0)
multi_json (~> 1.10)
......@@ -301,6 +310,25 @@ GEM
json
multi_json
request_store (>= 1.0)
google-api-client (0.8.7)
activesupport (>= 3.2, < 5.0)
addressable (~> 2.3)
autoparse (~> 0.3)
extlib (~> 0.9)
faraday (~> 0.9)
googleauth (~> 0.3)
launchy (~> 2.4)
multi_json (~> 1.10)
retriable (~> 1.4)
signet (~> 0.6)
googleauth (0.5.1)
faraday (~> 0.9)
jwt (~> 1.4)
logging (~> 2.0)
memoist (~> 0.12)
multi_json (~> 1.11)
os (~> 0.9)
signet (~> 0.7)
grape (0.18.0)
activesupport
builder
......@@ -405,11 +433,16 @@ GEM
listen (3.0.5)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
little-plugger (1.1.4)
logging (2.1.0)
little-plugger (~> 1.1)
multi_json (~> 1.10)
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.4)
mime-types (>= 1.16, < 4)
mail_room (0.9.0)
memoist (0.15.0)
method_source (0.8.2)
mime-types (2.99.3)
mimemagic (0.3.0)
......@@ -439,8 +472,8 @@ GEM
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
octokit (4.6.2)
sawyer (~> 0.8.0, >= 0.5.3)
oj (2.17.4)
omniauth (1.3.1)
hashie (>= 1.2, < 4)
......@@ -497,6 +530,7 @@ GEM
org-ruby (0.9.12)
rubypants (~> 0.2)
orm_adapter (0.5.0)
os (0.9.6)
paranoia (2.2.0)
activerecord (>= 4.0, < 5.1)
parser (2.3.1.4)
......@@ -608,6 +642,7 @@ GEM
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
retriable (1.4.1)
rinku (2.0.0)
rotp (2.1.2)
rouge (2.0.7)
......@@ -669,9 +704,9 @@ GEM
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
sawyer (0.7.0)
addressable (>= 2.3.5, < 2.5)
faraday (~> 0.8, < 0.10)
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
scss_lint (0.47.1)
rake (>= 0.9, < 11)
sass (~> 3.4.15)
......@@ -699,6 +734,11 @@ GEM
sidekiq (>= 4.2.1)
sidekiq-limit_fetch (3.4.0)
sidekiq (>= 4)
signet (0.7.3)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (~> 1.5)
multi_json (~> 1.10)
simplecov (0.12.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
......@@ -870,6 +910,7 @@ DEPENDENCIES
flay (~> 2.6.1)
fog-aws (~> 0.9)
fog-core (~> 1.40)
fog-google (~> 0.5)
fog-local (~> 0.3)
fog-openstack (~> 0.1)
fog-rackspace (~> 0.1.1)
......@@ -887,6 +928,7 @@ DEPENDENCIES
gollum-lib (~> 4.2)
gollum-rugged_adapter (~> 0.4.2)
gon (~> 6.1.0)
google-api-client (~> 0.8.6)
grape (~> 0.18.0)
grape-entity (~> 0.6.0)
gssapi
......@@ -922,7 +964,7 @@ DEPENDENCIES
newrelic_rpm (~> 3.16)
nokogiri (~> 1.6.7, >= 1.6.7.2)
oauth2 (~> 1.2.0)
octokit (~> 4.3.0)
octokit (~> 4.6.2)
oj (~> 2.17.4)
omniauth (~> 1.3.1)
omniauth-auth0 (~> 1.4.1)
......
......@@ -75,7 +75,7 @@ $(() => {
});
gl.IssueBoardsSearch = new Vue({
el: '#js-boards-seach',
el: '#js-boards-search',
data: {
filters: Store.state.filters
},
......
......@@ -45,14 +45,28 @@
const issue = this.list.findIssue(this.detailIssue.issue.id);
if (issue) {
const offsetLeft = this.$el.offsetLeft;
const boardsList = document.querySelectorAll('.boards-list')[0];
const right = (this.$el.offsetLeft + this.$el.offsetWidth) - boardsList.offsetWidth;
const left = boardsList.scrollLeft - this.$el.offsetLeft;
const left = boardsList.scrollLeft - offsetLeft;
let right = (offsetLeft + this.$el.offsetWidth);
if (window.innerWidth > 768 && boardsList.classList.contains('is-compact')) {
// -290 here because width of boardsList is animating so therefore
// getting the width here is incorrect
// 290 is the width of the sidebar
right -= (boardsList.offsetWidth - 290);
} else {
right -= boardsList.offsetWidth;
}
if (right - boardsList.scrollLeft > 0) {
boardsList.scrollLeft = right;
$(boardsList).animate({
scrollLeft: right
}, this.sortableOptions.animation);
} else if (left > 0) {
boardsList.scrollLeft = this.$el.offsetLeft;
$(boardsList).animate({
scrollLeft: offsetLeft
}, this.sortableOptions.animation);
}
}
},
......@@ -65,7 +79,7 @@
}
},
mounted () {
const options = gl.issueBoards.getBoardSortableDefaultOptions({
this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({
disabled: this.disabled,
group: 'boards',
draggable: '.is-draggable',
......@@ -84,7 +98,7 @@
}
});
this.sortable = Sortable.create(this.$el.parentNode, options);
this.sortable = Sortable.create(this.$el.parentNode, this.sortableOptions);
},
});
})();
......@@ -20,6 +20,7 @@
gl.issueBoards.getBoardSortableDefaultOptions = (obj) => {
let defaultSortOptions = {
animation: 200,
forceFallback: true,
fallbackClass: 'is-dragging',
fallbackOnBody: true,
......
......@@ -55,6 +55,13 @@
$('.dropdown-toggle-text', $dropdown).text(text);
$dropdownContainer.removeClass('open');
});
$dropdownContainer.on('click', '.dropdown-content a', (e) => {
$dropdown.prop('title', e.target.text.replace(/_+?/g, '-'));
if ($dropdown.hasClass('has-tooltip')) {
$dropdown.tooltip('fixTitle');
}
});
});
};
......
......@@ -66,6 +66,17 @@
new UsernameValidator();
new ActiveTabMemoizer();
break;
case 'sessions:create':
if (!gon.u2f) break;
window.gl.u2fAuthenticate = new gl.U2FAuthenticate(
$("#js-authenticate-u2f"),
'#js-login-u2f-form',
gon.u2f,
document.querySelector('#js-login-2fa-device'),
document.querySelector('.js-2fa-form'),
);
window.gl.u2fAuthenticate.start();
break;
case 'projects:boards:show':
case 'projects:boards:index':
shortcut_handler = new ShortcutsNavigation();
......@@ -207,7 +218,9 @@
new gl.Members();
new UsersSelect();
break;
case 'projects:project_members:index':
case 'projects:members:show':
new gl.MemberExpirationDate('.js-access-expiration-date-groups');
new GroupsSelect();
new gl.MemberExpirationDate();
new gl.Members();
new UsersSelect();
......@@ -253,10 +266,6 @@
case 'projects:artifacts:browse':
new BuildArtifacts();
break;
case 'projects:group_links:index':
new gl.MemberExpirationDate();
new GroupsSelect();
break;
case 'search:show':
new Search();
break;
......
......@@ -80,9 +80,12 @@
}
parseSelectedDate() {
this.rawSelectedDate = $("input[name='" + this.fieldName + "']").val();
this.rawSelectedDate = $(`input[name='${this.fieldName}']`).val();
if (this.rawSelectedDate.length) {
let dateObj = new Date(this.rawSelectedDate);
// Construct Date object manually to avoid buggy dateString support within Date constructor
const dateArray = this.rawSelectedDate.split('-').map(v => parseInt(v, 10));
const dateObj = new Date(dateArray[0], dateArray[1] - 1, dateArray[2]);
this.displayedDate = $.datepicker.formatDate('M d, yy', dateObj);
} else {
this.displayedDate = 'No due date';
......
......@@ -45,7 +45,7 @@
return fn(item);
}).filter(Boolean);
window.gl.environmentsList.EnvironmentsComponent = Vue.component('environment-component', {
gl.environmentsList.EnvironmentsComponent = Vue.component('environment-component', {
props: {
store: {
type: Object,
......@@ -55,7 +55,7 @@
},
components: {
'environment-item': window.gl.environmentsList.EnvironmentItem,
'environment-item': gl.environmentsList.EnvironmentItem,
},
data() {
......@@ -216,7 +216,7 @@
<th class="environments-deploy">Last deployment</th>
<th class="environments-build">Build</th>
<th class="environments-commit">Commit</th>
<th class="environments-date"></th>
<th class="environments-date">Created</th>
<th class="hidden-xs environments-actions"></th>
</tr>
</thead>
......
......@@ -5,7 +5,7 @@
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
window.gl.environmentsList.ActionsComponent = Vue.component('actions-component', {
gl.environmentsList.ActionsComponent = Vue.component('actions-component', {
props: {
actions: {
type: Array,
......
......@@ -5,7 +5,7 @@
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
window.gl.environmentsList.ExternalUrlComponent = Vue.component('external-url-component', {
gl.environmentsList.ExternalUrlComponent = Vue.component('external-url-component', {
props: {
externalUrl: {
type: String,
......
......@@ -29,12 +29,12 @@
gl.environmentsList.EnvironmentItem = Vue.component('environment-item', {
components: {
'commit-component': window.gl.CommitComponent,
'actions-component': window.gl.environmentsList.ActionsComponent,
'external-url-component': window.gl.environmentsList.ExternalUrlComponent,
'stop-component': window.gl.environmentsList.StopComponent,
'rollback-component': window.gl.environmentsList.RollbackComponent,
'terminal-button-component': window.gl.environmentsList.TerminalButtonComponent,
'commit-component': gl.CommitComponent,
'actions-component': gl.environmentsList.ActionsComponent,
'external-url-component': gl.environmentsList.ExternalUrlComponent,
'stop-component': gl.environmentsList.StopComponent,
'rollback-component': gl.environmentsList.RollbackComponent,
'terminal-button-component': gl.environmentsList.TerminalButtonComponent,
},
props: {
......@@ -183,7 +183,7 @@
* @returns {String}
*/
createdDate() {
return window.gl.environmentsList.timeagoInstance.format(
return gl.environmentsList.timeagoInstance.format(
this.model.last_deployment.deployable.created_at,
);
},
......
......@@ -5,7 +5,7 @@
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
window.gl.environmentsList.RollbackComponent = Vue.component('rollback-component', {
gl.environmentsList.RollbackComponent = Vue.component('rollback-component', {
props: {
retryUrl: {
type: String,
......
......@@ -5,7 +5,7 @@
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
window.gl.environmentsList.StopComponent = Vue.component('stop-component', {
gl.environmentsList.StopComponent = Vue.component('stop-component', {
props: {
stopUrl: {
type: String,
......
......@@ -5,7 +5,7 @@
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
window.gl.environmentsList.TerminalButtonComponent = Vue.component('terminal-button-component', {
gl.environmentsList.TerminalButtonComponent = Vue.component('terminal-button-component', {
props: {
terminalPath: {
type: String,
......
......@@ -7,15 +7,17 @@
$(() => {
window.gl = window.gl || {};
if (window.gl.EnvironmentsListApp) {
window.gl.EnvironmentsListApp.$destroy(true);
if (gl.EnvironmentsListApp) {
gl.EnvironmentsListApp.$destroy(true);
}
const Store = window.gl.environmentsList.EnvironmentsStore;
const Store = gl.environmentsList.EnvironmentsStore;
window.gl.EnvironmentsListApp = new window.gl.environmentsList.EnvironmentsComponent({
gl.EnvironmentsListApp = new gl.environmentsList.EnvironmentsComponent({
el: document.querySelector('#environments-list-view'),
propsData: {
store: Store.create(),
},
});
});
......@@ -48,6 +48,7 @@
},
DefaultOptions: {
sorter: function(query, items, searchKey) {
this.setting.highlightFirst = query.length > 0;
if (gl.GfmAutoComplete.isLoading(items)) {
return items;
}
......@@ -55,11 +56,9 @@
},
filter: function(query, data, searchKey) {
if (gl.GfmAutoComplete.isLoading(data)) {
gl.GfmAutoComplete.togglePreventSelection.call(this, true);
gl.GfmAutoComplete.fetchData(this.$inputor, this.at);
return data;
} else {
gl.GfmAutoComplete.togglePreventSelection.call(this, false);
return $.fn.atwho["default"].callbacks.filter(query, data, searchKey);
}
},
......@@ -257,9 +256,9 @@
insertTpl: '${atwho-at}${title}',
callbacks: {
matcher: this.DefaultOptions.matcher,
sorter: this.DefaultOptions.sorter,
beforeInsert: this.DefaultOptions.beforeInsert,
filter: this.DefaultOptions.filter,
sorter: this.DefaultOptions.sorter,
beforeSave: function(merges) {
if (gl.GfmAutoComplete.isLoading(merges)) return merges;
var sanitizeLabelTitle;
......@@ -370,11 +369,7 @@
if (!data || !data.length) return false;
if (Array.isArray(data)) data = data[0];
return data === this.defaultLoadingData[0] || data.name === this.defaultLoadingData[0];
},
togglePreventSelection(isPrevented = !!this.setting.tabSelectsMatch) {
this.setting.tabSelectsMatch = !isPrevented;
this.setting.spaceSelectsMatch = !isPrevented;
},
}
};
}).call(this);
......@@ -35,8 +35,8 @@
autosize(this.textarea);
// form and textarea event listeners
this.addEventListeners();
gl.text.init(this.form);
}
gl.text.init(this.form);
// hide discard button
this.form.find('.js-note-discard').hide();
return this.form.show();
......
......@@ -106,8 +106,9 @@
);
};
gl.utils.getPagePath = function() {
return $('body').data('page').split(':')[0];
gl.utils.getPagePath = function(index) {
index = index || 0;
return $('body').data('page').split(':')[index];
};
gl.utils.parseUrl = function (url) {
......@@ -127,6 +128,17 @@
return e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
};
gl.utils.scrollToElement = function($el) {
var top = $el.offset().top;
gl.navBarHeight = gl.navBarHeight || $('.navbar-gitlab').height();
gl.navLinksHeight = gl.navLinksHeight || $('.nav-links').height();
gl.mrTabsHeight = gl.mrTabsHeight || $('.merge-request-tabs').height();
return $('body, html').animate({
scrollTop: top - (gl.navBarHeight + gl.navLinksHeight + gl.mrTabsHeight)
}, 200);
};
})(window);
}).call(this);
/**
* CustomEvent support for IE
*/
if (typeof window.CustomEvent !== 'function') {
window.CustomEvent = function CustomEvent(e, params) {
const options = params || { bubbles: false, cancelable: false, detail: undefined };
const evt = document.createEvent('CustomEvent');
evt.initCustomEvent(e, options.bubbles, options.cancelable, options.detail);
return evt;
};
window.CustomEvent.prototype = window.Event.prototype;
}
......@@ -44,9 +44,25 @@
}
};
gl.text.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
var insertText, inserted, selectedSplit, startChar;
var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine;
removedLastNewLine = false;
removedFirstNewLine = false;
// Remove the first newline
if (selected.indexOf('\n') === 0) {
removedFirstNewLine = true;
selected = selected.replace(/\n+/, '');
}
// Remove the last newline
if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) {
removedLastNewLine = true;
selected = selected.replace(/\n$/, '');
}
selectedSplit = selected.split('\n');
startChar = !wrap && textArea.selectionStart > 0 ? '\n' : '';
if (selectedSplit.length > 1 && (!wrap || (blockTag != null))) {
if (blockTag != null) {
insertText = this.blockTagText(text, textArea, blockTag, selected);
......@@ -62,6 +78,15 @@
} else {
insertText = "" + startChar + tag + selected + (wrap ? tag : ' ');
}
if (removedFirstNewLine) {
insertText = '\n' + insertText;
}
if (removedLastNewLine) {
insertText += '\n';
}
if (document.queryCommandSupported('insertText')) {
inserted = document.execCommand('insertText', false, insertText);
}
......@@ -74,9 +99,9 @@
document.execCommand("ms-endUndoUnit");
} catch (error) {}
}
return this.moveCursor(textArea, tag, wrap);
return this.moveCursor(textArea, tag, wrap, removedLastNewLine);
};
gl.text.moveCursor = function(textArea, tag, wrapped) {
gl.text.moveCursor = function(textArea, tag, wrapped, removedLastNewLine) {
var pos;
if (!textArea.setSelectionRange) {
return;
......@@ -87,6 +112,11 @@
} else {
pos = textArea.selectionStart;
}
if (removedLastNewLine) {
pos -= 1;
}
return textArea.setSelectionRange(pos, pos);
}
};
......
/* eslint-disable func-names, space-before-function-paren, vars-on-top, no-var, object-shorthand, comma-dangle, max-len */
(function() {
(() => {
// Add datepickers to all `js-access-expiration-date` elements. If those elements are
// children of an element with the `clearable-input` class, and have a sibling
// `js-clear-input` element, then show that element when there is a value in the
// datepicker, and make clicking on that element clear the field.
//
gl.MemberExpirationDate = function() {
window.gl = window.gl || {};
gl.MemberExpirationDate = (selector = '.js-access-expiration-date') => {
function toggleClearInput() {
$(this).closest('.clearable-input').toggleClass('has-value', $(this).val() !== '');
}
var inputs = $('.js-access-expiration-date');
const inputs = $(selector);
inputs.datepicker({
dateFormat: 'yy-mm-dd',
minDate: 1,
onSelect: function () {
onSelect: function onSelect() {
$(this).trigger('change');
toggleClearInput.call(this);
}
},
});
inputs.next('.js-clear-input').on('click', function(event) {
inputs.next('.js-clear-input').on('click', function clicked(event) {
event.preventDefault();
var input = $(this).closest('.clearable-input').find('.js-access-expiration-date');
const input = $(this).closest('.clearable-input').find(selector);
input.datepicker('setDate', null)
.trigger('change');
toggleClearInput.call(input);
......
......@@ -52,6 +52,12 @@
this.setupMainTargetNoteForm();
this.initTaskList();
this.collapseLongCommitList();
// We are in the Merge Requests page so we need another edit form for Changes tab
if (gl.utils.getPagePath(1) === 'merge_requests') {
$('.note-edit-form').clone()
.addClass('mr-note-edit-form').insertAfter('.note-edit-form');
}
}
Notes.prototype.addBinding = function() {
......@@ -63,7 +69,7 @@
// change note in UI after update
$(document).on("ajax:success", "form.edit-note", this.updateNote);
// Edit note link
$(document).on("click", ".js-note-edit", this.showEditForm);
$(document).on("click", ".js-note-edit", this.showEditForm.bind(this));
$(document).on("click", ".note-edit-cancel", this.cancelEdit);
// Reopen and close actions for Issue/MR combined with note form submit
$(document).on("click", ".js-comment-button", this.updateCloseButton);
......@@ -466,6 +472,7 @@
var $html, $note_li;
// Convert returned HTML to a jQuery object so we can modify it further
$html = $(note.html);
this.revertNoteEditForm();
gl.utils.localTimeAgo($('.js-timeago', $html));
$html.renderGFM();
$html.find('.js-task-list-container').taskList('enable');
......@@ -480,48 +487,56 @@
};
Notes.prototype.checkContentToAllowEditing = function($el) {
var initialContent = $el.find('.original-note-content').text().trim();
var currentContent = $el.find('.note-textarea').val();
var isAllowed = true;
if (currentContent === initialContent) {
this.removeNoteEditForm($el);
}
else {
var $buttons = $el.find('.note-form-actions');
var isWidgetVisible = gl.utils.isInViewport($el.get(0));
if (!isWidgetVisible) {
gl.utils.scrollToElement($el);
}
$el.find('.js-edit-warning').show();
isAllowed = false;
}
return isAllowed;
}
/*
Called in response to clicking the edit note link
Replaces the note text with the note edit form
Adds a data attribute to the form with the original content of the note for cancellations
*/
*/
Notes.prototype.showEditForm = function(e, scrollTo, myLastNote) {
var $noteText, done, form, note;
e.preventDefault();
note = $(this).closest(".note");
note.addClass("is-editting");
form = note.find(".note-edit-form");
form.addClass('current-note-edit-form');
// Show the attachment delete link
note.find(".js-note-attachment-delete").show();
done = function($noteText) {
var noteTextVal;
// Neat little trick to put the cursor at the end
noteTextVal = $noteText.val();
// Store the original note text in a data attribute to retrieve if a user cancels edit.
form.find('form.edit-note').data('original-note', noteTextVal);
return $noteText.val('').val(noteTextVal);
};
new GLForm(form);
if ((scrollTo != null) && (myLastNote != null)) {
// scroll to the bottom
// so the open of the last element doesn't make a jump
$('html, body').scrollTop($(document).height());
return $('html, body').animate({
scrollTop: myLastNote.offset().top - 150
}, 500, function() {
var $noteText;
$noteText = form.find(".js-note-text");
$noteText.focus();
return done($noteText);
});
} else {
$noteText = form.find('.js-note-text');
$noteText.focus();
return done($noteText);
var $target = $(e.target);
var $editForm = $(this.getEditFormSelector($target));
var $note = $target.closest('.note');
var $currentlyEditing = $('.note.is-editting:visible');
if ($currentlyEditing.length) {
var isEditAllowed = this.checkContentToAllowEditing($currentlyEditing);
if (!isEditAllowed) {
return;
}
}
$note.find('.js-note-attachment-delete').show();
$editForm.addClass('current-note-edit-form');
$note.addClass('is-editting');
this.putEditFormInPlace($target);
};
......@@ -532,19 +547,41 @@
*/
Notes.prototype.cancelEdit = function(e) {
var note;
e.preventDefault();
note = $(e.target).closest('.note');
var $target = $(e.target);
var note = $target.closest('.note');
note.find('.js-edit-warning').hide();
this.revertNoteEditForm($target);
return this.removeNoteEditForm(note);
};
Notes.prototype.revertNoteEditForm = function($target) {
$target = $target || $('.note.is-editting:visible');
var selector = this.getEditFormSelector($target);
var $editForm = $(selector);
$editForm.insertBefore('.notes-form');
$editForm.find('.js-comment-button').enable();
$editForm.find('.js-edit-warning').hide();
};
Notes.prototype.getEditFormSelector = function($el) {
var selector = '.note-edit-form:not(.mr-note-edit-form)';
if ($el.parents('#diffs').length) {
selector = '.note-edit-form.mr-note-edit-form';
}
return selector;
};
Notes.prototype.removeNoteEditForm = function(note) {
var form;
form = note.find(".current-note-edit-form");
note.removeClass("is-editting");
form.removeClass("current-note-edit-form");
var form = note.find('.current-note-edit-form');
note.removeClass('is-editting');
form.removeClass('current-note-edit-form');
form.find('.js-edit-warning').hide();
// Replace markdown textarea text with original note text.
return form.find(".js-note-text").val(form.find('form.edit-note').data('original-note'));
return form.find('.js-note-text').val(form.find('form.edit-note').data('original-note'));
};
......@@ -837,15 +874,46 @@
Notes.prototype.initTaskList = function() {
this.enableTaskList();
return $(document).on('tasklist:changed', '.note .js-task-list-container', this.updateTaskList);
return $(document).on('tasklist:changed', '.note .js-task-list-container', this.updateTaskList.bind(this));
};
Notes.prototype.enableTaskList = function() {
return $('.note .js-task-list-container').taskList('enable');
};
Notes.prototype.updateTaskList = function() {
return $('form', this).submit();
Notes.prototype.putEditFormInPlace = function($el) {
var $editForm = $(this.getEditFormSelector($el));
var $note = $el.closest('.note');
$editForm.insertAfter($note.find('.note-text'));
var $originalContentEl = $note.find('.original-note-content');
var originalContent = $originalContentEl.text().trim();
var postUrl = $originalContentEl.data('post-url');
var targetId = $originalContentEl.data('target-id');
var targetType = $originalContentEl.data('target-type');
new GLForm($editForm.find('form'));
$editForm.find('form')
.attr('action', postUrl)
.attr('data-remote', 'true');
$editForm.find('.js-form-target-id').val(targetId);
$editForm.find('.js-form-target-type').val(targetType);
$editForm.find('.js-note-text').focus().val(originalContent);
$editForm.find('.js-md-write-button').trigger('click');
$editForm.find('.referenced-users').hide();
}
Notes.prototype.updateTaskList = function(e) {
var $target = $(e.target);
var $list = $target.closest('.js-task-list-container');
var $editForm = $(this.getEditFormSelector($target));
var $note = $list.closest('.note');
this.putEditFormInPlace($list);
$editForm.find('#note_note').val($note.find('.original-task-list').val());
$('form', $list).submit();
};
Notes.prototype.updateNotesCount = function(updateCount) {
......
......@@ -41,15 +41,12 @@
}
beforeUpdateUsername() {
$('.loading-username').show();
$(this).find('.update-success').hide();
return $(this).find('.update-failed').hide();
$('.loading-username', this).removeClass('hidden');
}
afterUpdateUsername() {
$('.loading-username').hide();
$(this).find('.btn-save').enable();
return $(this).find('.loading-gif').hide();
$('.loading-username', this).addClass('hidden');
$('button[type=submit]', this).enable();
}
onUpdateNotifs(e, data) {
......
......@@ -23,7 +23,7 @@
});
$('.no-template', this.dropdown.parent()).on('click', () => {
this.currentTemplate = '';
this.currentTemplate.content = '';
this.setInputValueToTemplateContent();
$('.dropdown-toggle-text', this.dropdown).text('Choose a template');
});
......
//= require xterm/encoding-indexes
//= require xterm/encoding
//= require xterm/xterm.js
//= require xterm/fit.js
//= require ./terminal.js
......
......@@ -8,21 +8,26 @@
// State Flow #1: setup -> in_progress -> authenticated -> POST to server
// State Flow #2: setup -> in_progress -> error -> setup
(function() {
const global = window.gl || (window.gl = {});
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
this.U2FAuthenticate = (function() {
function U2FAuthenticate(container, u2fParams) {
global.U2FAuthenticate = (function() {
function U2FAuthenticate(container, form, u2fParams, fallbackButton, fallbackUI) {
this.container = container;
this.renderNotSupported = bind(this.renderNotSupported, this);
this.renderAuthenticated = bind(this.renderAuthenticated, this);
this.renderError = bind(this.renderError, this);
this.renderInProgress = bind(this.renderInProgress, this);
this.renderSetup = bind(this.renderSetup, this);
this.renderTemplate = bind(this.renderTemplate, this);
this.authenticate = bind(this.authenticate, this);
this.start = bind(this.start, this);
this.appId = u2fParams.app_id;
this.challenge = u2fParams.challenge;
this.form = form;
this.fallbackButton = fallbackButton;
this.fallbackUI = fallbackUI;
if (this.fallbackButton) this.fallbackButton.addEventListener('click', this.switchToFallbackUI.bind(this));
this.signRequests = u2fParams.sign_requests.map(function(request) {
// The U2F Javascript API v1.1 requires a single challenge, with
// _no challenges per-request_. The U2F Javascript API v1.0 requires a
......@@ -41,7 +46,7 @@
U2FAuthenticate.prototype.start = function() {
if (U2FUtil.isU2FSupported()) {
return this.renderSetup();
return this.renderInProgress();
} else {
return this.renderNotSupported();
}
......@@ -77,11 +82,6 @@
return this.container.html(template(params));
};
U2FAuthenticate.prototype.renderSetup = function() {
this.renderTemplate('setup');
return this.container.find('#js-login-u2f-device').on('click', this.renderInProgress);
};
U2FAuthenticate.prototype.renderInProgress = function() {
this.renderTemplate('inProgress');
return this.authenticate();
......@@ -92,22 +92,29 @@
error_message: error.message(),
error_code: error.errorCode
});
return this.container.find('#js-u2f-try-again').on('click', this.renderSetup);
return this.container.find('#js-u2f-try-again').on('click', this.renderInProgress);
};
U2FAuthenticate.prototype.renderAuthenticated = function(deviceResponse) {
this.renderTemplate('authenticated');
// Prefer to do this instead of interpolating using Underscore templates
// because of JSON escaping issues.
return this.container.find("#js-device-response").val(deviceResponse);
const container = this.container[0];
container.querySelector('#js-device-response').value = deviceResponse;
container.querySelector(this.form).submit();
this.fallbackButton.classList.add('hidden');
};
U2FAuthenticate.prototype.renderNotSupported = function() {
return this.renderTemplate('notSupported');
};
U2FAuthenticate.prototype.switchToFallbackUI = function() {
this.fallbackButton.classList.add('hidden');
this.container[0].classList.add('hidden');
this.fallbackUI.classList.remove('hidden');
};
return U2FAuthenticate;
})();
}).call(this);
})();
......@@ -97,8 +97,20 @@
padding: 5px 6px;
outline: 0;
&:hover,
&.disabled {
cursor: default;
&:hover,
&:focus,
&:active {
background-color: $white-light;
border-color: $border-color;
box-shadow: none;
}
}
&.active,
&:hover,
&:active {
background-color: $row-hover;
border-color: $row-hover-border;
......
......@@ -4,8 +4,3 @@
color: $badge-color;
vertical-align: baseline;
}
.badge-dark {
background-color: $badge-bg-dark;
color: $badge-color-dark;
}
.centered-light-block {
text-align: center;
color: $gl-gray;
color: $gl-text-color;
margin: 20px;
}
.nothing-here-block {
text-align: center;
padding: 20px;
color: $gl-gray;
color: $gl-text-color;
font-weight: normal;
font-size: 14px;
line-height: 36px;
......@@ -29,7 +29,7 @@
margin-bottom: 0;
border-top: 1px solid $white-dark;
border-bottom: 1px solid $white-dark;
color: $gl-gray;
color: $gl-text-color;
&.oneline-block {
line-height: 42px;
......@@ -135,11 +135,11 @@
}
.cover-title {
color: $gl-header-color;
color: $gl-text-color;
font-size: 23px;
h1 {
color: $gl-gray-dark;
color: $gl-text-color;
margin-bottom: 6px;
font-size: 23px;
}
......@@ -153,7 +153,7 @@
p {
padding: 0 $gl-padding;
color: $gl-text-color-dark;
color: $gl-text-color;
}
}
......@@ -211,7 +211,7 @@
display: inline;
font-weight: normal;
font-size: 24px;
color: $gl-title-color;
color: $gl-text-color;
}
}
}
......
......@@ -88,7 +88,7 @@
}
@mixin btn-gray {
@include btn-color($gray-light, $border-gray-normal, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, $gl-gray-dark);
@include btn-color($gray-light, $border-gray-normal, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, $gl-text-color);
}
@mixin btn-white {
......@@ -242,7 +242,7 @@
}
.btn-transparent {
color: $gl-gray-light;
color: $gl-text-color-secondary;
background-color: transparent;
border: 0;
......@@ -338,7 +338,7 @@
margin-left: 10px;
i {
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
}
......
......@@ -26,6 +26,7 @@
.append-bottom-default { margin-bottom: $gl-padding; }
.inline { display: inline-block; }
.center { text-align: center; }
.vertical-align-middle { vertical-align: middle; }
.underlined-link { text-decoration: underline; }
.hint { font-style: italic; color: $hint-color; }
......@@ -415,7 +416,7 @@ table {
padding: 0 10px;
clip: auto;
text-decoration: none;
color: $gl-title-color;
color: $gl-text-color;
background: $gray-light;
z-index: 1;
}
......
......@@ -205,7 +205,7 @@
}
.icon-play {
fill: $gl-gray-light;
fill: $gl-text-color-secondary;
margin-right: 6px;
height: 12px;
width: 11px;
......@@ -213,7 +213,7 @@
}
.dropdown-header {
color: $gl-gray-light;
color: $gl-text-color-secondary;
font-size: 13px;
line-height: 22px;
padding: 0 10px;
......@@ -226,7 +226,7 @@
.unclickable {
cursor: not-allowed;
padding: 5px 8px;
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
}
......@@ -596,7 +596,7 @@
}
.ui-datepicker-title {
color: $gl-gray;
color: $gl-text-color;
font-size: 14px;
line-height: 1;
font-weight: normal;
......@@ -618,17 +618,17 @@
.dropdown-menu-inner-title {
display: block;
color: $gl-title-color;
color: $gl-text-color;
font-weight: 600;
}
.dropdown-menu-inner-content {
display: block;
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
.dropdown-toggle-text {
&.is-default {
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
}
......@@ -182,3 +182,52 @@ span.idiff {
border-bottom-right-radius: 2px;
}
}
.file-stats {
ul {
list-style: none;
margin: 0;
padding: 10px 0;
li {
padding: 3px 0;
line-height: 20px;
}
}
.new-file {
a {
color: $gl-text-green;
}
}
.renamed-file {
a {
color: $gl-text-orange;
}
}
.deleted-file {
a {
color: $gl-text-red;
}
}
.edit-file {
a {
color: $gl-text-color;
}
}
a {
text-decoration: none;
.new-file {
color: $notify-new-file;
}
.deleted-file {
color: $notify-deleted-file;
}
}
}
......@@ -153,7 +153,7 @@ label {
}
.form-control::-webkit-input-placeholder {
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
.input-group {
......
......@@ -45,7 +45,7 @@ header {
padding: 0;
.nav > li > a {
color: $gl-gray-light;
color: $gl-text-color-secondary;
font-size: 18px;
padding: 0;
margin: ($header-height - 28) / 2 0;
......@@ -63,7 +63,7 @@ header {
&:focus,
&:active {
background-color: $gray-light;
color: darken($gl-gray-light, 30%);
color: darken($gl-text-color-secondary, 30%);
.todos-pending-count {
background: darken($todo-alert-blue, 10%);
......@@ -88,7 +88,7 @@ header {
}
&.active {
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
}
}
......
......@@ -34,10 +34,10 @@
.ci-status-icon-canceled,
.ci-status-icon-disabled,
.ci-status-icon-not-found {
color: $gl-gray;
color: $gl-text-color;
svg {
fill: $gl-gray;
fill: $gl-text-color;
}
}
......
......@@ -41,6 +41,6 @@
}
&.status-box-upcoming {
background: $gl-gray-light;
background: $gl-text-color-secondary;
}
}
......@@ -128,7 +128,7 @@ ul.content-list {
}
a {
color: $gl-dark-link-color;
color: $gl-text-color;
}
.member-group-link {
......@@ -169,6 +169,10 @@ ul.content-list {
&:last-child {
margin-right: 0;
@media(max-width: $screen-xs-max) {
margin: 0 auto;
}
}
}
......@@ -236,18 +240,50 @@ ul.content-list {
}
.label-default {
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
}
.panel > .content-list > li {
padding: $gl-padding-top $gl-padding;
// Table list
.table-list {
display: table;
width: 100%;
.table-list-row {
display: table-row;
}
&.commit {
@media (min-width: $screen-sm-min) {
padding-left: 46px + $gl-padding;
.table-list-cell {
display: table-cell;
vertical-align: top;
padding: 10px 16px;
border-bottom: 1px solid $gray-darker;
&.avatar-cell {
width: 36px;
padding-right: 0;
img {
margin-right: 0;
}
}
}
&.table-wide {
.table-list-cell {
&:last-of-type {
padding-right: 0;
}
&:first-of-type {
padding-left: 0;
}
}
}
}
.panel > .content-list > li {
padding: $gl-padding-top $gl-padding;
}
ul.controls {
......
......@@ -73,7 +73,7 @@
}
.referenced-users {
color: $gl-header-color;
color: $gl-text-color;
padding-top: 10px;
}
......@@ -135,7 +135,7 @@
.toolbar-btn {
float: left;
padding: 0 5px;
color: $gl-gray-light;
color: $gl-text-color-secondary;
background: transparent;
border: 0;
outline: 0;
......
......@@ -46,7 +46,7 @@
&.light {
a {
color: $gl-gray;
color: $gl-text-color;
}
}
}
......
......@@ -51,7 +51,7 @@
margin-bottom: -1px;
font-size: 14px;
line-height: 28px;
color: $gl-gray-light;
color: $gl-text-color-secondary;
border-bottom: 2px solid transparent;
&:hover,
......@@ -315,7 +315,7 @@
.fa-caret-down {
margin-left: 5px;
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
.dropdown {
......
......@@ -14,7 +14,7 @@
.header-action-buttons {
i {
color: $gl-gray-light;
color: $gl-text-color-secondary;
font-size: 13px;
margin-right: 3px;
}
......@@ -42,7 +42,7 @@
.commit-committer-link,
.commit-author-link {
color: $gl-gray;
color: $gl-text-color;
font-weight: bold;
}
......
......@@ -48,3 +48,11 @@
line-height: inherit;
}
}
.panel-default {
.table-list-row:last-child {
.table-list-cell {
border-bottom: 0;
}
}
}
......@@ -7,7 +7,7 @@
.timeline-entry {
padding: $gl-padding $gl-btn-padding 11px;
border-color: $white-normal;
color: $gl-gray;
color: $gl-text-color;
border-bottom: 1px solid $border-white-light;
&:target {
......@@ -32,7 +32,7 @@
.system-note {
.note-text {
color: $gl-gray !important;
color: $gl-text-color !important;
}
}
......
......@@ -98,7 +98,7 @@
&.label-gray {
background-color: $label-gray-bg;
color: $gl-gray;
color: $gl-text-color;
text-shadow: none;
}
......
......@@ -65,11 +65,11 @@ $legend-color: $text-color;
//
//##
$pagination-color: $gl-gray;
$pagination-color: $gl-text-color;
$pagination-bg: $white-light;
$pagination-border: $border-color;
$pagination-hover-color: $gl-gray;
$pagination-hover-color: $gl-text-color;
$pagination-hover-bg: $row-hover;
$pagination-hover-border: $border-color;
......@@ -121,6 +121,9 @@ $panel-default-heading-bg: $gray-light;
$panel-footer-bg: $gray-light;
$panel-inner-border: $border-color;
$badge-bg: $badge-bg;
$badge-color: $badge-color;
//== Wells
//
//##
......@@ -154,7 +157,7 @@ $nav-link-padding: 13px $gl-padding;
//
//##
$pre-bg: $gray-light !default;
$pre-color: $gl-gray !default;
$pre-color: $gl-text-color !default;
$pre-border-color: $border-color;
$table-bg-accent: $gray-light;
@mixin md-typography {
color: $md-text-color;
color: $gl-text-color;
word-wrap: break-word;
a {
......@@ -50,14 +50,14 @@
margin: 16px 0 10px;
padding: 0 0 0.3em;
border-bottom: 1px solid $white-dark;
color: $gl-gray-dark;
color: $gl-text-color;
}
h2 {
font-size: 1.5em;
font-weight: 600;
margin: 16px 0 10px;
color: $gl-gray-dark;
color: $gl-text-color;
}
h3 {
......@@ -100,7 +100,7 @@
}
p {
color: $gl-text-color-dark;
color: $gl-text-color;
margin: 6px 0 0;
}
......@@ -108,7 +108,7 @@
@extend .table;
@extend .table-bordered;
margin: 12px 0;
color: $gl-text-color-dark;
color: $gl-text-color;
th {
background: $label-gray-bg;
......@@ -230,7 +230,7 @@ h3,
h4,
h5,
h6 {
color: $gl-title-color;
color: $gl-text-color;
font-weight: 600;
}
......@@ -292,7 +292,7 @@ h2,
h3,
h4 {
small {
color: $gl-gray;
color: $gl-text-color;
}
}
......
......@@ -96,29 +96,22 @@ $well-light-text-color: #5b6169;
* Text
*/
$gl-font-size: 14px;
$gl-title-color: #333;
$gl-text-color: #5c5c5c;
$gl-text-color-dark: #5c5d5e;
$gl-text-color-light: #8c8c8c;
$gl-text-color: rgba(0, 0, 0, .85);
$gl-text-color-secondary: rgba(0, 0, 0, .55);
$gl-text-color-disabled: rgba(0, 0, 0, .35);
$gl-text-green: #4a2;
$gl-text-red: #d12f19;
$gl-text-orange: #d90;
$gl-link-color: #3777b0;
$gl-diff-text-color: #555;
$gl-dark-link-color: #333;
$gl-gray-light: #8f8f8f;
$gl-grayish-blue: #7f8fa4;
$gl-gray: $gl-text-color;
$gl-gray-dark: #313236;
$gl-header-color: #4c4e54;
/*
* Lists
*/
$list-font-size: $gl-font-size;
$list-title-color: $gl-title-color;
$list-title-color: $gl-text-color;
$list-text-color: $gl-text-color;
$list-text-disabled-color: #888;
$list-text-disabled-color: $gl-text-color-disabled;
$list-border-light: #eee;
$list-border: rgba(0, 0, 0, 0.05);
$list-text-height: 42px;
......@@ -129,7 +122,6 @@ $list-warning-row-color: #8a6d3b;
/*
* Markdown
*/
$md-text-color: $gl-text-color;
$md-link-color: $gl-link-color;
$md-area-border: #ddd;
......@@ -170,9 +162,7 @@ $btn-side-margin: 10px;
$btn-sm-side-margin: 7px;
$btn-xs-side-margin: 5px;
$issue-status-expired: #cea61b;
$issuable-sidebar-color: #999;
$issuable-avatar-hover-border: #999;
$issuable-clipboard-color: #999;
$issuable-sidebar-color: $gl-text-color-secondary;
$show-aside-bg: #eee;
$show-aside-color: #777;
$show-aside-shadow: #ddd;
......@@ -289,10 +279,8 @@ $btn-white-active: #848484;
/*
* Badges
*/
$badge-bg: #f3f3f3;
$badge-bg-dark: #eee;
$badge-color: #929292;
$badge-color-dark: #8f8f8f;
$badge-bg: #eee;
$badge-color: $gl-text-color-secondary;
/*
* Award emoji
......@@ -311,8 +299,8 @@ $location-icon-color: #e7e9ed;
/*
* Notes
*/
$notes-light-color: #8e8e8e;
$notes-role-color: #8e8e8e;
$notes-light-color: $gl-text-color-secondary;
$notes-role-color: $gl-text-color-secondary;
$note-disabled-comment-color: #b2b2b2;
$note-targe3-outside: #fffff0;
$note-targe3-inside: #ffffd3;
......@@ -337,7 +325,7 @@ $calendar-user-contrib-text: #959494;
$cycle-analytics-box-padding: 30px;
$cycle-analytics-box-text-color: #8c8c8c;
$cycle-analytics-big-font: 19px;
$cycle-analytics-dark-text: $gl-title-color;
$cycle-analytics-dark-text: $gl-text-color;
$cycle-analytics-light-gray: #bfbfbf;
$cycle-analytics-dismiss-icon-color: #b2b2b2;
......@@ -383,14 +371,13 @@ $callout-success-color: #3c763d;
/*
* Commit Page
*/
$commit-committer-color: #999;
$commit-max-width-marker-color: rgba(0, 0, 0, 0.0);
$commit-message-text-area-bg: rgba(0, 0, 0, 0.0);
/*
* Common
*/
$common-gray: $gl-gray;
$common-gray: $gl-text-color;
$common-gray-light: #bbb;
$common-gray-dark: #444;
$common-red: $gl-text-red;
......@@ -545,3 +532,4 @@ Pipeline Graph
*/
$stage-hover-bg: #eaf3fc;
$stage-hover-border: #d1e7fc;
$action-icon-color: #d6d6d6;
.info-well {
background: $gray-light;
color: $gl-gray;
color: $gl-text-color;
border: 1px solid $border-color;
border-radius: $border-radius-default;
......
......@@ -40,7 +40,7 @@
}
.zen-control-full {
color: $gl-gray-light;
color: $gl-text-color-secondary;
&:hover {
color: $gl-link-color;
......
......@@ -3,7 +3,7 @@
/*
* White Syntax Colors
*/
$white-code-color: #333;
$white-code-color: $gl-text-color;
$white-highlight: #fafe3d;
$white-pre-hll-bg: #f8eec7;
$white-hll-bg: #f8f8f8;
......
......@@ -18,15 +18,3 @@ p.details {
pre.commit-message {
white-space: pre-wrap;
}
.file-stats > a {
text-decoration: none;
> .new-file {
color: $notify-new-file;
}
> .deleted-file {
color: $notify-deleted-file;
}
}
......@@ -73,6 +73,7 @@
height: 409px; // Needed for PhantomJS
height: calc(100vh - 290px);
min-height: 409px;
transition: width .2s;
&.is-compact {
width: calc(100% - 290px);
......@@ -258,7 +259,7 @@
.board-list-count {
padding: 10px 0;
color: $gl-gray-light;
color: $gl-text-color-secondary;
font-size: 13px;
> .fa {
......@@ -372,3 +373,18 @@
}
}
}
.right-sidebar.right-sidebar-expanded {
&.boards-sidebar-slide-enter-active,
&.boards-sidebar-slide-leave-active {
transition: width .2s,
padding .2s;
}
&.boards-sidebar-slide-enter,
&.boards-sidebar-slide-leave-active {
width: 0;
padding-left: 0;
padding-right: 0;
}
}
.divergence-graph {
padding: 12px 12px 0 0;
float: right;
.graph-side {
position: relative;
width: 80px;
height: 22px;
padding: 5px 0 13px;
float: left;
.bar {
position: absolute;
height: 4px;
background-color: $divergence-graph-bar-bg;
}
.bar-behind {
right: 0;
border-radius: 3px 0 0 3px;
}
.bar-ahead {
left: 0;
border-radius: 0 3px 3px 0;
}
.count {
padding-top: 6px;
padding-bottom: 0;
font-size: 12px;
color: $gl-text-color;
display: block;
}
.count-behind {
padding-right: 4px;
text-align: right;
}
.count-ahead {
padding-left: 4px;
text-align: left;
}
}
.graph-separator {
position: relative;
width: 1px;
height: 18px;
margin: 5px 0 0;
float: left;
background-color: $divergence-graph-separator-bg;
}
}
......@@ -160,7 +160,7 @@
flex: 1;
a {
color: $gl-gray;
color: $gl-text-color;
&:hover {
color: $gl-link-color;
......@@ -357,7 +357,7 @@
}
.build-light-text {
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
.build-gutter-toggle {
......
......@@ -18,7 +18,7 @@
}
td {
color: $gl-gray;
color: $gl-text-color;
vertical-align: middle !important;
a {
......
.commit-title {
display: block;
}
.commit-author,
.commit-committer {
display: block;
color: $commit-committer-color;
font-weight: normal;
font-style: italic;
}
.commit-author strong,
.commit-committer strong {
font-weight: bold;
font-style: normal;
}
.commit-description {
background: none;
border: none;
margin: 0;
padding: 0;
margin-top: 10px;
word-break: normal;
white-space: pre-wrap;
}
.js-details-expand {
&:hover {
text-decoration: none;
}
}
.ci-status-link {
svg {
overflow: visible;
}
}
.commit-box {
border-top: 1px solid $border-color;
padding: $gl-padding 0;
.commit-title {
margin: 0;
font-size: 23px;
color: $gl-gray-dark;
}
.commit-description {
margin-top: 15px;
}
}
.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;
}
}
.file-stats {
ul {
list-style: none;
margin: 0;
padding: 10px 0;
li {
padding: 3px 0;
line-height: 20px;
}
}
.new-file {
a {
color: $gl-text-green;
}
}
.renamed-file {
a {
color: $gl-text-orange;
}
}
.deleted-file {
a {
color: $gl-text-red;
}
}
.edit-file {
a {
color: $gl-text-color;
}
}
}
/*
* Commit message textarea for web editor and
* custom merge request message
*/
.commit-message-container {
background-color: $body-bg;
position: relative;
font-family: $monospace_font;
$left: 12px;
overflow: hidden; // See https://gitlab.com/gitlab-org/gitlab-ce/issues/13987
.max-width-marker {
width: 72ch;
color: $commit-max-width-marker-color;
font-family: inherit;
left: $left;
height: 100%;
border-right: 1px solid mix($input-border, $white-light);
position: absolute;
z-index: 1;
}
> textarea {
background-color: $commit-message-text-area-bg;
font-family: inherit;
padding-left: $left;
position: relative;
z-index: 2;
}
}
.commit-description {
background: none;
border: none;
padding: 0;
margin-top: 10px;
word-break: normal;
white-space: pre-wrap;
}
.js-details-expand {
&:hover {
text-decoration: none;
}
}
.commit-box {
border-top: 1px solid $border-color;
padding: $gl-padding 0;
.commit-title {
margin: 0;
color: $gl-text-color;
}
.commit-description {
margin-top: 15px;
}
}
.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 message textarea for web editor and
* custom merge request message
*/
.commit-message-container {
background-color: $body-bg;
position: relative;
font-family: $monospace_font;
$left: 12px;
overflow: hidden; // See https://gitlab.com/gitlab-org/gitlab-ce/issues/13987
.max-width-marker {
width: 72ch;
color: $commit-max-width-marker-color;
font-family: inherit;
left: $left;
height: 100%;
border-right: 1px solid mix($input-border, $white-light);
position: absolute;
z-index: 1;
}
textarea {
background-color: $commit-message-text-area-bg;
font-family: inherit;
padding-left: $left;
position: relative;
z-index: 2;
}
}
.commits-compare-switch {
@include btn-default;
@include btn-white;
float: left;
margin-right: 9px;
}
......@@ -8,7 +77,6 @@
.commit-header {
padding: 5px 10px;
background-color: $gray-light;
border-top: 1px solid $gray-darker;
border-bottom: 1px solid $gray-darker;
font-size: 14px;
......@@ -18,8 +86,6 @@
}
.commit-row-title {
line-height: 1.35;
.notes_count {
float: right;
margin-right: 10px;
......@@ -30,15 +96,14 @@
}
.commit-row-message {
color: $gl-dark-link-color;
color: $gl-text-color;
}
}
.text-expander {
display: inline-block;
background: $gray-light;
color: $gl-gray-light;
color: $gl-text-color-secondary;
padding: 0 5px;
cursor: pointer;
border: 1px solid $border-gray-dark;
......@@ -54,9 +119,8 @@
.commit-actions {
@media (min-width: $screen-sm-min) {
float: right;
margin-left: $gl-padding;
margin-top: 2px;
width: 300px;
text-align: right;
font-size: 0;
}
......@@ -86,35 +150,13 @@
.commit,
.generic_commit_status {
padding: 10px 0;
position: relative;
@media (min-width: $screen-sm-min) {
padding-left: 46px;
}
&:not(:last-child) {
border-bottom: 1px solid $gray-darker;
}
a,
button {
color: $gl-dark-link-color;
color: $gl-text-color;
vertical-align: baseline;
}
.avatar {
margin-left: -46px;
}
.item-title {
display: inline-block;
@media (min-width: $screen-sm-min) {
max-width: 70%;
}
}
.commit-row-description {
font-size: 14px;
border-left: 1px solid $white-normal;
......@@ -134,20 +176,7 @@
}
a {
color: $gl-dark-link-color;
}
}
.commit-row-info {
color: $gl-gray;
line-height: 1.35;
a {
color: $gl-gray;
}
.avatar {
margin-right: 8px;
color: $gl-text-color;
}
}
......@@ -164,7 +193,7 @@
}
.branch-commit {
color: $gl-gray;
color: $gl-text-color;
.commit-icon {
text-align: center;
......@@ -174,7 +203,7 @@
height: 14px;
width: 14px;
vertical-align: middle;
fill: $gl-gray-light;
fill: $gl-text-color-secondary;
}
}
......@@ -183,62 +212,6 @@
}
.commit-row-message {
color: $gl-gray;
}
}
.divergence-graph {
padding: 12px 12px 0 0;
float: right;
.graph-side {
position: relative;
width: 80px;
height: 22px;
padding: 5px 0 13px;
float: left;
.bar {
position: absolute;
height: 4px;
background-color: $divergence-graph-bar-bg;
}
.bar-behind {
right: 0;
border-radius: 3px 0 0 3px;
}
.bar-ahead {
left: 0;
border-radius: 0 3px 3px 0;
}
.count {
padding-top: 6px;
padding-bottom: 0;
font-size: 12px;
color: $gl-title-color;
display: block;
}
.count-behind {
padding-right: 4px;
text-align: right;
}
.count-ahead {
padding-left: 4px;
text-align: left;
}
}
.graph-separator {
position: relative;
width: 1px;
height: 18px;
margin: 5px 0 0;
float: left;
background-color: $divergence-graph-separator-bg;
color: $gl-text-color;
}
}
......@@ -111,14 +111,14 @@
line-height: 19px;
font-size: 14px;
font-weight: 600;
color: $gl-title-color;
color: $gl-text-color;
}
&.text {
color: $layout-link-gray;
&.value-col {
color: $gl-title-color;
color: $gl-text-color;
}
}
}
......@@ -260,7 +260,7 @@
.stage-empty,
.not-available {
color: $gl-text-color-light;
color: $gl-text-color-secondary;
}
}
}
......@@ -327,7 +327,7 @@
@include text-overflow();
a {
color: $gl-dark-link-color;
color: $gl-text-color;
}
}
}
......@@ -355,7 +355,7 @@
.issue-link,
.commit-author-link,
.issue-author-link {
color: $gl-dark-link-color;
color: $gl-text-color;
}
// Custom CSS for components
......@@ -396,11 +396,11 @@
}
.item-build-name {
color: $gl-title-color;
color: $gl-text-color;
}
.pipeline-id {
color: $gl-title-color;
color: $gl-text-color;
padding: 0 3px 0 0;
}
......@@ -423,7 +423,7 @@
}
.fa {
color: $gl-text-color-light;
color: $gl-text-color-secondary;
font-size: $code_font_size;
}
}
......@@ -435,7 +435,7 @@
width: 75%;
margin: 0 auto;
padding-top: 130px;
color: $gl-text-color-light;
color: $gl-text-color-secondary;
h4 {
color: $gl-text-color;
......
.detail-page-header {
padding: $gl-padding-top 0;
border-bottom: 1px solid $border-color;
color: $gl-text-color-dark;
color: $gl-text-color;
line-height: 34px;
.author {
color: $gl-text-color-dark;
color: $gl-text-color;
}
.identifier {
color: $gl-text-color-dark;
color: $gl-text-color;
}
.issue_created_ago,
......@@ -22,7 +22,7 @@
.title {
margin: 0 0 16px;
font-size: 2em;
color: $gl-gray-dark;
color: $gl-text-color;
padding: 0 0 0.3em;
border-bottom: 1px solid $white-dark;
}
......
......@@ -14,7 +14,7 @@
background: $gray-light;
border-bottom: 1px solid $border-color;
padding: 10px 16px;
color: $gl-diff-text-color;
color: $gl-text-color;
z-index: 10;
border-radius: 3px 3px 0 0;
......@@ -50,7 +50,7 @@
overflow: auto;
overflow-y: hidden;
background: $white-light;
color: $gl-title-color;
color: $gl-text-color;
border-radius: 0 0 3px 3px;
.unfold {
......@@ -380,7 +380,7 @@
}
cursor: default;
color: $gl-title-color;
color: $gl-text-color;
}
&.disabled {
......
......@@ -72,25 +72,25 @@
.external-url,
.dropdown-new {
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
.dropdown-menu {
.fa {
margin-right: 6px;
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
}
.build-link,
.branch-name {
color: $gl-dark-link-color;
color: $gl-text-color;
}
.stop-env-link,
.external-url {
color: $gl-gray-light;
color: $gl-text-color-secondary;
.stop-env-icon {
font-size: 14px;
......@@ -101,7 +101,7 @@
.build-column {
.build-link {
color: $gl-dark-link-color;
color: $gl-text-color;
}
.avatar {
......
......@@ -21,7 +21,7 @@
}
a {
color: $gl-dark-link-color;
color: $gl-text-color;
}
.avatar {
......
......@@ -18,7 +18,7 @@
.stats {
float: right;
line-height: $list-text-height;
color: $gl-gray;
color: $gl-text-color;
span {
margin-right: 15px;
......
......@@ -5,6 +5,12 @@
}
}
.title {
padding: 0;
margin: 0;
border-bottom: none;
}
// Border around images in issue and MR descriptions.
.description img:not(.emoji) {
border: 1px solid $white-normal;
......@@ -97,7 +103,7 @@
}
.edit-link {
color: $gl-gray;
color: $gl-text-color;
&:hover {
color: $md-link-color;
......@@ -133,7 +139,7 @@
}
.btn-clipboard:hover {
color: $gl-gray;
color: $gl-text-color;
}
}
......@@ -168,7 +174,7 @@
}
.no-value {
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
.sidebar-collapsed-icon {
......@@ -236,7 +242,7 @@
color: $issuable-sidebar-color;
&:hover {
color: $gl-gray;
color: $gl-text-color;
}
span {
......@@ -249,16 +255,16 @@
}
.avatar:hover {
border-color: $issuable-avatar-hover-border;
border-color: $issuable-sidebar-color;
}
.btn-clipboard {
border: none;
color: $issuable-clipboard-color;
color: $issuable-sidebar-color;
&:hover {
background: transparent;
color: $gl-gray;
color: $gl-text-color;
}
}
}
......@@ -332,7 +338,7 @@
margin-left: 5px;
a {
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
}
......@@ -433,7 +439,7 @@
}
&:hover svg {
fill: $gl-gray;
fill: $gl-text-color;
}
}
......@@ -480,10 +486,10 @@
.compare-display {
font-size: 13px;
color: $gl-gray-light;
color: $gl-text-color-secondary;
.compare-value {
color: $gl-gray;
color: $gl-text-color;
}
}
}
......
......@@ -117,7 +117,7 @@
.manage-labels-list {
.btn-action {
color: $gl-dark-link-color;
color: $gl-text-color;
.fa {
font-size: 18px;
......
......@@ -17,14 +17,19 @@
line-height: 1.5;
p {
font-size: 18px;
font-size: 16px;
color: $login-brand-holder-color;
}
h1:first-child {
font-weight: normal;
margin-bottom: 30px;
margin-bottom: 0.68em;
margin-top: 0;
font-size: 34px;
}
h3 {
font-size: 22px;
}
img {
......
......@@ -31,7 +31,7 @@
}
.form-horizontal {
margin-top: 5px;
margin-top: 20px;
@media (min-width: $screen-sm-min) {
display: -webkit-flex;
......@@ -104,6 +104,10 @@
padding-right: 35px;
@media (min-width: $screen-sm-min) {
width: 250px;
}
@media (min-width: $screen-md-min) {
width: 350px;
}
......
......@@ -4,7 +4,7 @@
*/
.mr-state-widget {
background: $gray-light;
color: $gl-gray;
color: $gl-text-color;
border: 1px solid $border-color;
border-radius: 2px;
......@@ -58,7 +58,7 @@
padding-right: 0;
a {
color: $gl-gray;
color: $gl-text-color;
}
}
......@@ -70,7 +70,7 @@
.ci_widget {
border-bottom: 1px solid $well-inner-border;
color: $gl-gray;
color: $gl-text-color;
svg {
margin-right: 4px;
......@@ -94,7 +94,7 @@
}
.normal {
color: $gl-text-color-dark;
color: $gl-text-color;
}
.js-deployment-link {
......@@ -106,7 +106,7 @@
font-weight: 600;
font-size: 16px;
margin: 5px 0;
color: $gl-gray-dark;
color: $gl-text-color;
&.has-conflicts .fa-exclamation-triangle {
color: $gl-warning;
......@@ -190,7 +190,7 @@
}
.label-branch {
color: $gl-gray-dark;
color: $gl-text-color;
font-family: $monospace_font;
font-weight: bold;
overflow: hidden;
......@@ -310,10 +310,6 @@
left: 0;
top: 2px;
}
.commit-row-info {
line-height: 20px;
}
}
.btn-clipboard {
......@@ -367,7 +363,7 @@
th {
background-color: $white-light;
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
}
}
......@@ -433,6 +429,10 @@
left: 0;
z-index: 10;
transition: right .15s;
@media (max-width: $screen-xs-max) {
right: 0;
}
}
&:not(.affix) .container-fluid {
......
......@@ -102,7 +102,7 @@
margin-top: 7px;
.issuable-number {
color: $gl-gray-light;
color: $gl-text-color-secondary;
margin-right: 5px;
}
......
......@@ -27,6 +27,7 @@
.new-note,
.note-edit-form {
.note-form-actions {
position: relative;
margin-top: $gl-padding;
}
......@@ -44,7 +45,7 @@
.note-textarea {
display: block;
padding: 10px 0;
color: $gl-gray;
color: $gl-text-color;
font-family: $regular_font;
border: 0;
......@@ -204,7 +205,7 @@
.comment-toolbar {
padding-top: $gl-padding-top;
color: $gl-gray-light;
color: $gl-text-color-secondary;
border-top: 1px solid $border-color;
}
......@@ -265,3 +266,18 @@
}
}
}
.note-edit-warning.settings-message {
display: none;
padding: 5px 10px;
position: absolute;
left: 127px;
top: 2px;
@media (max-width: $screen-xs-max) {
position: relative;
top: 0;
left: 0;
margin-bottom: 10px;
}
}
......@@ -43,7 +43,7 @@ ul.notes {
}
.system-note-message {
display: inline-block;
display: inline;
&::first-letter {
text-transform: lowercase;
......@@ -55,7 +55,7 @@ ul.notes {
}
p {
display: inline-block;
display: inline;
margin: 0;
&::first-letter {
......@@ -345,7 +345,7 @@ ul.notes {
}
.author_link {
color: $gl-gray;
color: $gl-text-color;
}
}
......@@ -353,6 +353,14 @@ ul.notes {
font-size: 14px;
}
.note-headline-light {
display: inline;
@media (max-width: $screen-xs-min) {
display: block;
}
}
.note-headline-light,
.discussion-headline-light {
color: $notes-light-color;
......@@ -580,13 +588,11 @@ ul.notes {
// Merge request notes in diffs
.diff-file {
// Diff is side by side
.notes_content.parallel .note-header .note-headline-light {
display: block;
position: relative;
}
// Diff is inline
.notes_content .note-header .note-headline-light {
display: inline-block;
......
This diff is collapsed.
......@@ -26,7 +26,7 @@
margin-bottom: 5px;
}
&> .form-group {
& > .form-group {
padding-left: 0;
}
}
......@@ -73,7 +73,7 @@
border: 1px solid $border-color;
}
&+ .select2 a {
& + .select2 a {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
......@@ -292,7 +292,7 @@
.option-title {
font-weight: normal;
display: inline-block;
color: $gl-gray-dark;
color: $gl-text-color;
}
.option-descr {
......@@ -331,7 +331,7 @@
a.deploy-project-label {
padding: 5px;
margin-right: 5px;
color: $gl-gray;
color: $gl-text-color;
background-color: $row-hover;
&:hover {
......@@ -372,7 +372,7 @@ a.deploy-project-label {
}
a {
color: $gl-dark-link-color;
color: $gl-text-color;
}
.dropdown-menu {
......@@ -426,7 +426,7 @@ a.deploy-project-label {
width: 100%;
height: 100%;
padding-top: $gl-padding;
color: $gl-gray;
color: $gl-text-color;
.caption {
min-height: 30px;
......@@ -552,7 +552,7 @@ pre.light-well {
margin: 0 7px 7px;
h5 {
color: $gl-text-color-dark;
color: $gl-text-color;
}
.light-well {
......@@ -618,7 +618,6 @@ pre.light-well {
margin: 0;
}
.activity-filter-block {
.controls {
padding-bottom: 7px;
......@@ -627,6 +626,12 @@ pre.light-well {
}
}
.commits-search-form {
.input-short {
min-width: 200px;
}
}
.project-last-commit {
@media (min-width: $screen-sm-min) {
margin-top: $gl-padding;
......@@ -657,7 +662,7 @@ pre.light-well {
}
.commit-row-message {
color: $gl-gray;
color: $gl-text-color;
}
.commit_short_id {
......@@ -758,7 +763,7 @@ a.allowed-to-push {
.protected-branches-list {
a {
color: $gl-gray;
color: $gl-text-color;
&:hover {
color: $gl-link-color;
......@@ -838,7 +843,31 @@ a.allowed-to-push {
.compare-form-group {
.dropdown-menu {
width: 300px;
width: 100%;
@media (min-width: $screen-sm-min) {
width: 300px;
}
}
+ .compare-ellipsis {
width: 100%;
vertical-align: middle;
text-align: center;
margin-top: -20px;
@media (min-width: $screen-sm-min) {
margin-top: 0;
width: auto;
}
}
.inline-input-group {
width: 100%;
@media (min-width: $screen-sm-min) {
width: 250px;
}
}
}
......
.settings-list-icon {
color: $gl-gray-light;
color: $gl-text-color-secondary;
font-size: $settings-icon-size;
line-height: 42px;
}
......
......@@ -61,15 +61,15 @@
&.ci-canceled,
&.ci-disabled {
color: $gl-gray;
border-color: $gl-gray;
color: $gl-text-color;
border-color: $gl-text-color;
&:not(span):hover {
background-color: rgba($gl-gray, .07);
background-color: rgba($gl-text-color, .07);
}
svg {
fill: $gl-gray;
fill: $gl-text-color;
}
}
......@@ -101,15 +101,15 @@
&.ci-created,
&.ci-skipped {
color: $gl-gray-light;
border-color: $gl-gray-light;
color: $gl-text-color-secondary;
border-color: $gl-text-color-secondary;
&:not(span):hover {
background-color: rgba($gl-gray-light, .07);
background-color: rgba($gl-text-color-secondary, .07);
}
svg {
fill: $gl-gray-light;
fill: $gl-text-color-secondary;
}
}
......@@ -135,3 +135,9 @@
left: 5px;
}
}
.ci-status-link {
svg {
overflow: visible;
}
}
......@@ -90,7 +90,7 @@
}
p {
color: $gl-text-color-dark;
color: $gl-text-color;
}
}
......
......@@ -78,7 +78,7 @@
i,
a {
color: $gl-dark-link-color;
color: $gl-text-color;
}
img {
......@@ -104,21 +104,21 @@
padding-right: 8px;
.commit-author-name {
color: $gl-gray;
color: $gl-text-color;
}
}
.tree-time-ago {
min-width: 135px;
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
.tree-commit {
max-width: 320px;
color: $gl-gray-light;
color: $gl-text-color-secondary;
.tree-commit-link {
color: $gl-gray-light;
color: $gl-text-color-secondary;
&:hover {
text-decoration: underline;
......@@ -134,21 +134,18 @@
.blob-commit-info {
list-style: none;
padding: $gl-padding;
background: $gray-light;
padding: 6px 0;
border: 1px solid $border-color;
border-bottom: none;
margin: 0;
.commit {
padding-top: 0;
padding-bottom: 0;
.table-list-cell {
border-bottom: none;
}
.commit-row-title {
.commit-row-message {
font-weight: normal;
}
}
.commit-actions {
width: 200px;
}
}
......
......@@ -15,7 +15,7 @@
}
.wiki-last-edit-by {
color: $gl-gray-light;
color: $gl-text-color-secondary;
strong {
color: $gl-text-color;
......@@ -24,7 +24,7 @@
.light {
font-weight: normal;
color: $gl-gray-light;
color: $gl-text-color-secondary;
}
.git-access-header {
......
......@@ -16,9 +16,6 @@ class Admin::UsersController < Admin::ApplicationController
@joined_projects = user.projects.joined(@user)
end
def groups
end
def keys
@keys = user.keys
end
......
......@@ -82,7 +82,7 @@ module CreatesCommit
return @merge_request if defined?(@merge_request)
@merge_request = MergeRequestsFinder.new(current_user, project_id: @mr_target_project.id).execute.opened.
find_by(source_branch: @mr_source_branch, target_branch: @mr_target_branch)
find_by(source_branch: @mr_source_branch, target_branch: @mr_target_branch, source_project_id: @mr_source_project)
end
def different_project?
......
module GlobalMilestones
extend ActiveSupport::Concern
def milestones
epoch = DateTime.parse('1970-01-01')
@milestones = MilestonesFinder.new.execute(@projects, params)
@milestones = GlobalMilestone.build_collection(@milestones)
@milestones = @milestones.sort_by { |x| x.due_date.nil? ? epoch : x.due_date }
end
def milestone
milestones = Milestone.of_projects(@projects).where(title: params[:title])
if milestones.present?
@milestone = GlobalMilestone.new(params[:title], milestones)
else
render_404
end
end
end
class Dashboard::MilestonesController < Dashboard::ApplicationController
include GlobalMilestones
before_action :projects
before_action :milestone, only: [:show]
......@@ -17,4 +15,15 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController
def show
end
private
def milestones
@milestones = GlobalMilestone.build_collection(@projects, params)
end
def milestone
@milestone = GlobalMilestone.build(@projects, params[:title])
render_404 unless @milestone
end
end
class Groups::MilestonesController < Groups::ApplicationController
include GlobalMilestones
before_action :group_projects
before_action :milestone, only: [:show, :update]
before_action :authorize_admin_milestones!, only: [:new, :create, :update]
......@@ -73,4 +71,13 @@ class Groups::MilestonesController < Groups::ApplicationController
def milestone_path(title)
group_milestone_path(@group, title.to_slug.to_s, title: title)
end
def milestones
@milestones = GroupMilestone.build_collection(@group, @projects, params)
end
def milestone
@milestone = GroupMilestone.build(@group, @projects, params[:title])
render_404 unless @milestone
end
end
......@@ -42,6 +42,8 @@ class GroupsController < Groups::ApplicationController
@notification_setting = current_user.notification_settings_for(group)
end
@nested_groups = group.children
setup_projects
respond_to do |format|
......
......@@ -4,10 +4,7 @@ class Projects::GroupLinksController < Projects::ApplicationController
before_action :authorize_admin_project_member!, only: [:update]
def index
@group_links = project.project_group_links.all
@skip_groups = @group_links.pluck(:group_id)
@skip_groups << project.namespace_id unless project.personal?
redirect_to namespace_project_settings_members_path
end
def create
......@@ -25,7 +22,7 @@ class Projects::GroupLinksController < Projects::ApplicationController
flash[:alert] = 'Please select a group.'
end
redirect_to namespace_project_group_links_path(project.namespace, project)
redirect_to namespace_project_settings_members_path(project.namespace, project)
end
def update
......@@ -39,7 +36,7 @@ class Projects::GroupLinksController < Projects::ApplicationController
respond_to do |format|
format.html do
redirect_to namespace_project_group_links_path(project.namespace, project)
redirect_to namespace_project_settings_members_path(project.namespace, project)
end
format.js { head :ok }
end
......
......@@ -30,7 +30,7 @@ class Projects::MattermostsController < Projects::ApplicationController
def configure_params
params.require(:mattermost).permit(:trigger, :team_id).merge(
url: service_trigger_url(@service),
icon_url: asset_url('gitlab_logo.png'))
icon_url: asset_url('slash-command-logo.png'))
end
def teams
......
......@@ -100,7 +100,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@start_version = @comparable_diffs.find { |diff| diff.head_commit_sha == @start_sha }
unless @start_version
render_404
@start_sha = @merge_request_diff.head_commit_sha
@start_version = @merge_request_diff
end
end
......
......@@ -6,54 +6,14 @@ class Projects::ProjectMembersController < Projects::ApplicationController
before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
def index
@sort = params[:sort].presence || sort_value_name
@group_links = @project.project_group_links
@project_members = @project.project_members
@project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
group = @project.group
if group
# We need `.where.not(user_id: nil)` here otherwise when a group has an
# invitee, it would make the following query return 0 rows since a NULL
# user_id would be present in the subquery
# See http://stackoverflow.com/questions/129077/not-in-clause-and-null-values
# FIXME: This whole logic should be moved to a finder!
non_null_user_ids = @project_members.where.not(user_id: nil).select(:user_id)
group_members = group.group_members.where.not(user_id: non_null_user_ids)
group_members = group_members.non_invite unless can?(current_user, :admin_group, @group)
end
if params[:search].present?
user_ids = @project.users.search(params[:search]).select(:id)
@project_members = @project_members.where(user_id: user_ids)
if group_members
user_ids = group.users.search(params[:search]).select(:id)
group_members = group_members.where(user_id: user_ids)
end
@group_links = @project.project_group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id))
end
wheres = ["members.id IN (#{@project_members.select(:id).to_sql})"]
wheres << "members.id IN (#{group_members.select(:id).to_sql})" if group_members
@project_members = Member.
where(wheres.join(' OR ')).
sort(@sort).
page(params[:page])
@requesters = AccessRequestsFinder.new(@project).execute(current_user)
@project_member = @project.project_members.new
sort = params[:sort].presence || sort_value_name
redirect_to namespace_project_settings_members_path(@project.namespace, @project, sort: sort)
end
def create
status = Members::CreateService.new(@project, current_user, params).execute
redirect_url = namespace_project_project_members_path(@project.namespace, @project)
redirect_url = namespace_project_settings_members_path(@project.namespace, @project)
if status
members = @project.project_members.where(user_id: params[:user_ids].split(','))
......@@ -88,14 +48,14 @@ class Projects::ProjectMembersController < Projects::ApplicationController
respond_to do |format|
format.html do
redirect_to namespace_project_project_members_path(@project.namespace, @project)
redirect_to namespace_project_settings_members_path(@project.namespace, @project)
end
format.js { head :ok }
end
end
def resend_invite
redirect_path = namespace_project_project_members_path(@project.namespace, @project)
redirect_path = namespace_project_settings_members_path(@project.namespace, @project)
@project_member = @project.project_members.find(params[:id])
......@@ -118,7 +78,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
return render_404
end
redirect_to(namespace_project_project_members_path(project.namespace, project),
redirect_to(namespace_project_settings_members_path(project.namespace, project),
notice: notice)
end
......
module Projects
module Settings
class MembersController < Projects::ApplicationController
include SortingHelper
def show
@sort = params[:sort].presence || sort_value_name
@group_links = @project.project_group_links
@project_members = @project.project_members
@project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
group = @project.group
# group links
@group_links = @project.project_group_links.all
@skip_groups = @group_links.pluck(:group_id)
@skip_groups << @project.namespace_id unless @project.personal?
if group
# We need `.where.not(user_id: nil)` here otherwise when a group has an
# invitee, it would make the following query return 0 rows since a NULL
# user_id would be present in the subquery
# See http://stackoverflow.com/questions/129077/not-in-clause-and-null-values
group_members = MembersFinder.new(@project_members, group).execute(current_user)
end
if params[:search].present?
user_ids = @project.users.search(params[:search]).select(:id)
@project_members = @project_members.where(user_id: user_ids)
if group_members
user_ids = group.users.search(params[:search]).select(:id)
group_members = group_members.where(user_id: user_ids)
end
@group_links = @project.project_group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id))
end
wheres = ["members.id IN (#{@project_members.select(:id).to_sql})"]
wheres << "members.id IN (#{group_members.select(:id).to_sql})" if group_members
@project_members = Member.
where(wheres.join(' OR ')).
sort(@sort).
page(params[:page])
@requesters = AccessRequestsFinder.new(@project).execute(current_user)
@project_member = @project.project_members.new
end
end
end
end
......@@ -7,17 +7,17 @@ class RegistrationsController < Devise::RegistrationsController
end
def create
if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
# To avoid duplicate form fields on the login page, the registration form
# names fields using `new_user`, but Devise still wants the params in
# `user`.
if params["new_#{resource_name}"].present? && params[resource_name].blank?
params[resource_name] = params.delete(:"new_#{resource_name}")
end
# To avoid duplicate form fields on the login page, the registration form
# names fields using `new_user`, but Devise still wants the params in
# `user`.
if params["new_#{resource_name}"].present? && params[resource_name].blank?
params[resource_name] = params.delete(:"new_#{resource_name}")
end
if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
super
else
flash[:alert] = "There was an error with the reCAPTCHA code below. Please re-enter the code."
flash[:alert] = 'There was an error with the reCAPTCHA. Please re-solve the reCAPTCHA.'
flash.delete :recaptcha_error
render action: 'new'
end
......@@ -57,7 +57,7 @@ class RegistrationsController < Devise::RegistrationsController
end
def sign_up_params
params.require(:user).permit(:username, :email, :name, :password, :password_confirmation)
params.require(:user).permit(:username, :email, :email_confirmation, :name, :password)
end
def resource_name
......
class MembersFinder < Projects::ApplicationController
def initialize(project_members, project_group)
@project_members = project_members
@project_group = project_group
end
def execute(current_user)
non_null_user_ids = @project_members.where.not(user_id: nil).select(:user_id)
group_members = @project_group.group_members.where.not(user_id: non_null_user_ids)
group_members = group_members.non_invite unless can?(current_user, :admin_group, @project_group)
group_members
end
end
......@@ -110,6 +110,28 @@ module GitlabMarkdownHelper
end
end
# Returns the text necessary to reference `entity` across projects
#
# project - Project to reference
# entity - Object that responds to `to_reference`
#
# Examples:
#
# cross_project_reference(project, project.issues.first)
# # => 'namespace1/project1#123'
#
# cross_project_reference(project, project.merge_requests.first)
# # => 'namespace1/project1!345'
#
# Returns a String
def cross_project_reference(project, entity)
if entity.respond_to?(:to_reference)
entity.to_reference(project, full: true)
else
''
end
end
private
# Return +text+, truncated to +max_chars+ characters, excluding any HTML
......@@ -158,28 +180,6 @@ module GitlabMarkdownHelper
end
end
# Returns the text necessary to reference `entity` across projects
#
# project - Project to reference
# entity - Object that responds to `to_reference`
#
# Examples:
#
# cross_project_reference(project, project.issues.first)
# # => 'namespace1/project1#123'
#
# cross_project_reference(project, project.merge_requests.first)
# # => 'namespace1/project1!345'
#
# Returns a String
def cross_project_reference(project, entity)
if entity.respond_to?(:to_reference)
entity.to_reference(project)
else
''
end
end
def markdown_toolbar_button(options = {})
data = options[:data].merge({ container: "body" })
content_tag :button,
......
......@@ -206,4 +206,9 @@ module GitlabRoutingHelper
file_namespace_project_build_artifacts_path(*args)
end
end
# Settings
def project_settings_members_path(project, *args)
namespace_project_settings_members_path(project.namespace, project, *args)
end
end
......@@ -58,13 +58,13 @@ module IssuesHelper
end
def status_box_class(item)
if item.respond_to?(:expired?) && item.expired?
if item.try(:expired?)
'status-box-expired'
elsif item.respond_to?(:merged?) && item.merged?
elsif item.try(:merged?)
'status-box-merged'
elsif item.closed?
'status-box-closed'
elsif item.respond_to?(:upcoming?) && item.upcoming?
elsif item.try(:upcoming?)
'status-box-upcoming'
else
'status-box-open'
......@@ -128,8 +128,10 @@ module IssuesHelper
names.to_sentence
end
def award_active_class(awards, current_user)
if current_user && awards.find { |a| a.user_id == current_user.id }
def award_state_class(awards, current_user)
if !current_user
"disabled"
elsif current_user && awards.find { |a| a.user_id == current_user.id }
"active"
else
""
......
......@@ -173,48 +173,27 @@ module ProjectsHelper
nav_tabs << :merge_requests
end
if can?(current_user, :read_pipeline, project)
nav_tabs << :pipelines
end
if can?(current_user, :read_build, project)
nav_tabs << :builds
end
if Gitlab.config.registry.enabled && can?(current_user, :read_container_image, project)
nav_tabs << :container_registry
end
if can?(current_user, :read_environment, project)
nav_tabs << :environments
end
if can?(current_user, :admin_project, project)
nav_tabs << :settings
end
if can?(current_user, :read_project_member, project)
nav_tabs << :team
end
if can?(current_user, :read_issue, project)
nav_tabs << :issues
end
if can?(current_user, :read_wiki, project)
nav_tabs << :wiki
end
if can?(current_user, :read_project_snippet, project)
nav_tabs << :snippets
end
if can?(current_user, :read_label, project)
nav_tabs << :labels
end
tab_ability_map = {
environments: :read_environment,
milestones: :read_milestone,
pipelines: :read_pipeline,
snippets: :read_project_snippet,
settings: :admin_project,
builds: :read_build,
labels: :read_label,
issues: :read_issue,
team: :read_project_member,
wiki: :read_wiki
}
if can?(current_user, :read_milestone, project)
nav_tabs << :milestones
tab_ability_map.each do |tab, ability|
if can?(current_user, ability, project)
nav_tabs << tab
end
end
nav_tabs.flatten
......
......@@ -47,7 +47,7 @@ module SearchHelper
# Autocomplete results for various settings pages
def default_autocomplete
[
{ category: "Settings", label: "Profile settings", url: profile_path },
{ category: "Settings", label: "User settings", url: profile_path },
{ category: "Settings", label: "SSH Keys", url: profile_keys_path },
{ category: "Settings", label: "Dashboard", url: root_path },
{ category: "Settings", label: "Admin Section", url: admin_root_path },
......@@ -83,7 +83,7 @@ module SearchHelper
{ category: "Current Project", label: "Merge Requests", url: namespace_project_merge_requests_path(@project.namespace, @project) },
{ category: "Current Project", label: "Milestones", url: namespace_project_milestones_path(@project.namespace, @project) },
{ category: "Current Project", label: "Snippets", url: namespace_project_snippets_path(@project.namespace, @project) },
{ category: "Current Project", label: "Members", url: namespace_project_project_members_path(@project.namespace, @project) },
{ category: "Current Project", label: "Members", url: namespace_project_settings_members_path(@project.namespace, @project) },
{ category: "Current Project", label: "Wiki", url: namespace_project_wikis_path(@project.namespace, @project) },
]
else
......
......@@ -91,8 +91,8 @@ class Commit
@link_reference_pattern ||= super("commit", /(?<commit>\h{7,40})/)
end
def to_reference(from_project = nil)
commit_reference(from_project, id)
def to_reference(from_project = nil, full: false)
commit_reference(from_project, id, full: full)
end
def reference_link_text(from_project = nil)
......@@ -320,8 +320,8 @@ class Commit
private
def commit_reference(from_project, referable_commit_id)
reference = project.to_reference(from_project)
def commit_reference(from_project, referable_commit_id, full: false)
reference = project.to_reference(from_project, full: full)
if reference.present?
"#{reference}#{self.class.reference_prefix}#{referable_commit_id}"
......
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.
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.
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.
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