Commit 86dcb79b authored by Sean McGivern's avatar Sean McGivern

Merge branch 'master' into merge-conflicts-editor-2

parents 26e327ea 052de060
CHANGELOG merge=union CHANGELOG.md merge=union
*.js.es6 gitlab-language=javascript *.js.es6 gitlab-language=javascript
...@@ -99,7 +99,7 @@ update-knapsack: ...@@ -99,7 +99,7 @@ update-knapsack:
- export KNAPSACK_REPORT_PATH=knapsack/spinach_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json - export KNAPSACK_REPORT_PATH=knapsack/spinach_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export KNAPSACK_GENERATE_REPORT=true - export KNAPSACK_GENERATE_REPORT=true
- cp knapsack/spinach_report.json ${KNAPSACK_REPORT_PATH} - cp knapsack/spinach_report.json ${KNAPSACK_REPORT_PATH}
- knapsack spinach "-r rerun" || retry '[ ! -e tmp/spinach-rerun.txt ] || bundle exec spinach -r rerun $(cat tmp/spinach-rerun.txt)' - knapsack spinach "-r rerun" || retry '[[ -e tmp/spinach-rerun.txt ]] && bundle exec spinach -r rerun $(cat tmp/spinach-rerun.txt)'
artifacts: artifacts:
expire_in: 31d expire_in: 31d
paths: paths:
...@@ -309,6 +309,9 @@ coverage: ...@@ -309,6 +309,9 @@ coverage:
# Trigger docs build # Trigger docs build
trigger_docs: trigger_docs:
stage: post-test stage: post-test
before_script: []
cache: {}
artifacts: {}
script: script:
- "curl -X POST -F token=${DOCS_TRIGGER_TOKEN} -F ref=master https://gitlab.com/api/v3/projects/38069/trigger/builds" - "curl -X POST -F token=${DOCS_TRIGGER_TOKEN} -F ref=master https://gitlab.com/api/v3/projects/38069/trigger/builds"
only: only:
......
See the general Documentation guidelines http://docs.gitlab.com/ce/development/doc_styleguide.html. See the general Documentation guidelines http://docs.gitlab.com/ce/development/doc_styleguide.html
## What does this MR do? ## What does this MR do?
......
...@@ -61,7 +61,7 @@ linters: ...@@ -61,7 +61,7 @@ linters:
# Separate rule, function, and mixin declarations with empty lines. # Separate rule, function, and mixin declarations with empty lines.
EmptyLineBetweenBlocks: EmptyLineBetweenBlocks:
enabled: false enabled: true
# Reports when you have an empty rule set. # Reports when you have an empty rule set.
EmptyRule: EmptyRule:
...@@ -219,7 +219,7 @@ linters: ...@@ -219,7 +219,7 @@ linters:
# Property values, @extend, @include, and @import directives, and variable # Property values, @extend, @include, and @import directives, and variable
# declarations should always end with a semicolon. # declarations should always end with a semicolon.
TrailingSemicolon: TrailingSemicolon:
enabled: false enabled: true
# Reports lines containing trailing whitespace. # Reports lines containing trailing whitespace.
TrailingWhitespace: TrailingWhitespace:
......
This diff is collapsed.
...@@ -247,7 +247,7 @@ request is as follows: ...@@ -247,7 +247,7 @@ request is as follows:
1. Fork the project into your personal space on GitLab.com 1. Fork the project into your personal space on GitLab.com
1. Create a feature branch, branch away from `master` 1. Create a feature branch, branch away from `master`
1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code 1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code
1. Add your changes to the [CHANGELOG](CHANGELOG): 1. Add your changes to the [CHANGELOG.md](CHANGELOG.md):
1. If you are fixing a ~regression issue, you can add your entry to the next 1. If you are fixing a ~regression issue, you can add your entry to the next
patch release (e.g. `8.12.5` if current version is `8.12.4`) patch release (e.g. `8.12.5` if current version is `8.12.4`)
1. Otherwise, add your entry to the next minor release (e.g. `8.13.0` if 1. Otherwise, add your entry to the next minor release (e.g. `8.13.0` if
......
...@@ -15,18 +15,17 @@ ...@@ -15,18 +15,17 @@
this.hideSidebar = bind(this.hideSidebar, this); this.hideSidebar = bind(this.hideSidebar, this);
this.toggleSidebar = bind(this.toggleSidebar, this); this.toggleSidebar = bind(this.toggleSidebar, this);
this.updateDropdown = bind(this.updateDropdown, this); this.updateDropdown = bind(this.updateDropdown, this);
this.$document = $(document);
clearInterval(Build.interval); clearInterval(Build.interval);
// Init breakpoint checker // Init breakpoint checker
this.bp = Breakpoints.get(); this.bp = Breakpoints.get();
$('.js-build-sidebar').niceScroll(); this.initSidebar();
this.populateJobs(this.build_stage); this.populateJobs(this.build_stage);
this.updateStageDropdownText(this.build_stage); this.updateStageDropdownText(this.build_stage);
this.hideSidebar();
$(document).off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar);
$(window).off('resize.build').on('resize.build', this.hideSidebar); $(window).off('resize.build').on('resize.build', this.hideSidebar);
$(document).off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown); this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown);
$('#js-build-scroll > a').off('click').on('click', this.stepTrace); $('#js-build-scroll > a').off('click').on('click', this.stepTrace);
this.updateArtifactRemoveDate(); this.updateArtifactRemoveDate();
if ($('#build-trace').length) { if ($('#build-trace').length) {
...@@ -62,6 +61,21 @@ ...@@ -62,6 +61,21 @@
} }
} }
Build.prototype.initSidebar = function() {
this.$sidebar = $('.js-build-sidebar');
this.sidebarTranslationLimits = {
min: $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight()
}
this.sidebarTranslationLimits.max = this.sidebarTranslationLimits.min + $('.scrolling-tabs-container').outerHeight();
this.$sidebar.css({
top: this.sidebarTranslationLimits.max
});
this.$sidebar.niceScroll();
this.hideSidebar();
this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar);
this.$document.off('scroll.translateSidebar').on('scroll.translateSidebar', this.translateSidebar.bind(this));
};
Build.prototype.getInitialBuildTrace = function() { Build.prototype.getInitialBuildTrace = function() {
var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped'] var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped']
...@@ -129,15 +143,23 @@ ...@@ -129,15 +143,23 @@
Build.prototype.toggleSidebar = function() { Build.prototype.toggleSidebar = function() {
if (this.shouldHideSidebar()) { if (this.shouldHideSidebar()) {
return $('.js-build-sidebar').toggleClass('right-sidebar-expanded right-sidebar-collapsed'); return this.$sidebar.toggleClass('right-sidebar-expanded right-sidebar-collapsed');
} }
}; };
Build.prototype.translateSidebar = function(e) {
var newPosition = this.sidebarTranslationLimits.max - document.body.scrollTop;
if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min;
this.$sidebar.css({
top: newPosition
});
};
Build.prototype.hideSidebar = function() { Build.prototype.hideSidebar = function() {
if (this.shouldHideSidebar()) { if (this.shouldHideSidebar()) {
return $('.js-build-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed'); return this.$sidebar.removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
} else { } else {
return $('.js-build-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); return this.$sidebar.removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
} }
}; };
......
...@@ -9,7 +9,10 @@ ...@@ -9,7 +9,10 @@
var $dropdown, selected; var $dropdown, selected;
$dropdown = $(this); $dropdown = $(this);
selected = $dropdown.data('selected'); selected = $dropdown.data('selected');
return $dropdown.glDropdown({ const $dropdownContainer = $dropdown.closest('.dropdown');
const $fieldInput = $(`input[name="${$dropdown.data('field-name')}"]`, $dropdownContainer);
const $filterInput = $('input[type="search"]', $dropdownContainer);
$dropdown.glDropdown({
data: function(term, callback) { data: function(term, callback) {
return $.ajax({ return $.ajax({
url: $dropdown.data('refs-url'), url: $dropdown.data('refs-url'),
...@@ -42,6 +45,14 @@ ...@@ -42,6 +45,14 @@
return $el.text().trim(); return $el.text().trim();
} }
}); });
$filterInput.on('keyup', (e) => {
const keyCode = e.keyCode || e.which;
if (keyCode !== 13) return;
const text = $filterInput.val();
$fieldInput.val(text);
$('.dropdown-toggle-text', $dropdown).text(text);
$dropdownContainer.removeClass('open');
});
}); });
}; };
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
Dispatcher = (function() { Dispatcher = (function() {
function Dispatcher() { function Dispatcher() {
this.initSearch(); this.initSearch();
this.initFieldErrors();
this.initPageScripts(); this.initPageScripts();
} }
...@@ -20,6 +21,9 @@ ...@@ -20,6 +21,9 @@
path = page.split(':'); path = page.split(':');
shortcut_handler = null; shortcut_handler = null;
switch (page) { switch (page) {
case 'sessions:new':
new UsernameValidator();
break;
case 'projects:boards:show': case 'projects:boards:show':
case 'projects:boards:index': case 'projects:boards:index':
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
...@@ -137,12 +141,12 @@ ...@@ -137,12 +141,12 @@
break; break;
case 'groups:group_members:index': case 'groups:group_members:index':
new gl.MemberExpirationDate(); new gl.MemberExpirationDate();
new GroupMembers(); new gl.Members();
new UsersSelect(); new UsersSelect();
break; break;
case 'projects:project_members:index': case 'projects:project_members:index':
new gl.MemberExpirationDate(); new gl.MemberExpirationDate();
new ProjectMembers(); new gl.Members();
new UsersSelect(); new UsersSelect();
break; break;
case 'groups:new': case 'groups:new':
...@@ -288,6 +292,12 @@ ...@@ -288,6 +292,12 @@
} }
}; };
Dispatcher.prototype.initFieldErrors = function() {
$('.show-gl-field-errors').each((i, form) => {
new gl.GlFieldErrors(form);
});
};
return Dispatcher; return Dispatcher;
})(); })();
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
return function(e) { return function(e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
return _this.input.val('').trigger('keyup').focus(); return _this.input.val('').trigger('input').focus();
}; };
})(this)); })(this));
// Key events // Key events
...@@ -37,28 +37,16 @@ ...@@ -37,28 +37,16 @@
e.preventDefault() e.preventDefault()
} }
}) })
.on('keyup', function(e) { .on('input', function() {
var keyCode;
keyCode = e.which;
if (ARROW_KEY_CODES.indexOf(keyCode) >= 0) {
return;
}
if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) { if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.addClass(HAS_VALUE_CLASS); $inputContainer.addClass(HAS_VALUE_CLASS);
} else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) { } else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.removeClass(HAS_VALUE_CLASS); $inputContainer.removeClass(HAS_VALUE_CLASS);
} }
if (keyCode === 13 && !options.elIsInput) {
return false;
}
// Only filter asynchronously only if option remote is set // Only filter asynchronously only if option remote is set
if (this.options.remote) { if (this.options.remote) {
clearTimeout(timeout); clearTimeout(timeout);
return timeout = setTimeout(function() { return timeout = setTimeout(function() {
var blurField = this.shouldBlur(keyCode);
if (blurField && this.filterInputBlur) {
this.input.blur();
}
return this.options.query(this.input.val(), function(data) { return this.options.query(this.input.val(), function(data) {
return this.options.callback(data); return this.options.callback(data);
}.bind(this)); }.bind(this));
...@@ -255,7 +243,7 @@ ...@@ -255,7 +243,7 @@
_this.fullData = data; _this.fullData = data;
_this.parseData(_this.fullData); _this.parseData(_this.fullData);
if (_this.options.filterable && _this.filter && _this.filter.input) { if (_this.options.filterable && _this.filter && _this.filter.input) {
return _this.filter.input.trigger('keyup'); return _this.filter.input.trigger('input');
} }
}; };
// Remote data // Remote data
...@@ -487,7 +475,7 @@ ...@@ -487,7 +475,7 @@
// Triggering 'keyup' will re-render the dropdown which is not always required // Triggering 'keyup' will re-render the dropdown which is not always required
// specially if we want to keep the state of the dropdown needed for bulk-assignment // specially if we want to keep the state of the dropdown needed for bulk-assignment
if (!this.options.persistWhenHide) { if (!this.options.persistWhenHide) {
$input.trigger("keyup"); $input.trigger("input");
} }
if (this.dropdown.find(".dropdown-toggle-page").length) { if (this.dropdown.find(".dropdown-toggle-page").length) {
$('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS); $('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS);
...@@ -500,14 +488,27 @@ ...@@ -500,14 +488,27 @@
// Render the full menu // Render the full menu
GitLabDropdown.prototype.renderMenu = function(html) { GitLabDropdown.prototype.renderMenu = function(html) {
var menu_html;
menu_html = "";
if (this.options.renderMenu) { if (this.options.renderMenu) {
menu_html = this.options.renderMenu(html); return this.options.renderMenu(html);
} else { } else {
menu_html = $('<ul />').append(html); var ul = document.createElement('ul');
for (var i = 0; i < html.length; i++) {
var el = html[i];
if (el instanceof jQuery) {
el = el.get(0);
}
if (typeof el === 'string') {
ul.innerHTML += el;
} else {
ul.appendChild(el);
}
}
return ul;
} }
return menu_html;
}; };
// Append the menu into the dropdown // Append the menu into the dropdown
...@@ -521,7 +522,7 @@ ...@@ -521,7 +522,7 @@
}; };
GitLabDropdown.prototype.renderItem = function(data, group, index) { GitLabDropdown.prototype.renderItem = function(data, group, index) {
var cssClass, field, fieldName, groupAttrs, html, selected, text, url, value; var field, fieldName, html, selected, text, url, value;
if (group == null) { if (group == null) {
group = false; group = false;
} }
...@@ -529,18 +530,16 @@ ...@@ -529,18 +530,16 @@
// Render the row // Render the row
index = false; index = false;
} }
html = ""; html = document.createElement('li');
// Divider if (data === 'divider' || data === 'separator') {
if (data === "divider") { html.className = data;
return "<li class='divider'></li>"; return html;
}
// Separator is a full-width divider
if (data === "separator") {
return "<li class='separator'></li>";
} }
// Header // Header
if (data.header != null) { if (data.header != null) {
return _.template('<li class="dropdown-header"><%- header %></li>')({ header: data.header }); html.className = 'dropdown-header';
html.innerHTML = data.header;
return html;
} }
if (this.options.renderRow) { if (this.options.renderRow) {
// Call the render function // Call the render function
...@@ -567,24 +566,25 @@ ...@@ -567,24 +566,25 @@
} else { } else {
text = data.text != null ? data.text : ''; text = data.text != null ? data.text : '';
} }
cssClass = "";
if (selected) {
cssClass = "is-active";
}
if (this.highlight) { if (this.highlight) {
text = this.highlightTextMatches(text, this.filterInput.val()); text = this.highlightTextMatches(text, this.filterInput.val());
} }
// Create the list item & the link
var link = document.createElement('a');
link.href = url;
link.innerHTML = text;
if (selected) {
link.className = 'is-active';
}
if (group) { if (group) {
groupAttrs = 'data-group=' + group + ' data-index=' + index; link.dataset.group = group;
} else { link.dataset.index = index;
groupAttrs = '';
} }
html = _.template('<li><a href="<%- url %>" <%- groupAttrs %> class="<%- cssClass %>"><%= text %></a></li>')({
url: url, html.appendChild(link);
groupAttrs: groupAttrs,
cssClass: cssClass,
text: text
});
} }
return html; return html;
}; };
......
((global) => {
/*
* This class overrides the browser's validation error bubbles, displaying custom
* error messages for invalid fields instead. To begin validating any form, add the
* class `show-gl-field-errors` to the form element, and ensure error messages are
* declared in each inputs' title attribute.
*
* Example:
*
* <form class='show-gl-field-errors'>
* <input type='text' name='username' title='Username is required.'/>
*</form>
*
* */
const errorMessageClass = 'gl-field-error';
const inputErrorClass = 'gl-field-error-outline';
class GlFieldError {
constructor({ input, formErrors }) {
this.inputElement = $(input);
this.inputDomElement = this.inputElement.get(0);
this.form = formErrors;
this.errorMessage = this.inputElement.attr('title') || 'This field is required.';
this.fieldErrorElement = $(`<p class='${errorMessageClass} hide'>${ this.errorMessage }</p>`);
this.state = {
valid: false,
empty: true
};
this.initFieldValidation();
}
initFieldValidation() {
// hidden when injected into DOM
this.inputElement.after(this.fieldErrorElement);
this.inputElement.off('invalid').on('invalid', this.handleInvalidSubmit.bind(this));
this.scopedSiblings = this.safelySelectSiblings();
}
safelySelectSiblings() {
// Apply `ignoreSelector` in markup to siblings whose visibility should not be toggled with input validity
const ignoreSelector = '.validation-ignore';
const unignoredSiblings = this.inputElement.siblings(`p:not(${ignoreSelector})`);
const parentContainer = this.inputElement.parent('.form-group');
// Only select siblings when they're scoped within a form-group with one input
const safelyScoped = parentContainer.length && parentContainer.find('input').length === 1;
return safelyScoped ? unignoredSiblings : this.fieldErrorElement;
}
renderValidity() {
this.renderClear();
if (this.state.valid) {
return this.renderValid();
}
if (this.state.empty) {
return this.renderEmpty();
}
if (!this.state.valid) {
return this.renderInvalid();
}
}
handleInvalidSubmit(event) {
event.preventDefault();
const currentValue = this.accessCurrentValue();
this.state.valid = false;
this.state.empty = currentValue === '';
this.renderValidity();
this.form.focusOnFirstInvalid.apply(this.form);
// For UX, wait til after first invalid submission to check each keyup
this.inputElement.off('keyup.field_validator')
.on('keyup.field_validator', this.updateValidity.bind(this));
}
/* Get or set current input value */
accessCurrentValue(newVal) {
return newVal ? this.inputElement.val(newVal) : this.inputElement.val();
}
getInputValidity() {
return this.inputDomElement.validity.valid;
}
updateValidity() {
const inputVal = this.accessCurrentValue();
this.state.empty = !inputVal.length;
this.state.valid = this.getInputValidity();
this.renderValidity();
}
renderValid() {
return this.renderClear();
}
renderEmpty() {
return this.renderInvalid();
}
renderInvalid() {
this.inputElement.addClass(inputErrorClass);
this.scopedSiblings.hide();
return this.fieldErrorElement.show();
}
renderClear() {
const inputVal = this.accessCurrentValue();
if (!inputVal.split(' ').length) {
const trimmedInput = inputVal.trim();
this.accessCurrentValue(trimmedInput);
}
this.inputElement.removeClass(inputErrorClass);
this.scopedSiblings.hide();
this.fieldErrorElement.hide();
}
}
const customValidationFlag = 'no-gl-field-errors';
class GlFieldErrors {
constructor(form) {
this.form = $(form);
this.state = {
inputs: [],
valid: false
};
this.initValidators();
}
initValidators () {
// select all non-hidden inputs in form
this.state.inputs = this.form.find(':input:not([type=hidden])').toArray()
.filter((input) => !input.classList.contains(customValidationFlag))
.map((input) => new GlFieldError({ input, formErrors: this }));
this.form.on('submit', this.catchInvalidFormSubmit);
}
/* Neccessary to prevent intercept and override invalid form submit
* because Safari & iOS quietly allow form submission when form is invalid
* and prevents disabling of invalid submit button by application.js */
catchInvalidFormSubmit (event) {
if (!event.currentTarget.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
}
focusOnFirstInvalid () {
const firstInvalid = this.state.inputs.filter((input) => !input.inputDomElement.validity.valid)[0];
firstInvalid.inputElement.focus();
}
}
global.GlFieldErrors = GlFieldErrors;
})(window.gl || (window.gl = {}));
(function() {
this.GroupMembers = (function() {
function GroupMembers() {
$('li.group_member').bind('ajax:success', function() {
return $(this).fadeOut();
});
}
return GroupMembers;
})();
}).call(this);
...@@ -14,14 +14,18 @@ ...@@ -14,14 +14,18 @@
inputs.datepicker({ inputs.datepicker({
dateFormat: 'yy-mm-dd', dateFormat: 'yy-mm-dd',
minDate: 1, minDate: 1,
onSelect: toggleClearInput onSelect: function () {
$(this).trigger('change');
toggleClearInput.call(this);
}
}); });
inputs.next('.js-clear-input').on('click', function(event) { inputs.next('.js-clear-input').on('click', function(event) {
event.preventDefault(); event.preventDefault();
var input = $(this).closest('.clearable-input').find('.js-access-expiration-date'); var input = $(this).closest('.clearable-input').find('.js-access-expiration-date');
input.datepicker('setDate', null); input.datepicker('setDate', null)
.trigger('change');
toggleClearInput.call(input); toggleClearInput.call(input);
}); });
......
((w) => {
w.gl = w.gl || {};
class Members {
constructor() {
this.addListeners();
}
addListeners() {
$('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow);
$('.js-member-update-control').off('change').on('change', this.formSubmit);
$('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess);
}
removeRow(e) {
const $target = $(e.target);
if ($target.hasClass('btn-remove')) {
$target.closest('.member')
.fadeOut(function () {
$(this).remove();
});
}
}
formSubmit() {
$(this).closest('form').trigger("submit.rails").end().disable();
}
formSuccess() {
$(this).find('.js-member-update-control').enable();
}
}
gl.Members = Members;
})(window);
...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
this._location = location; this._location = location;
this.bindEvents(); this.bindEvents();
this.activateTab(this.opts.action); this.activateTab(this.opts.action);
this.initAffix();
} }
MergeRequestTabs.prototype.bindEvents = function() { MergeRequestTabs.prototype.bindEvents = function() {
...@@ -380,6 +381,46 @@ ...@@ -380,6 +381,46 @@
// Only when sidebar is collapsed // Only when sidebar is collapsed
}; };
MergeRequestTabs.prototype.initAffix = function () {
var $tabs = $('.js-tabs-affix');
// Screen space on small screens is usually very sparse
// So we dont affix the tabs on these
if (Breakpoints.get().getBreakpointSize() === 'xs' || !$tabs.length) return;
var tabsWidth = $tabs.outerWidth(),
$diffTabs = $('#diff-notes-app'),
offsetTop = $tabs.offset().top - ($('.navbar-fixed-top').height() + $('.layout-nav').height());
$tabs.off('affix.bs.affix affix-top.bs.affix')
.affix({
offset: {
top: offsetTop
}
}).on('affix.bs.affix', function () {
$tabs.css({
left: $tabs.offset().left,
width: tabsWidth
});
$diffTabs.css({
marginTop: $tabs.height()
});
}).on('affix-top.bs.affix', function () {
$tabs.css({
left: '',
width: ''
});
$diffTabs.css({
marginTop: ''
});
});
// Fix bug when reloading the page already scrolling
if ($tabs.hasClass('affix')) {
$tabs.trigger('affix.bs.affix');
}
};
return MergeRequestTabs; return MergeRequestTabs;
})(); })();
......
(function() { ((global) => {
var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
this.MergeRequestWidget = (function() { const DEPLOYMENT_TEMPLATE = `<div class="mr-widget-heading" id="<%- id %>">
<div class="ci_widget ci-success">
<%= ci_success_icon %>
<span>
Deployed to
<a href="<%- url %>" target="_blank" class="environment">
<%- name %>
</a>
<span class="js-environment-timeago" data-toggle="tooltip" data-placement="top" data-title="<%- deployed_at_formatted %>">
<%- deployed_at %>
</span>
<a class="js-environment-link" href="<%- external_url %>" target="_blank">
<i class="fa fa-external-link"></i>
View on <%- external_url_formatted %>
</a>
</span>
</div>
</div>`;
global.MergeRequestWidget = (function() {
function MergeRequestWidget(opts) { function MergeRequestWidget(opts) {
// Initialize MergeRequestWidget behavior // Initialize MergeRequestWidget behavior
// //
...@@ -10,17 +29,23 @@ ...@@ -10,17 +29,23 @@
// ci_status_url - String, URL to use to check CI status // ci_status_url - String, URL to use to check CI status
// //
this.opts = opts; this.opts = opts;
this.$widgetBody = $('.mr-widget-body');
$('#modal_merge_info').modal({ $('#modal_merge_info').modal({
show: false show: false
}); });
this.firstCICheck = true; this.firstCICheck = true;
this.readyForCICheck = false; this.readyForCICheck = false;
this.readyForCIEnvironmentCheck = false;
this.cancel = false; this.cancel = false;
clearInterval(this.fetchBuildStatusInterval); clearInterval(this.fetchBuildStatusInterval);
clearInterval(this.fetchBuildEnvironmentStatusInterval);
this.clearEventListeners(); this.clearEventListeners();
this.addEventListeners(); this.addEventListeners();
this.getCIStatus(false); this.getCIStatus(false);
this.getCIEnvironmentsStatus();
this.retrieveSuccessIcon();
this.pollCIStatus(); this.pollCIStatus();
this.pollCIEnvironmentsStatus();
notifyPermissions(); notifyPermissions();
} }
...@@ -41,6 +66,7 @@ ...@@ -41,6 +66,7 @@
page = $('body').data('page').split(':').last(); page = $('body').data('page').split(':').last();
if (allowedPages.indexOf(page) < 0) { if (allowedPages.indexOf(page) < 0) {
clearInterval(_this.fetchBuildStatusInterval); clearInterval(_this.fetchBuildStatusInterval);
clearInterval(_this.fetchBuildEnvironmentStatusInterval);
_this.cancelPolling(); _this.cancelPolling();
return _this.clearEventListeners(); return _this.clearEventListeners();
} }
...@@ -48,6 +74,12 @@ ...@@ -48,6 +74,12 @@
})(this)); })(this));
}; };
MergeRequestWidget.prototype.retrieveSuccessIcon = function() {
const $ciSuccessIcon = $('.js-success-icon');
this.$ciSuccessIcon = $ciSuccessIcon.html();
$ciSuccessIcon.remove();
}
MergeRequestWidget.prototype.mergeInProgress = function(deleteSourceBranch) { MergeRequestWidget.prototype.mergeInProgress = function(deleteSourceBranch) {
if (deleteSourceBranch == null) { if (deleteSourceBranch == null) {
deleteSourceBranch = false; deleteSourceBranch = false;
...@@ -62,7 +94,7 @@ ...@@ -62,7 +94,7 @@
urlSuffix = deleteSourceBranch ? '?deleted_source_branch=true' : ''; urlSuffix = deleteSourceBranch ? '?deleted_source_branch=true' : '';
return window.location.href = window.location.pathname + urlSuffix; return window.location.href = window.location.pathname + urlSuffix;
} else if (data.merge_error) { } else if (data.merge_error) {
return $('.mr-widget-body').html("<h4>" + data.merge_error + "</h4>"); return this.$widgetBody.html("<h4>" + data.merge_error + "</h4>");
} else { } else {
callback = function() { callback = function() {
return merge_request_widget.mergeInProgress(deleteSourceBranch); return merge_request_widget.mergeInProgress(deleteSourceBranch);
...@@ -118,6 +150,7 @@ ...@@ -118,6 +150,7 @@
if (data.status === '') { if (data.status === '') {
return; return;
} }
if (data.environments && data.environments.length) _this.renderEnvironments(data.environments);
if (_this.firstCICheck || data.status !== _this.opts.ci_status && (data.status != null)) { if (_this.firstCICheck || data.status !== _this.opts.ci_status && (data.status != null)) {
_this.opts.ci_status = data.status; _this.opts.ci_status = data.status;
_this.showCIStatus(data.status); _this.showCIStatus(data.status);
...@@ -150,6 +183,41 @@ ...@@ -150,6 +183,41 @@
})(this)); })(this));
}; };
MergeRequestWidget.prototype.pollCIEnvironmentsStatus = function() {
this.fetchBuildEnvironmentStatusInterval = setInterval(() => {
if (!this.readyForCIEnvironmentCheck) return;
this.getCIEnvironmentsStatus();
this.readyForCIEnvironmentCheck = false;
}, 300000);
};
MergeRequestWidget.prototype.getCIEnvironmentsStatus = function() {
$.getJSON(this.opts.ci_environments_status_url, (environments) => {
if (this.cancel) return;
this.readyForCIEnvironmentCheck = true;
if (environments && environments.length) this.renderEnvironments(environments);
});
};
MergeRequestWidget.prototype.renderEnvironments = function(environments) {
for (let i = 0; i < environments.length; i++) {
const environment = environments[i];
if ($(`.mr-state-widget #${ environment.id }`).length) return;
const $template = $(DEPLOYMENT_TEMPLATE);
if (!environment.external_url || !environment.external_url_formatted) $('.js-environment-link', $template).remove();
if (environment.deployed_at && environment.deployed_at_formatted) {
environment.deployed_at = $.timeago(environment.deployed_at) + '.';
} else {
$('.js-environment-timeago', $template).remove();
environment.name += '.';
}
environment.ci_success_icon = this.$ciSuccessIcon;
const templateString = _.unescape($template[0].outerHTML);
const template = _.template(templateString)(environment)
this.$widgetBody.before(template);
}
};
MergeRequestWidget.prototype.showCIStatus = function(state) { MergeRequestWidget.prototype.showCIStatus = function(state) {
var allowed_states; var allowed_states;
if (state == null) { if (state == null) {
...@@ -190,4 +258,4 @@ ...@@ -190,4 +258,4 @@
})(); })();
}).call(this); })(window.gl || (window.gl = {}));
(function() {
this.ProjectMembers = (function() {
function ProjectMembers() {
$('li.project_member').bind('ajax:success', function() {
return $(this).fadeOut();
});
}
return ProjectMembers;
})();
}).call(this);
...@@ -16,7 +16,13 @@ ...@@ -16,7 +16,13 @@
if (initialQuery.name) this.requestFile(initialQuery); if (initialQuery.name) this.requestFile(initialQuery);
$('.reset-template', this.dropdown.parent()).on('click', () => { $('.reset-template', this.dropdown.parent()).on('click', () => {
if (this.currentTemplate) this.setInputValueToTemplateContent(false); this.setInputValueToTemplateContent();
});
$('.no-template', this.dropdown.parent()).on('click', () => {
this.currentTemplate = '';
this.setInputValueToTemplateContent();
$('.dropdown-toggle-text', this.dropdown).text('Choose a template');
}); });
} }
......
((global) => {
const debounceTimeoutDuration = 1000;
const invalidInputClass = 'gl-field-error-outline';
const successInputClass = 'gl-field-success-outline';
const unavailableMessageSelector = '.username .validation-error';
const successMessageSelector = '.username .validation-success';
const pendingMessageSelector = '.username .validation-pending';
const invalidMessageSelector = '.username .gl-field-error';
class UsernameValidator {
constructor() {
this.inputElement = $('#new_user_username');
this.inputDomElement = this.inputElement.get(0);
this.state = {
available: false,
valid: false,
pending: false,
empty: true
};
const debounceTimeout = _.debounce((username) => {
this.validateUsername(username);
}, debounceTimeoutDuration);
this.inputElement.on('keyup.username_check', () => {
const username = this.inputElement.val();
this.state.valid = this.inputDomElement.validity.valid;
this.state.empty = !username.length;
if (this.state.valid) {
return debounceTimeout(username);
}
this.renderState();
});
// Override generic field validation
this.inputElement.on('invalid', this.interceptInvalid.bind(this));
}
renderState() {
// Clear all state
this.clearFieldValidationState();
if (this.state.valid && this.state.available) {
return this.setSuccessState();
}
if (this.state.empty) {
return this.clearFieldValidationState();
}
if (this.state.pending) {
return this.setPendingState();
}
if (!this.state.available) {
return this.setUnavailableState();
}
if (!this.state.valid) {
return this.setInvalidState();
}
}
interceptInvalid(event) {
event.preventDefault();
event.stopPropagation();
}
validateUsername(username) {
if (this.state.valid) {
this.state.pending = true;
this.state.available = false;
this.renderState();
return $.ajax({
type: 'GET',
url: `/u/${username}/exists`,
dataType: 'json',
success: (res) => this.setAvailabilityState(res.exists)
});
}
}
setAvailabilityState(usernameTaken) {
if (usernameTaken) {
this.state.valid = false;
this.state.available = false;
} else {
this.state.available = true;
}
this.state.pending = false;
this.renderState();
}
clearFieldValidationState() {
this.inputElement.siblings('p').hide();
this.inputElement.removeClass(invalidInputClass)
.removeClass(successInputClass);
}
setUnavailableState() {
const $usernameUnavailableMessage = this.inputElement.siblings(unavailableMessageSelector);
this.inputElement.addClass(invalidInputClass).removeClass(successInputClass);
$usernameUnavailableMessage.show();
}
setSuccessState() {
const $usernameSuccessMessage = this.inputElement.siblings(successMessageSelector);
this.inputElement.addClass(successInputClass).removeClass(invalidInputClass);
$usernameSuccessMessage.show();
}
setPendingState() {
const $usernamePendingMessage = $(pendingMessageSelector);
if (this.state.pending) {
$usernamePendingMessage.show();
} else {
$usernamePendingMessage.hide();
}
}
setInvalidState() {
const $inputErrorMessage = $(invalidMessageSelector);
this.inputElement.addClass(invalidInputClass).removeClass(successInputClass);
$inputErrorMessage.show();
}
}
global.UsernameValidator = UsernameValidator;
})(window);
...@@ -325,6 +325,10 @@ ...@@ -325,6 +325,10 @@
}; };
UsersSelect.prototype.user = function(user_id, callback) { UsersSelect.prototype.user = function(user_id, callback) {
if(!/^\d+$/.test(user_id)) {
return false;
}
var url; var url;
url = this.buildUrl(this.userPath); url = this.buildUrl(this.userPath);
url = url.replace(':id', user_id); url = url.replace(':id', user_id);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
display: none; display: none;
&.hide { display: block; } &.hide { display: block; }
} }
&.open .content { &.open .content {
display: block; display: block;
&.hide { display: none; } &.hide { display: none; }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
&.diff-collapsed { &.diff-collapsed {
padding: 5px; padding: 5px;
.click-to-expand { .click-to-expand {
cursor: pointer; cursor: pointer;
} }
...@@ -203,6 +204,7 @@ ...@@ -203,6 +204,7 @@
} }
} }
} }
&.user-cover-block { &.user-cover-block {
padding: 24px 0 0; padding: 24px 0 0;
} }
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
&:focus { &:focus {
background-color: $hover-background; background-color: $hover-background;
color: $hover-text; color: $hover-text;
border-color: $hover-border;; border-color: $hover-border;
} }
} }
...@@ -152,7 +152,8 @@ ...@@ -152,7 +152,8 @@
@include btn-blue-medium; @include btn-blue-medium;
} }
&.btn-info { &.btn-info,
&.btn-register {
@include btn-blue; @include btn-blue;
} }
...@@ -240,6 +241,7 @@ ...@@ -240,6 +241,7 @@
width: 100%; width: 100%;
margin: 0; margin: 0;
margin-bottom: 15px; margin-bottom: 15px;
&.btn { &.btn {
padding: 6px 0; padding: 6px 0;
} }
...@@ -321,6 +323,7 @@ ...@@ -321,6 +323,7 @@
.btn-build { .btn-build {
margin-left: 10px; margin-left: 10px;
i { i {
color: $gl-icon-color; color: $gl-icon-color;
} }
...@@ -328,6 +331,7 @@ ...@@ -328,6 +331,7 @@
.clone-dropdown-btn a { .clone-dropdown-btn a {
color: $dropdown-link-color; color: $dropdown-link-color;
&:hover { &:hover {
text-decoration: none; text-decoration: none;
} }
...@@ -337,6 +341,7 @@ ...@@ -337,6 +341,7 @@
background-color: $background-color !important; background-color: $background-color !important;
border: 1px solid lightgrey; border: 1px solid lightgrey;
cursor: default; cursor: default;
&:active { &:active {
-moz-box-shadow: inset 0 0 0 white; -moz-box-shadow: inset 0 0 0 white;
-webkit-box-shadow: inset 0 0 0 white; -webkit-box-shadow: inset 0 0 0 white;
......
...@@ -13,10 +13,12 @@ ...@@ -13,10 +13,12 @@
color: $text-color; color: $text-color;
background: $background-color; background: $background-color;
} }
.bs-callout h4 { .bs-callout h4 {
margin-top: 0; margin-top: 0;
margin-bottom: 5px; margin-bottom: 5px;
} }
.bs-callout p:last-child { .bs-callout p:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
...@@ -27,16 +29,19 @@ ...@@ -27,16 +29,19 @@
border-color: #eed3d7; border-color: #eed3d7;
color: #b94a48; color: #b94a48;
} }
.bs-callout-warning { .bs-callout-warning {
background-color: #faf8f0; background-color: #faf8f0;
border-color: #faebcc; border-color: #faebcc;
color: #8a6d3b; color: #8a6d3b;
} }
.bs-callout-info { .bs-callout-info {
background-color: #f4f8fa; background-color: #f4f8fa;
border-color: #bce8f1; border-color: #bce8f1;
color: #34789a; color: #34789a;
} }
.bs-callout-success { .bs-callout-success {
background-color: #dff0d8; background-color: #dff0d8;
border-color: #5ca64d; border-color: #5ca64d;
......
/** COLORS **/ /** COLORS **/
.cgray { color: $gl-gray; } .cgray { color: $gl-gray; }
.clgray { color: #bbb } .clgray { color: #bbb; }
.cred { color: $gl-text-red; } .cred { color: $gl-text-red; }
.cgreen { color: $gl-text-green; } .cgreen { color: $gl-text-green; }
.cdark { color: #444 } .cdark { color: #444; }
/** COMMON CLASSES **/ /** COMMON CLASSES **/
.prepend-top-0 { margin-top: 0; } .prepend-top-0 { margin-top: 0; }
.prepend-top-5 { margin-top: 5px; } .prepend-top-5 { margin-top: 5px; }
.prepend-top-10 { margin-top: 10px } .prepend-top-10 { margin-top: 10px; }
.prepend-top-default { margin-top: $gl-padding !important; } .prepend-top-default { margin-top: $gl-padding !important; }
.prepend-top-20 { margin-top: 20px } .prepend-top-20 { margin-top: 20px; }
.prepend-left-5 { margin-left: 5px } .prepend-left-5 { margin-left: 5px; }
.prepend-left-10 { margin-left: 10px } .prepend-left-10 { margin-left: 10px; }
.prepend-left-default { margin-left: $gl-padding; } .prepend-left-default { margin-left: $gl-padding; }
.prepend-left-20 { margin-left: 20px } .prepend-left-20 { margin-left: 20px; }
.append-right-5 { margin-right: 5px } .append-right-5 { margin-right: 5px; }
.append-right-10 { margin-right: 10px } .append-right-10 { margin-right: 10px; }
.append-right-default { margin-right: $gl-padding; } .append-right-default { margin-right: $gl-padding; }
.append-right-20 { margin-right: 20px } .append-right-20 { margin-right: 20px; }
.append-bottom-0 { margin-bottom: 0 } .append-bottom-0 { margin-bottom: 0; }
.append-bottom-10 { margin-bottom: 10px } .append-bottom-10 { margin-bottom: 10px; }
.append-bottom-15 { margin-bottom: 15px } .append-bottom-15 { margin-bottom: 15px; }
.append-bottom-20 { margin-bottom: 20px } .append-bottom-20 { margin-bottom: 20px; }
.append-bottom-default { margin-bottom: $gl-padding; } .append-bottom-default { margin-bottom: $gl-padding; }
.inline { display: inline-block } .inline { display: inline-block; }
.center { text-align: center } .center { text-align: center; }
.underlined-link { text-decoration: underline; } .underlined-link { text-decoration: underline; }
.hint { font-style: italic; color: #999; } .hint { font-style: italic; color: #999; }
...@@ -97,6 +97,7 @@ span.update-author { ...@@ -97,6 +97,7 @@ span.update-author {
color: #999; color: #999;
font-weight: normal; font-weight: normal;
font-style: italic; font-style: italic;
strong { strong {
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
...@@ -128,7 +129,7 @@ p.time { ...@@ -128,7 +129,7 @@ p.time {
// Fix issue with notes & lists creating a bunch of bottom borders. // Fix issue with notes & lists creating a bunch of bottom borders.
li.note { li.note {
img { max-width: 100% } img { max-width: 100%; }
.note-title { .note-title {
li { li {
border-bottom: none !important; border-bottom: none !important;
...@@ -172,6 +173,7 @@ li.note { ...@@ -172,6 +173,7 @@ li.note {
@extend .col-md-6; @extend .col-md-6;
text-align: left; text-align: left;
margin-top: 40px; margin-top: 40px;
pre { pre {
background: white; background: white;
border: none; border: none;
...@@ -197,6 +199,7 @@ li.note { ...@@ -197,6 +199,7 @@ li.note {
background: #c67; background: #c67;
color: #fff; color: #fff;
font-weight: bold; font-weight: bold;
a { a {
color: #fff; color: #fff;
text-decoration: underline; text-decoration: underline;
...@@ -227,6 +230,7 @@ li.note { ...@@ -227,6 +230,7 @@ li.note {
&.milestone-closed { &.milestone-closed {
background: $gray-light; background: $gray-light;
} }
.progress { .progress {
margin-bottom: 0; margin-bottom: 0;
margin-top: 4px; margin-top: 4px;
...@@ -286,6 +290,7 @@ table { ...@@ -286,6 +290,7 @@ table {
.footer-links { .footer-links {
margin-bottom: 20px; margin-bottom: 20px;
a { a {
margin-right: 15px; margin-right: 15px;
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
.dropdown-menu, .dropdown-menu,
.dropdown-menu-nav { .dropdown-menu-nav {
display: block; display: block;
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
width: 100%; width: 100%;
} }
...@@ -48,6 +49,7 @@ ...@@ -48,6 +49,7 @@
margin-top: -6px; margin-top: -6px;
color: $dropdown-toggle-icon-color; color: $dropdown-toggle-icon-color;
font-size: 10px; font-size: 10px;
&.fa-spinner { &.fa-spinner {
font-size: 16px; font-size: 16px;
margin-top: -8px; margin-top: -8px;
......
...@@ -26,15 +26,6 @@ ...@@ -26,15 +26,6 @@
padding: 10px $gl-padding; padding: 10px $gl-padding;
word-wrap: break-word; word-wrap: break-word;
border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0;
cursor: pointer;
&:hover {
background-color: $dark-background-color;
}
.diff-toggle-caret {
padding-right: 6px;
}
&.file-title-clear { &.file-title-clear {
padding-left: 0; padding-left: 0;
...@@ -66,6 +57,7 @@ ...@@ -66,6 +57,7 @@
margin-top: -3px; margin-top: -3px;
} }
} }
.file-content { .file-content {
background: #fff; background: #fff;
...@@ -105,22 +97,27 @@ ...@@ -105,22 +97,27 @@
border: none; border: none;
margin: 0; margin: 0;
} }
tr { tr {
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
td { td {
&:first-child { &:first-child {
border-left: none; border-left: none;
} }
&:last-child { &:last-child {
border-right: none; border-right: none;
} }
} }
td.blame-commit { td.blame-commit {
padding: 0 10px; padding: 0 10px;
min-width: 400px; min-width: 400px;
background: $gray-light; background: $gray-light;
} }
td.line-numbers { td.line-numbers {
float: none; float: none;
border-left: 1px solid #ddd; border-left: 1px solid #ddd;
...@@ -130,6 +127,7 @@ ...@@ -130,6 +127,7 @@
margin-right: 0; margin-right: 0;
} }
} }
td.lines { td.lines {
padding: 0; padding: 0;
} }
...@@ -146,8 +144,10 @@ ...@@ -146,8 +144,10 @@
border-left: 1px solid $border-color; border-left: 1px solid $border-color;
margin-bottom: 0; margin-bottom: 0;
background: white; background: white;
li { li {
color: #888; color: #888;
p { p {
margin: 0; margin: 0;
color: #333; color: #333;
......
...@@ -9,7 +9,7 @@ input { ...@@ -9,7 +9,7 @@ input {
input[type='text'].danger { input[type='text'].danger {
background: #f2dede!important; background: #f2dede!important;
border-color: #d66; border-color: #d66;
text-shadow: 0 1px 1px #fff text-shadow: 0 1px 1px #fff;
} }
.datetime-controls { .datetime-controls {
...@@ -73,8 +73,8 @@ label { ...@@ -73,8 +73,8 @@ label {
} }
.form-control { .form-control {
box-shadow: none; @include box-shadow(none);
border-radius: 3px; border-radius: 2px;
padding: $gl-vert-padding $gl-input-padding; padding: $gl-vert-padding $gl-input-padding;
} }
...@@ -117,9 +117,11 @@ label { ...@@ -117,9 +117,11 @@ label {
display: table-cell; display: table-cell;
width: 200px !important; width: 200px !important;
} }
.input-group-addon { .input-group-addon {
background-color: #f7f8fa; background-color: #f7f8fa;
} }
.input-group-addon:not(:first-child):not(:last-child) { .input-group-addon:not(:first-child):not(:last-child) {
border-left: 0; border-left: 0;
border-right: 0; border-right: 0;
...@@ -129,3 +131,8 @@ label { ...@@ -129,3 +131,8 @@ label {
.help-block { .help-block {
margin-bottom: 0; margin-bottom: 0;
} }
.gl-field-error {
color: $red-normal;
}
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
} }
i { i {
color: $white-light color: $white-light;
} }
path, path,
......
...@@ -168,6 +168,7 @@ header { ...@@ -168,6 +168,7 @@ header {
a { a {
color: $gl-text-color; color: $gl-text-color;
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
padding-top: 1px; padding-top: 1px;
margin: 0; margin: 0;
color: $gray-dark; color: $gray-dark;
img { img {
position: relative; position: relative;
top: 3px; top: 3px;
...@@ -128,6 +129,10 @@ ul.content-list { ...@@ -128,6 +129,10 @@ ul.content-list {
color: $gl-dark-link-color; color: $gl-dark-link-color;
} }
.member-group-link {
color: $blue-normal;
}
.description { .description {
p { p {
@include str-truncated; @include str-truncated;
...@@ -168,6 +173,14 @@ ul.content-list { ...@@ -168,6 +173,14 @@ ul.content-list {
} }
} }
.member-controls {
float: none;
@media (min-width: $screen-sm-min) {
float: right;
}
}
// When dragging a list item // When dragging a list item
&.ui-sortable-helper { &.ui-sortable-helper {
border-bottom: none; border-bottom: none;
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
0%, 10%, 100% { 0%, 10%, 100% {
fill: lighten($tanuki-yellow, 25%); fill: lighten($tanuki-yellow, 25%);
} }
90% { 90% {
fill: $tanuki-yellow; fill: $tanuki-yellow;
} }
...@@ -48,6 +49,7 @@ ...@@ -48,6 +49,7 @@
10%, 80% { 10%, 80% {
fill: $tanuki-orange; fill: $tanuki-orange;
} }
20%, 90% { 20%, 90% {
fill: lighten($tanuki-orange, 25%); fill: lighten($tanuki-orange, 25%);
} }
...@@ -59,6 +61,7 @@ ...@@ -59,6 +61,7 @@
10%, 80% { 10%, 80% {
fill: $tanuki-red; fill: $tanuki-red;
} }
20%, 90% { 20%, 90% {
fill: lighten($tanuki-red, 25%); fill: lighten($tanuki-red, 25%);
} }
...@@ -70,6 +73,7 @@ ...@@ -70,6 +73,7 @@
20%, 70% { 20%, 70% {
fill: $tanuki-red; fill: $tanuki-red;
} }
30%, 80% { 30%, 80% {
fill: lighten($tanuki-red, 25%); fill: lighten($tanuki-red, 25%);
} }
...@@ -81,6 +85,7 @@ ...@@ -81,6 +85,7 @@
30%, 60% { 30%, 60% {
fill: $tanuki-orange; fill: $tanuki-orange;
} }
40%, 70% { 40%, 70% {
fill: lighten($tanuki-orange, 25%); fill: lighten($tanuki-orange, 25%);
} }
...@@ -92,6 +97,7 @@ ...@@ -92,6 +97,7 @@
30%, 60% { 30%, 60% {
fill: $tanuki-red; fill: $tanuki-red;
} }
40%, 70% { 40%, 70% {
fill: lighten($tanuki-red, 25%); fill: lighten($tanuki-red, 25%);
} }
...@@ -103,6 +109,7 @@ ...@@ -103,6 +109,7 @@
40% { 40% {
fill: $tanuki-yellow; fill: $tanuki-yellow;
} }
60% { 60% {
fill: lighten($tanuki-yellow, 25%); fill: lighten($tanuki-yellow, 25%);
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
&.active { &.active {
background: $gray-light; background: $gray-light;
a { a {
font-weight: 600; font-weight: 600;
} }
......
...@@ -210,6 +210,7 @@ ...@@ -210,6 +210,7 @@
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
padding-bottom: 0; padding-bottom: 0;
width: 100%; width: 100%;
.btn, form, .dropdown, .dropdown-menu-toggle, .form-control { .btn, form, .dropdown, .dropdown-menu-toggle, .form-control {
margin: 0 0 10px; margin: 0 0 10px;
display: block; display: block;
......
...@@ -13,6 +13,11 @@ ...@@ -13,6 +13,11 @@
.dropdown-menu-toggle { .dropdown-menu-toggle {
line-height: 20px; line-height: 20px;
} }
.badge {
margin-top: -2px;
margin-left: 5px;
}
} }
.panel-body { .panel-body {
......
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
background: none; background: none;
.select2-search-field input { .select2-search-field input {
padding: $gl-padding / 2; padding: 5px $gl-padding / 2;
font-size: 13px; font-size: 13px;
height: auto; height: auto;
font-family: inherit; font-family: inherit;
...@@ -101,7 +101,7 @@ ...@@ -101,7 +101,7 @@
} }
.select2-search-choice { .select2-search-choice {
margin: 8px 0 0 8px; margin: 5px 0 0 8px;
box-shadow: none; box-shadow: none;
border-color: $input-border; border-color: $input-border;
color: $gl-text-color; color: $gl-text-color;
...@@ -137,6 +137,7 @@ ...@@ -137,6 +137,7 @@
.select2-results { .select2-results {
max-height: 350px; max-height: 350px;
.select2-highlighted { .select2-highlighted {
background: $gl-primary; background: $gl-primary;
} }
...@@ -212,9 +213,11 @@ ...@@ -212,9 +213,11 @@
.group-image { .group-image {
float: left; float: left;
} }
.group-name { .group-name {
font-weight: bold; font-weight: bold;
} }
.group-path { .group-path {
color: #999; color: #999;
} }
...@@ -239,6 +242,7 @@ ...@@ -239,6 +242,7 @@
color: #aaa; color: #aaa;
font-weight: normal; font-weight: normal;
} }
.namespace-path { .namespace-path {
margin-left: 10px; margin-left: 10px;
font-weight: bolder; font-weight: bolder;
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
&:before { &:before {
background: none; background: none;
} }
.timeline-entry .timeline-entry-inner { .timeline-entry .timeline-entry-inner {
.timeline-icon { .timeline-icon {
display: none; display: none;
......
...@@ -48,31 +48,40 @@ ...@@ -48,31 +48,40 @@
.clearfix { .clearfix {
@include clearfix(); @include clearfix();
} }
.center-block { .center-block {
@include center-block(); @include center-block();
} }
.pull-right { .pull-right {
float: right !important; float: right !important;
} }
.pull-left { .pull-left {
float: left !important; float: left !important;
} }
.hide { .hide {
display: none; display: none;
} }
.show { .show {
display: block !important; display: block !important;
} }
.invisible { .invisible {
visibility: hidden; visibility: hidden;
} }
.text-hide { .text-hide {
@include text-hide(); @include text-hide();
} }
.hidden { .hidden {
display: none !important; display: none !important;
visibility: hidden !important; visibility: hidden !important;
} }
.affix { .affix {
position: fixed; position: fixed;
} }
...@@ -146,6 +155,7 @@ ...@@ -146,6 +155,7 @@
padding: 6px 15px; padding: 6px 15px;
font-size: 13px; font-size: 13px;
font-weight: normal; font-weight: normal;
a { a {
color: #777; color: #777;
} }
......
...@@ -106,6 +106,7 @@ ...@@ -106,6 +106,7 @@
@extend .table-bordered; @extend .table-bordered;
margin: 12px 0; margin: 12px 0;
color: #5c5d5e; color: #5c5d5e;
th { th {
background: #f8fafc; background: #f8fafc;
} }
......
...@@ -55,68 +55,68 @@ ...@@ -55,68 +55,68 @@
color: #000 !important; color: #000 !important;
} }
.hll { background-color: #373b41 } .hll { background-color: #373b41; }
.c { color: #969896 } /* Comment */ .c { color: #969896; } /* Comment */
.err { color: #c66 } /* Error */ .err { color: #c66; } /* Error */
.k { color: #b294bb } /* Keyword */ .k { color: #b294bb; } /* Keyword */
.l { color: #de935f } /* Literal */ .l { color: #de935f; } /* Literal */
.n { color: #c5c8c6 } /* Name */ .n { color: #c5c8c6; } /* Name */
.o { color: #8abeb7 } /* Operator */ .o { color: #8abeb7; } /* Operator */
.p { color: #c5c8c6 } /* Punctuation */ .p { color: #c5c8c6; } /* Punctuation */
.cm { color: #969896 } /* Comment.Multiline */ .cm { color: #969896; } /* Comment.Multiline */
.cp { color: #969896 } /* Comment.Preproc */ .cp { color: #969896; } /* Comment.Preproc */
.c1 { color: #969896 } /* Comment.Single */ .c1 { color: #969896; } /* Comment.Single */
.cs { color: #969896 } /* Comment.Special */ .cs { color: #969896; } /* Comment.Special */
.gd { color: #c66 } /* Generic.Deleted */ .gd { color: #c66; } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */ .ge { font-style: italic; } /* Generic.Emph */
.gh { color: #c5c8c6; font-weight: bold } /* Generic.Heading */ .gh { color: #c5c8c6; font-weight: bold; } /* Generic.Heading */
.gi { color: #b5bd68 } /* Generic.Inserted */ .gi { color: #b5bd68; } /* Generic.Inserted */
.gp { color: #969896; font-weight: bold } /* Generic.Prompt */ .gp { color: #969896; font-weight: bold; } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */ .gs { font-weight: bold; } /* Generic.Strong */
.gu { color: #8abeb7; font-weight: bold } /* Generic.Subheading */ .gu { color: #8abeb7; font-weight: bold; } /* Generic.Subheading */
.kc { color: #b294bb } /* Keyword.Constant */ .kc { color: #b294bb; } /* Keyword.Constant */
.kd { color: #b294bb } /* Keyword.Declaration */ .kd { color: #b294bb; } /* Keyword.Declaration */
.kn { color: #8abeb7 } /* Keyword.Namespace */ .kn { color: #8abeb7; } /* Keyword.Namespace */
.kp { color: #b294bb } /* Keyword.Pseudo */ .kp { color: #b294bb; } /* Keyword.Pseudo */
.kr { color: #b294bb } /* Keyword.Reserved */ .kr { color: #b294bb; } /* Keyword.Reserved */
.kt { color: #f0c674 } /* Keyword.Type */ .kt { color: #f0c674; } /* Keyword.Type */
.ld { color: #b5bd68 } /* Literal.Date */ .ld { color: #b5bd68; } /* Literal.Date */
.m { color: #de935f } /* Literal.Number */ .m { color: #de935f; } /* Literal.Number */
.s { color: #b5bd68 } /* Literal.String */ .s { color: #b5bd68; } /* Literal.String */
.na { color: #81a2be } /* Name.Attribute */ .na { color: #81a2be; } /* Name.Attribute */
.nb { color: #c5c8c6 } /* Name.Builtin */ .nb { color: #c5c8c6; } /* Name.Builtin */
.nc { color: #f0c674 } /* Name.Class */ .nc { color: #f0c674; } /* Name.Class */
.no { color: #c66 } /* Name.Constant */ .no { color: #c66; } /* Name.Constant */
.nd { color: #8abeb7 } /* Name.Decorator */ .nd { color: #8abeb7; } /* Name.Decorator */
.ni { color: #c5c8c6 } /* Name.Entity */ .ni { color: #c5c8c6; } /* Name.Entity */
.ne { color: #c66 } /* Name.Exception */ .ne { color: #c66; } /* Name.Exception */
.nf { color: #81a2be } /* Name.Function */ .nf { color: #81a2be; } /* Name.Function */
.nl { color: #c5c8c6 } /* Name.Label */ .nl { color: #c5c8c6; } /* Name.Label */
.nn { color: #f0c674 } /* Name.Namespace */ .nn { color: #f0c674; } /* Name.Namespace */
.nx { color: #81a2be } /* Name.Other */ .nx { color: #81a2be; } /* Name.Other */
.py { color: #c5c8c6 } /* Name.Property */ .py { color: #c5c8c6; } /* Name.Property */
.nt { color: #8abeb7 } /* Name.Tag */ .nt { color: #8abeb7; } /* Name.Tag */
.nv { color: #c66 } /* Name.Variable */ .nv { color: #c66; } /* Name.Variable */
.ow { color: #8abeb7 } /* Operator.Word */ .ow { color: #8abeb7; } /* Operator.Word */
.w { color: #c5c8c6 } /* Text.Whitespace */ .w { color: #c5c8c6; } /* Text.Whitespace */
.mf { color: #de935f } /* Literal.Number.Float */ .mf { color: #de935f; } /* Literal.Number.Float */
.mh { color: #de935f } /* Literal.Number.Hex */ .mh { color: #de935f; } /* Literal.Number.Hex */
.mi { color: #de935f } /* Literal.Number.Integer */ .mi { color: #de935f; } /* Literal.Number.Integer */
.mo { color: #de935f } /* Literal.Number.Oct */ .mo { color: #de935f; } /* Literal.Number.Oct */
.sb { color: #b5bd68 } /* Literal.String.Backtick */ .sb { color: #b5bd68; } /* Literal.String.Backtick */
.sc { color: #c5c8c6 } /* Literal.String.Char */ .sc { color: #c5c8c6; } /* Literal.String.Char */
.sd { color: #969896 } /* Literal.String.Doc */ .sd { color: #969896; } /* Literal.String.Doc */
.s2 { color: #b5bd68 } /* Literal.String.Double */ .s2 { color: #b5bd68; } /* Literal.String.Double */
.se { color: #de935f } /* Literal.String.Escape */ .se { color: #de935f; } /* Literal.String.Escape */
.sh { color: #b5bd68 } /* Literal.String.Heredoc */ .sh { color: #b5bd68; } /* Literal.String.Heredoc */
.si { color: #de935f } /* Literal.String.Interpol */ .si { color: #de935f; } /* Literal.String.Interpol */
.sx { color: #b5bd68 } /* Literal.String.Other */ .sx { color: #b5bd68; } /* Literal.String.Other */
.sr { color: #b5bd68 } /* Literal.String.Regex */ .sr { color: #b5bd68; } /* Literal.String.Regex */
.s1 { color: #b5bd68 } /* Literal.String.Single */ .s1 { color: #b5bd68; } /* Literal.String.Single */
.ss { color: #b5bd68 } /* Literal.String.Symbol */ .ss { color: #b5bd68; } /* Literal.String.Symbol */
.bp { color: #c5c8c6 } /* Name.Builtin.Pseudo */ .bp { color: #c5c8c6; } /* Name.Builtin.Pseudo */
.vc { color: #c66 } /* Name.Variable.Class */ .vc { color: #c66; } /* Name.Variable.Class */
.vg { color: #c66 } /* Name.Variable.Global */ .vg { color: #c66; } /* Name.Variable.Global */
.vi { color: #c66 } /* Name.Variable.Instance */ .vi { color: #c66; } /* Name.Variable.Instance */
.il { color: #de935f } /* Literal.Number.Integer.Long */ .il { color: #de935f; } /* Literal.Number.Integer.Long */
} }
...@@ -55,65 +55,65 @@ ...@@ -55,65 +55,65 @@
color: #000 !important; color: #000 !important;
} }
.hll { background-color: #49483e } .hll { background-color: #49483e; }
.c { color: #75715e } /* Comment */ .c { color: #75715e; } /* Comment */
.err { color: #960050; background-color: #1e0010 } /* Error */ .err { color: #960050; background-color: #1e0010; } /* Error */
.k { color: #66d9ef } /* Keyword */ .k { color: #66d9ef; } /* Keyword */
.l { color: #ae81ff } /* Literal */ .l { color: #ae81ff; } /* Literal */
.n { color: #f8f8f2 } /* Name */ .n { color: #f8f8f2; } /* Name */
.o { color: #f92672 } /* Operator */ .o { color: #f92672; } /* Operator */
.p { color: #f8f8f2 } /* Punctuation */ .p { color: #f8f8f2; } /* Punctuation */
.cm { color: #75715e } /* Comment.Multiline */ .cm { color: #75715e; } /* Comment.Multiline */
.cp { color: #75715e } /* Comment.Preproc */ .cp { color: #75715e; } /* Comment.Preproc */
.c1 { color: #75715e } /* Comment.Single */ .c1 { color: #75715e; } /* Comment.Single */
.cs { color: #75715e } /* Comment.Special */ .cs { color: #75715e; } /* Comment.Special */
.ge { font-style: italic } /* Generic.Emph */ .ge { font-style: italic; } /* Generic.Emph */
.gs { font-weight: bold } /* Generic.Strong */ .gs { font-weight: bold; } /* Generic.Strong */
.kc { color: #66d9ef } /* Keyword.Constant */ .kc { color: #66d9ef; } /* Keyword.Constant */
.kd { color: #66d9ef } /* Keyword.Declaration */ .kd { color: #66d9ef; } /* Keyword.Declaration */
.kn { color: #f92672 } /* Keyword.Namespace */ .kn { color: #f92672; } /* Keyword.Namespace */
.kp { color: #66d9ef } /* Keyword.Pseudo */ .kp { color: #66d9ef; } /* Keyword.Pseudo */
.kr { color: #66d9ef } /* Keyword.Reserved */ .kr { color: #66d9ef; } /* Keyword.Reserved */
.kt { color: #66d9ef } /* Keyword.Type */ .kt { color: #66d9ef; } /* Keyword.Type */
.ld { color: #e6db74 } /* Literal.Date */ .ld { color: #e6db74; } /* Literal.Date */
.m { color: #ae81ff } /* Literal.Number */ .m { color: #ae81ff; } /* Literal.Number */
.s { color: #e6db74 } /* Literal.String */ .s { color: #e6db74; } /* Literal.String */
.na { color: #a6e22e } /* Name.Attribute */ .na { color: #a6e22e; } /* Name.Attribute */
.nb { color: #f8f8f2 } /* Name.Builtin */ .nb { color: #f8f8f2; } /* Name.Builtin */
.nc { color: #a6e22e } /* Name.Class */ .nc { color: #a6e22e; } /* Name.Class */
.no { color: #66d9ef } /* Name.Constant */ .no { color: #66d9ef; } /* Name.Constant */
.nd { color: #a6e22e } /* Name.Decorator */ .nd { color: #a6e22e; } /* Name.Decorator */
.ni { color: #f8f8f2 } /* Name.Entity */ .ni { color: #f8f8f2; } /* Name.Entity */
.ne { color: #a6e22e } /* Name.Exception */ .ne { color: #a6e22e; } /* Name.Exception */
.nf { color: #a6e22e } /* Name.Function */ .nf { color: #a6e22e; } /* Name.Function */
.nl { color: #f8f8f2 } /* Name.Label */ .nl { color: #f8f8f2; } /* Name.Label */
.nn { color: #f8f8f2 } /* Name.Namespace */ .nn { color: #f8f8f2; } /* Name.Namespace */
.nx { color: #a6e22e } /* Name.Other */ .nx { color: #a6e22e; } /* Name.Other */
.py { color: #f8f8f2 } /* Name.Property */ .py { color: #f8f8f2; } /* Name.Property */
.nt { color: #f92672 } /* Name.Tag */ .nt { color: #f92672; } /* Name.Tag */
.nv { color: #f8f8f2 } /* Name.Variable */ .nv { color: #f8f8f2; } /* Name.Variable */
.ow { color: #f92672 } /* Operator.Word */ .ow { color: #f92672; } /* Operator.Word */
.w { color: #f8f8f2 } /* Text.Whitespace */ .w { color: #f8f8f2; } /* Text.Whitespace */
.mf { color: #ae81ff } /* Literal.Number.Float */ .mf { color: #ae81ff; } /* Literal.Number.Float */
.mh { color: #ae81ff } /* Literal.Number.Hex */ .mh { color: #ae81ff; } /* Literal.Number.Hex */
.mi { color: #ae81ff } /* Literal.Number.Integer */ .mi { color: #ae81ff; } /* Literal.Number.Integer */
.mo { color: #ae81ff } /* Literal.Number.Oct */ .mo { color: #ae81ff; } /* Literal.Number.Oct */
.sb { color: #e6db74 } /* Literal.String.Backtick */ .sb { color: #e6db74; } /* Literal.String.Backtick */
.sc { color: #e6db74 } /* Literal.String.Char */ .sc { color: #e6db74; } /* Literal.String.Char */
.sd { color: #e6db74 } /* Literal.String.Doc */ .sd { color: #e6db74; } /* Literal.String.Doc */
.s2 { color: #e6db74 } /* Literal.String.Double */ .s2 { color: #e6db74; } /* Literal.String.Double */
.se { color: #ae81ff } /* Literal.String.Escape */ .se { color: #ae81ff; } /* Literal.String.Escape */
.sh { color: #e6db74 } /* Literal.String.Heredoc */ .sh { color: #e6db74; } /* Literal.String.Heredoc */
.si { color: #e6db74 } /* Literal.String.Interpol */ .si { color: #e6db74; } /* Literal.String.Interpol */
.sx { color: #e6db74 } /* Literal.String.Other */ .sx { color: #e6db74; } /* Literal.String.Other */
.sr { color: #e6db74 } /* Literal.String.Regex */ .sr { color: #e6db74; } /* Literal.String.Regex */
.s1 { color: #e6db74 } /* Literal.String.Single */ .s1 { color: #e6db74; } /* Literal.String.Single */
.ss { color: #e6db74 } /* Literal.String.Symbol */ .ss { color: #e6db74; } /* Literal.String.Symbol */
.bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .bp { color: #f8f8f2; } /* Name.Builtin.Pseudo */
.vc { color: #f8f8f2 } /* Name.Variable.Class */ .vc { color: #f8f8f2; } /* Name.Variable.Class */
.vg { color: #f8f8f2 } /* Name.Variable.Global */ .vg { color: #f8f8f2; } /* Name.Variable.Global */
.vi { color: #f8f8f2 } /* Name.Variable.Instance */ .vi { color: #f8f8f2; } /* Name.Variable.Instance */
.il { color: #ae81ff } /* Literal.Number.Integer.Long */ .il { color: #ae81ff; } /* Literal.Number.Integer.Long */
.gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
.gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */ .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */
.gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */ .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */
......
...@@ -72,72 +72,72 @@ ...@@ -72,72 +72,72 @@
green #859900 operators, other keywords green #859900 operators, other keywords
*/ */
.c { color: #586e75 } /* Comment */ .c { color: #586e75; } /* Comment */
.err { color: #93a1a1 } /* Error */ .err { color: #93a1a1; } /* Error */
.g { color: #93a1a1 } /* Generic */ .g { color: #93a1a1; } /* Generic */
.k { color: #859900 } /* Keyword */ .k { color: #859900; } /* Keyword */
.l { color: #93a1a1 } /* Literal */ .l { color: #93a1a1; } /* Literal */
.n { color: #93a1a1 } /* Name */ .n { color: #93a1a1; } /* Name */
.o { color: #859900 } /* Operator */ .o { color: #859900; } /* Operator */
.x { color: #cb4b16 } /* Other */ .x { color: #cb4b16; } /* Other */
.p { color: #93a1a1 } /* Punctuation */ .p { color: #93a1a1; } /* Punctuation */
.cm { color: #586e75 } /* Comment.Multiline */ .cm { color: #586e75; } /* Comment.Multiline */
.cp { color: #859900 } /* Comment.Preproc */ .cp { color: #859900; } /* Comment.Preproc */
.c1 { color: #586e75 } /* Comment.Single */ .c1 { color: #586e75; } /* Comment.Single */
.cs { color: #859900 } /* Comment.Special */ .cs { color: #859900; } /* Comment.Special */
.gd { color: #2aa198 } /* Generic.Deleted */ .gd { color: #2aa198; } /* Generic.Deleted */
.ge { color: #93a1a1; font-style: italic } /* Generic.Emph */ .ge { color: #93a1a1; font-style: italic; } /* Generic.Emph */
.gr { color: #dc322f } /* Generic.Error */ .gr { color: #dc322f; } /* Generic.Error */
.gh { color: #cb4b16 } /* Generic.Heading */ .gh { color: #cb4b16; } /* Generic.Heading */
.gi { color: #859900 } /* Generic.Inserted */ .gi { color: #859900; } /* Generic.Inserted */
.go { color: #93a1a1 } /* Generic.Output */ .go { color: #93a1a1; } /* Generic.Output */
.gp { color: #93a1a1 } /* Generic.Prompt */ .gp { color: #93a1a1; } /* Generic.Prompt */
.gs { color: #93a1a1; font-weight: bold } /* Generic.Strong */ .gs { color: #93a1a1; font-weight: bold; } /* Generic.Strong */
.gu { color: #cb4b16 } /* Generic.Subheading */ .gu { color: #cb4b16; } /* Generic.Subheading */
.gt { color: #93a1a1 } /* Generic.Traceback */ .gt { color: #93a1a1; } /* Generic.Traceback */
.kc { color: #cb4b16 } /* Keyword.Constant */ .kc { color: #cb4b16; } /* Keyword.Constant */
.kd { color: #268bd2 } /* Keyword.Declaration */ .kd { color: #268bd2; } /* Keyword.Declaration */
.kn { color: #859900 } /* Keyword.Namespace */ .kn { color: #859900; } /* Keyword.Namespace */
.kp { color: #859900 } /* Keyword.Pseudo */ .kp { color: #859900; } /* Keyword.Pseudo */
.kr { color: #268bd2 } /* Keyword.Reserved */ .kr { color: #268bd2; } /* Keyword.Reserved */
.kt { color: #dc322f } /* Keyword.Type */ .kt { color: #dc322f; } /* Keyword.Type */
.ld { color: #93a1a1 } /* Literal.Date */ .ld { color: #93a1a1; } /* Literal.Date */
.m { color: #2aa198 } /* Literal.Number */ .m { color: #2aa198; } /* Literal.Number */
.s { color: #2aa198 } /* Literal.String */ .s { color: #2aa198; } /* Literal.String */
.na { color: #93a1a1 } /* Name.Attribute */ .na { color: #93a1a1; } /* Name.Attribute */
.nb { color: #b58900 } /* Name.Builtin */ .nb { color: #b58900; } /* Name.Builtin */
.nc { color: #268bd2 } /* Name.Class */ .nc { color: #268bd2; } /* Name.Class */
.no { color: #cb4b16 } /* Name.Constant */ .no { color: #cb4b16; } /* Name.Constant */
.nd { color: #268bd2 } /* Name.Decorator */ .nd { color: #268bd2; } /* Name.Decorator */
.ni { color: #cb4b16 } /* Name.Entity */ .ni { color: #cb4b16; } /* Name.Entity */
.ne { color: #cb4b16 } /* Name.Exception */ .ne { color: #cb4b16; } /* Name.Exception */
.nf { color: #268bd2 } /* Name.Function */ .nf { color: #268bd2; } /* Name.Function */
.nl { color: #93a1a1 } /* Name.Label */ .nl { color: #93a1a1; } /* Name.Label */
.nn { color: #93a1a1 } /* Name.Namespace */ .nn { color: #93a1a1; } /* Name.Namespace */
.nx { color: #93a1a1 } /* Name.Other */ .nx { color: #93a1a1; } /* Name.Other */
.py { color: #93a1a1 } /* Name.Property */ .py { color: #93a1a1; } /* Name.Property */
.nt { color: #268bd2 } /* Name.Tag */ .nt { color: #268bd2; } /* Name.Tag */
.nv { color: #268bd2 } /* Name.Variable */ .nv { color: #268bd2; } /* Name.Variable */
.ow { color: #859900 } /* Operator.Word */ .ow { color: #859900; } /* Operator.Word */
.w { color: #93a1a1 } /* Text.Whitespace */ .w { color: #93a1a1; } /* Text.Whitespace */
.mf { color: #2aa198 } /* Literal.Number.Float */ .mf { color: #2aa198; } /* Literal.Number.Float */
.mh { color: #2aa198 } /* Literal.Number.Hex */ .mh { color: #2aa198; } /* Literal.Number.Hex */
.mi { color: #2aa198 } /* Literal.Number.Integer */ .mi { color: #2aa198; } /* Literal.Number.Integer */
.mo { color: #2aa198 } /* Literal.Number.Oct */ .mo { color: #2aa198; } /* Literal.Number.Oct */
.sb { color: #586e75 } /* Literal.String.Backtick */ .sb { color: #586e75; } /* Literal.String.Backtick */
.sc { color: #2aa198 } /* Literal.String.Char */ .sc { color: #2aa198; } /* Literal.String.Char */
.sd { color: #93a1a1 } /* Literal.String.Doc */ .sd { color: #93a1a1; } /* Literal.String.Doc */
.s2 { color: #2aa198 } /* Literal.String.Double */ .s2 { color: #2aa198; } /* Literal.String.Double */
.se { color: #cb4b16 } /* Literal.String.Escape */ .se { color: #cb4b16; } /* Literal.String.Escape */
.sh { color: #93a1a1 } /* Literal.String.Heredoc */ .sh { color: #93a1a1; } /* Literal.String.Heredoc */
.si { color: #2aa198 } /* Literal.String.Interpol */ .si { color: #2aa198; } /* Literal.String.Interpol */
.sx { color: #2aa198 } /* Literal.String.Other */ .sx { color: #2aa198; } /* Literal.String.Other */
.sr { color: #dc322f } /* Literal.String.Regex */ .sr { color: #dc322f; } /* Literal.String.Regex */
.s1 { color: #2aa198 } /* Literal.String.Single */ .s1 { color: #2aa198; } /* Literal.String.Single */
.ss { color: #2aa198 } /* Literal.String.Symbol */ .ss { color: #2aa198; } /* Literal.String.Symbol */
.bp { color: #268bd2 } /* Name.Builtin.Pseudo */ .bp { color: #268bd2; } /* Name.Builtin.Pseudo */
.vc { color: #268bd2 } /* Name.Variable.Class */ .vc { color: #268bd2; } /* Name.Variable.Class */
.vg { color: #268bd2 } /* Name.Variable.Global */ .vg { color: #268bd2; } /* Name.Variable.Global */
.vi { color: #268bd2 } /* Name.Variable.Instance */ .vi { color: #268bd2; } /* Name.Variable.Instance */
.il { color: #2aa198 } /* Literal.Number.Integer.Long */ .il { color: #2aa198; } /* Literal.Number.Integer.Long */
} }
...@@ -78,72 +78,72 @@ ...@@ -78,72 +78,72 @@
green #859900 operators, other keywords green #859900 operators, other keywords
*/ */
.c { color: #93a1a1 } /* Comment */ .c { color: #93a1a1; } /* Comment */
.err { color: #586e75 } /* Error */ .err { color: #586e75; } /* Error */
.g { color: #586e75 } /* Generic */ .g { color: #586e75; } /* Generic */
.k { color: #859900 } /* Keyword */ .k { color: #859900; } /* Keyword */
.l { color: #586e75 } /* Literal */ .l { color: #586e75; } /* Literal */
.n { color: #586e75 } /* Name */ .n { color: #586e75; } /* Name */
.o { color: #859900 } /* Operator */ .o { color: #859900; } /* Operator */
.x { color: #cb4b16 } /* Other */ .x { color: #cb4b16; } /* Other */
.p { color: #586e75 } /* Punctuation */ .p { color: #586e75; } /* Punctuation */
.cm { color: #93a1a1 } /* Comment.Multiline */ .cm { color: #93a1a1; } /* Comment.Multiline */
.cp { color: #859900 } /* Comment.Preproc */ .cp { color: #859900; } /* Comment.Preproc */
.c1 { color: #93a1a1 } /* Comment.Single */ .c1 { color: #93a1a1; } /* Comment.Single */
.cs { color: #859900 } /* Comment.Special */ .cs { color: #859900; } /* Comment.Special */
.gd { color: #2aa198 } /* Generic.Deleted */ .gd { color: #2aa198; } /* Generic.Deleted */
.ge { color: #586e75; font-style: italic } /* Generic.Emph */ .ge { color: #586e75; font-style: italic; } /* Generic.Emph */
.gr { color: #dc322f } /* Generic.Error */ .gr { color: #dc322f; } /* Generic.Error */
.gh { color: #cb4b16 } /* Generic.Heading */ .gh { color: #cb4b16; } /* Generic.Heading */
.gi { color: #859900 } /* Generic.Inserted */ .gi { color: #859900; } /* Generic.Inserted */
.go { color: #586e75 } /* Generic.Output */ .go { color: #586e75; } /* Generic.Output */
.gp { color: #586e75 } /* Generic.Prompt */ .gp { color: #586e75; } /* Generic.Prompt */
.gs { color: #586e75; font-weight: bold } /* Generic.Strong */ .gs { color: #586e75; font-weight: bold; } /* Generic.Strong */
.gu { color: #cb4b16 } /* Generic.Subheading */ .gu { color: #cb4b16; } /* Generic.Subheading */
.gt { color: #586e75 } /* Generic.Traceback */ .gt { color: #586e75; } /* Generic.Traceback */
.kc { color: #cb4b16 } /* Keyword.Constant */ .kc { color: #cb4b16; } /* Keyword.Constant */
.kd { color: #268bd2 } /* Keyword.Declaration */ .kd { color: #268bd2; } /* Keyword.Declaration */
.kn { color: #859900 } /* Keyword.Namespace */ .kn { color: #859900; } /* Keyword.Namespace */
.kp { color: #859900 } /* Keyword.Pseudo */ .kp { color: #859900; } /* Keyword.Pseudo */
.kr { color: #268bd2 } /* Keyword.Reserved */ .kr { color: #268bd2; } /* Keyword.Reserved */
.kt { color: #dc322f } /* Keyword.Type */ .kt { color: #dc322f; } /* Keyword.Type */
.ld { color: #586e75 } /* Literal.Date */ .ld { color: #586e75; } /* Literal.Date */
.m { color: #2aa198 } /* Literal.Number */ .m { color: #2aa198; } /* Literal.Number */
.s { color: #2aa198 } /* Literal.String */ .s { color: #2aa198; } /* Literal.String */
.na { color: #586e75 } /* Name.Attribute */ .na { color: #586e75; } /* Name.Attribute */
.nb { color: #b58900 } /* Name.Builtin */ .nb { color: #b58900; } /* Name.Builtin */
.nc { color: #268bd2 } /* Name.Class */ .nc { color: #268bd2; } /* Name.Class */
.no { color: #cb4b16 } /* Name.Constant */ .no { color: #cb4b16; } /* Name.Constant */
.nd { color: #268bd2 } /* Name.Decorator */ .nd { color: #268bd2; } /* Name.Decorator */
.ni { color: #cb4b16 } /* Name.Entity */ .ni { color: #cb4b16; } /* Name.Entity */
.ne { color: #cb4b16 } /* Name.Exception */ .ne { color: #cb4b16; } /* Name.Exception */
.nf { color: #268bd2 } /* Name.Function */ .nf { color: #268bd2; } /* Name.Function */
.nl { color: #586e75 } /* Name.Label */ .nl { color: #586e75; } /* Name.Label */
.nn { color: #586e75 } /* Name.Namespace */ .nn { color: #586e75; } /* Name.Namespace */
.nx { color: #586e75 } /* Name.Other */ .nx { color: #586e75; } /* Name.Other */
.py { color: #586e75 } /* Name.Property */ .py { color: #586e75; } /* Name.Property */
.nt { color: #268bd2 } /* Name.Tag */ .nt { color: #268bd2; } /* Name.Tag */
.nv { color: #268bd2 } /* Name.Variable */ .nv { color: #268bd2; } /* Name.Variable */
.ow { color: #859900 } /* Operator.Word */ .ow { color: #859900; } /* Operator.Word */
.w { color: #586e75 } /* Text.Whitespace */ .w { color: #586e75; } /* Text.Whitespace */
.mf { color: #2aa198 } /* Literal.Number.Float */ .mf { color: #2aa198; } /* Literal.Number.Float */
.mh { color: #2aa198 } /* Literal.Number.Hex */ .mh { color: #2aa198; } /* Literal.Number.Hex */
.mi { color: #2aa198 } /* Literal.Number.Integer */ .mi { color: #2aa198; } /* Literal.Number.Integer */
.mo { color: #2aa198 } /* Literal.Number.Oct */ .mo { color: #2aa198; } /* Literal.Number.Oct */
.sb { color: #93a1a1 } /* Literal.String.Backtick */ .sb { color: #93a1a1; } /* Literal.String.Backtick */
.sc { color: #2aa198 } /* Literal.String.Char */ .sc { color: #2aa198; } /* Literal.String.Char */
.sd { color: #586e75 } /* Literal.String.Doc */ .sd { color: #586e75; } /* Literal.String.Doc */
.s2 { color: #2aa198 } /* Literal.String.Double */ .s2 { color: #2aa198; } /* Literal.String.Double */
.se { color: #cb4b16 } /* Literal.String.Escape */ .se { color: #cb4b16; } /* Literal.String.Escape */
.sh { color: #586e75 } /* Literal.String.Heredoc */ .sh { color: #586e75; } /* Literal.String.Heredoc */
.si { color: #2aa198 } /* Literal.String.Interpol */ .si { color: #2aa198; } /* Literal.String.Interpol */
.sx { color: #2aa198 } /* Literal.String.Other */ .sx { color: #2aa198; } /* Literal.String.Other */
.sr { color: #dc322f } /* Literal.String.Regex */ .sr { color: #dc322f; } /* Literal.String.Regex */
.s1 { color: #2aa198 } /* Literal.String.Single */ .s1 { color: #2aa198; } /* Literal.String.Single */
.ss { color: #2aa198 } /* Literal.String.Symbol */ .ss { color: #2aa198; } /* Literal.String.Symbol */
.bp { color: #268bd2 } /* Name.Builtin.Pseudo */ .bp { color: #268bd2; } /* Name.Builtin.Pseudo */
.vc { color: #268bd2 } /* Name.Variable.Class */ .vc { color: #268bd2; } /* Name.Variable.Class */
.vg { color: #268bd2 } /* Name.Variable.Global */ .vg { color: #268bd2; } /* Name.Variable.Global */
.vi { color: #268bd2 } /* Name.Variable.Instance */ .vi { color: #268bd2; } /* Name.Variable.Instance */
.il { color: #2aa198 } /* Literal.Number.Integer.Long */ .il { color: #2aa198; } /* Literal.Number.Integer.Long */
} }
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
background-color: #fafe3d !important; background-color: #fafe3d !important;
} }
.hll { background-color: #f8f8f8 } .hll { background-color: #f8f8f8; }
.c { color: #998; font-style: italic; } .c { color: #998; font-style: italic; }
.err { color: #a61717; background-color: #e3d2d2; } .err { color: #a61717; background-color: #e3d2d2; }
.k { font-weight: bold; } .k { font-weight: bold; }
......
...@@ -78,7 +78,7 @@ span.highlight_word { ...@@ -78,7 +78,7 @@ span.highlight_word {
background-color: #fafe3d !important; background-color: #fafe3d !important;
} }
.hll { background-color: #f8f8f8 } .hll { background-color: #f8f8f8; }
.c { color: #998; font-style: italic; } .c { color: #998; font-style: italic; }
.err { color: #a61717; background-color: #e3d2d2; } .err { color: #a61717; background-color: #e3d2d2; }
.k { font-weight: bold; } .k { font-weight: bold; }
......
...@@ -2,22 +2,28 @@ img { ...@@ -2,22 +2,28 @@ img {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
} }
p.details { p.details {
font-style: italic; font-style: italic;
color: #777 color: #777;
} }
.footer > p { .footer > p {
font-size: small; font-size: small;
color: #777 color: #777;
} }
pre.commit-message { pre.commit-message {
white-space: pre-wrap; white-space: pre-wrap;
} }
.file-stats > a { .file-stats > a {
text-decoration: none; text-decoration: none;
> .new-file { > .new-file {
color: #090; color: #090;
} }
> .deleted-file { > .deleted-file {
color: #b00; color: #b00;
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
.admin-filter form { .admin-filter form {
.select2-container { .select2-container {
width: 100% width: 100%;
} }
.controls { .controls {
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
.form-actions { .form-actions {
padding-left: 130px; padding-left: 130px;
background: #fff background: #fff;
} }
.visibility-levels { .visibility-levels {
...@@ -106,26 +106,33 @@ ...@@ -106,26 +106,33 @@
.table { .table {
table-layout: fixed; table-layout: fixed;
} }
.subheading { .subheading {
padding-bottom: $gl-padding; padding-bottom: $gl-padding;
} }
.message { .message {
word-wrap: break-word; word-wrap: break-word;
} }
.btn { .btn {
white-space: normal; white-space: normal;
padding: $gl-btn-padding; padding: $gl-btn-padding;
} }
th { th {
width: 15%; width: 15%;
&.wide { &.wide {
width: 55%; width: 55%;
} }
} }
@media (max-width: $screen-sm-max) { @media (max-width: $screen-sm-max) {
th { th {
width: 100%; width: 100%;
} }
td { td {
width: 100%; width: 100%;
float: left; float: left;
...@@ -137,6 +144,7 @@ ...@@ -137,6 +144,7 @@
margin-left: $btn-side-margin; margin-left: $btn-side-margin;
margin-top: 3px; margin-top: 3px;
} }
span { span {
font-size: 19px; font-size: 19px;
} }
......
...@@ -137,6 +137,7 @@ ...@@ -137,6 +137,7 @@
.retry-link { .retry-link {
color: $gl-link-color; color: $gl-link-color;
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
...@@ -218,6 +219,7 @@ ...@@ -218,6 +219,7 @@
.build-detail-row { .build-detail-row {
margin-bottom: 5px; margin-bottom: 5px;
&:last-of-type { &:last-of-type {
margin-bottom: 0; margin-bottom: 0;
} }
...@@ -233,3 +235,9 @@ ...@@ -233,3 +235,9 @@
right: 0; right: 0;
margin-top: -17px; margin-top: -17px;
} }
@media (min-width: $screen-md-min) {
.sub-nav.build {
width: calc(100% + #{$gutter_width});
}
}
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
margin-left: 4px; margin-left: 4px;
} }
} }
.commit-committer-link, .commit-committer-link,
.commit-author-link { .commit-author-link {
color: $gl-gray; color: $gl-gray;
...@@ -108,21 +109,25 @@ ...@@ -108,21 +109,25 @@
line-height: 20px; line-height: 20px;
} }
} }
.new-file { .new-file {
a { a {
color: $gl-text-green; color: $gl-text-green;
} }
} }
.renamed-file { .renamed-file {
a { a {
color: $gl-text-orange; color: $gl-text-orange;
} }
} }
.deleted-file { .deleted-file {
a { a {
color: $gl-text-red; color: $gl-text-red;
} }
} }
.edit-file { .edit-file {
a { a {
color: $gl-text-color; color: $gl-text-color;
...@@ -158,6 +163,7 @@ ...@@ -158,6 +163,7 @@
position: absolute; position: absolute;
z-index: 1; z-index: 1;
} }
> textarea { > textarea {
background-color: rgba(0, 0, 0, 0.0); background-color: rgba(0, 0, 0, 0.0);
font-family: inherit; font-family: inherit;
......
...@@ -161,6 +161,7 @@ ...@@ -161,6 +161,7 @@
.branch-commit { .branch-commit {
color: $gl-gray; color: $gl-gray;
.commit-id, .commit-row-message { .commit-id, .commit-row-message {
color: $gl-gray; color: $gl-gray;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
background: $background-color; background: $background-color;
border-top-left-radius: 0; border-top-left-radius: 0;
} }
border-top-left-radius: 0; border-top-left-radius: 0;
} }
} }
...@@ -17,6 +18,7 @@ ...@@ -17,6 +18,7 @@
float: left; float: left;
@extend .col-md-2; @extend .col-md-2;
} }
.btn { .btn {
margin-left: 5px; margin-left: 5px;
float: left; float: left;
......
...@@ -33,6 +33,19 @@ ...@@ -33,6 +33,19 @@
font-size: smaller; font-size: smaller;
} }
} }
.file-title {
cursor: pointer;
&:hover {
background-color: $dark-background-color;
}
.diff-toggle-caret {
padding-right: 6px;
}
}
.diff-content { .diff-content {
overflow: auto; overflow: auto;
overflow-y: hidden; overflow-y: hidden;
...@@ -123,15 +136,18 @@ ...@@ -123,15 +136,18 @@
max-width: 50px; max-width: 50px;
width: 35px; width: 35px;
@include user-select(none); @include user-select(none);
a { a {
float: left; float: left;
width: 35px; width: 35px;
font-weight: normal; font-weight: normal;
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
} }
} }
.line_content { .line_content {
display: block; display: block;
margin: 0; margin: 0;
...@@ -151,10 +167,12 @@ ...@@ -151,10 +167,12 @@
white-space: pre-wrap; white-space: pre-wrap;
} }
} }
.image { .image {
background: #ddd; background: #ddd;
text-align: center; text-align: center;
padding: 30px; padding: 30px;
.wrap { .wrap {
display: inline-block; display: inline-block;
} }
...@@ -163,6 +181,7 @@ ...@@ -163,6 +181,7 @@
display: inline-block; display: inline-block;
background-color: #fff; background-color: #fff;
line-height: 0; line-height: 0;
img { img {
border: 1px solid #fff; border: 1px solid #fff;
background-image: linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%), background-image: linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%),
...@@ -171,6 +190,7 @@ ...@@ -171,6 +190,7 @@
background-position: 0 0, 5px 5px; background-position: 0 0, 5px 5px;
max-width: 100%; max-width: 100%;
} }
&.deleted { &.deleted {
border: 1px solid $deleted; border: 1px solid $deleted;
} }
...@@ -179,6 +199,7 @@ ...@@ -179,6 +199,7 @@
border: 1px solid $added; border: 1px solid $added;
} }
} }
.image-info { .image-info {
font-size: 12px; font-size: 12px;
margin: 5px 0 0; margin: 5px 0 0;
...@@ -193,6 +214,7 @@ ...@@ -193,6 +214,7 @@
margin: auto; margin: auto;
position: relative; position: relative;
} }
.swipe-wrap { .swipe-wrap {
overflow: hidden; overflow: hidden;
border-left: 1px solid #999; border-left: 1px solid #999;
...@@ -201,10 +223,12 @@ ...@@ -201,10 +223,12 @@
top: 13px; top: 13px;
right: 7px; right: 7px;
} }
.frame { .frame {
top: 0; top: 0;
right: 0; right: 0;
position: absolute; position: absolute;
&.deleted { &.deleted {
margin: 0; margin: 0;
display: block; display: block;
...@@ -212,6 +236,7 @@ ...@@ -212,6 +236,7 @@
right: 7px; right: 7px;
} }
} }
.swipe-bar { .swipe-bar {
display: block; display: block;
height: 100%; height: 100%;
...@@ -219,14 +244,17 @@ ...@@ -219,14 +244,17 @@
z-index: 100; z-index: 100;
position: absolute; position: absolute;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
.top-handle { .top-handle {
background-position: -15px 3px; background-position: -15px 3px;
} }
.bottom-handle { .bottom-handle {
background-position: -15px -11px; background-position: -15px -11px;
} }
} }
.top-handle { .top-handle {
display: block; display: block;
height: 14px; height: 14px;
...@@ -235,6 +263,7 @@ ...@@ -235,6 +263,7 @@
top: 0; top: 0;
background: image-url('swipemode_sprites.gif') 0 3px no-repeat; background: image-url('swipemode_sprites.gif') 0 3px no-repeat;
} }
.bottom-handle { .bottom-handle {
display: block; display: block;
height: 14px; height: 14px;
...@@ -252,12 +281,14 @@ ...@@ -252,12 +281,14 @@
margin: auto; margin: auto;
position: relative; position: relative;
} }
.frame.added, .frame.deleted { .frame.added, .frame.deleted {
position: absolute; position: absolute;
display: block; display: block;
top: 0; top: 0;
left: 0; left: 0;
} }
.controls { .controls {
display: block; display: block;
height: 14px; height: 14px;
...@@ -311,6 +342,7 @@ ...@@ -311,6 +342,7 @@
} }
//.view.onion-skin //.view.onion-skin
} }
.view-modes { .view-modes {
padding: 10px; padding: 10px;
text-align: center; text-align: center;
...@@ -328,19 +360,24 @@ ...@@ -328,19 +360,24 @@
border-left: 1px solid #c1c1c1; border-left: 1px solid #c1c1c1;
padding: 0 12px 0 16px; padding: 0 12px 0 16px;
cursor: pointer; cursor: pointer;
&:first-child { &:first-child {
border-left: none; border-left: none;
} }
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
&.active { &.active {
&:hover { &:hover {
text-decoration: none; text-decoration: none;
} }
cursor: default; cursor: default;
color: #333; color: #333;
} }
&.disabled { &.disabled {
display: none; display: none;
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
.cancel-btn { .cancel-btn {
color: #b94a48; color: #b94a48;
&:hover { &:hover {
color: #b94a48; color: #b94a48;
} }
...@@ -70,16 +71,20 @@ ...@@ -70,16 +71,20 @@
.soft-wrap-toggle { .soft-wrap-toggle {
margin: 0 $btn-side-margin; margin: 0 $btn-side-margin;
.soft-wrap { .soft-wrap {
display: block; display: block;
} }
.no-wrap { .no-wrap {
display: none; display: none;
} }
&.soft-wrap-active { &.soft-wrap-active {
.soft-wrap { .soft-wrap {
display: none; display: none;
} }
.no-wrap { .no-wrap {
display: block; display: block;
} }
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
} }
} }
.table.builds.environments { .table.ci-table.environments {
.icon-container { .icon-container {
width: 20px; width: 20px;
......
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
margin-bottom: 0; margin-bottom: 0;
} }
} }
.event-note-icon { .event-note-icon {
color: #777; color: #777;
float: left; float: left;
...@@ -86,6 +87,7 @@ ...@@ -86,6 +87,7 @@
margin-right: 5px; margin-right: 5px;
} }
} }
.event_icon { .event_icon {
position: relative; position: relative;
float: right; float: right;
...@@ -95,12 +97,13 @@ ...@@ -95,12 +97,13 @@
background: $gray-light; background: $gray-light;
margin-left: 10px; margin-left: 10px;
top: -6px; top: -6px;
img { img {
width: 20px; width: 20px;
} }
} }
&:last-child { border: none } &:last-child { border: none; }
.event_commits { .event_commits {
li { li {
...@@ -109,6 +112,7 @@ ...@@ -109,6 +112,7 @@
padding: 3px; padding: 3px;
padding-left: 0; padding-left: 0;
border: none; border: none;
.commit-row-title { .commit-row-title {
font-size: $gl-font-size; font-size: $gl-font-size;
} }
...@@ -117,6 +121,7 @@ ...@@ -117,6 +121,7 @@
&.commits-stat { &.commits-stat {
display: block; display: block;
padding: 0 3px 0 0; padding: 0 3px 0 0;
&:hover { &:hover {
background: none; background: none;
} }
...@@ -158,6 +163,7 @@ ...@@ -158,6 +163,7 @@
overflow: visible; overflow: visible;
max-width: 100%; max-width: 100%;
} }
.avatar { .avatar {
display: none; display: none;
} }
......
.member-search-form {
float: left;
input[type='search'] {
width: 225px;
vertical-align: bottom;
@media (max-width: $screen-xs-max) {
width: 100px;
vertical-align: bottom;
}
}
}
.milestone-row { .milestone-row {
@include str-truncated(90%); @include str-truncated(90%);
} }
...@@ -48,6 +34,7 @@ ...@@ -48,6 +34,7 @@
.group-right-buttons { .group-right-buttons {
position: absolute; position: absolute;
right: 16px; right: 16px;
.btn { .btn {
@include btn-gray; @include btn-gray;
padding: 3px 10px; padding: 3px 10px;
......
...@@ -23,28 +23,28 @@ ...@@ -23,28 +23,28 @@
color: #555; color: #555;
tbody:first-child tr:first-child { tbody:first-child tr:first-child {
padding-top: 0 padding-top: 0;
} }
th { th {
padding-top: 15px; padding-top: 15px;
line-height: 1.5; line-height: 1.5;
color: #333; color: #333;
text-align: left text-align: left;
} }
td { td {
padding-top: 3px; padding-top: 3px;
padding-bottom: 3px; padding-bottom: 3px;
vertical-align: top; vertical-align: top;
line-height: 20px line-height: 20px;
} }
.shortcut { .shortcut {
padding-right: 10px; padding-right: 10px;
color: #999; color: #999;
text-align: right; text-align: right;
white-space: nowrap white-space: nowrap;
} }
.key { .key {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
margin-right: 5px; margin-right: 5px;
margin-bottom: 5px; margin-bottom: 5px;
display: inline-block; display: inline-block;
.color-label { .color-label {
padding: 6px 10px; padding: 6px 10px;
} }
...@@ -128,7 +129,7 @@ ...@@ -128,7 +129,7 @@
} }
.selectbox { .selectbox {
display: none display: none;
} }
.btn-clipboard { .btn-clipboard {
...@@ -199,7 +200,7 @@ ...@@ -199,7 +200,7 @@
display: none; display: none;
/* Small devices (tablets, 768px and up) */ /* Small devices (tablets, 768px and up) */
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
display: block display: block;
} }
width: $sidebar_collapsed_width; width: $sidebar_collapsed_width;
...@@ -276,7 +277,7 @@ ...@@ -276,7 +277,7 @@
} }
&.btn-primary { &.btn-primary {
@extend .btn-primary @extend .btn-primary;
} }
} }
...@@ -400,6 +401,7 @@ ...@@ -400,6 +401,7 @@
.js-issuable-selector { .js-issuable-selector {
width: 100%; width: 100%;
} }
@media (max-width: $screen-sm-max) { @media (max-width: $screen-sm-max) {
margin-bottom: $gl-padding; margin-bottom: $gl-padding;
} }
......
...@@ -37,6 +37,7 @@ ul.related-merge-requests > li { ...@@ -37,6 +37,7 @@ ul.related-merge-requests > li {
display: -ms-flexbox; display: -ms-flexbox;
display: -webkit-flex; display: -webkit-flex;
display: flex; display: flex;
.merge-request-id { .merge-request-id {
flex-shrink: 0; flex-shrink: 0;
} }
......
.suggest-colors { .suggest-colors {
margin-top: 5px; margin-top: 5px;
a { a {
border-radius: 4px; border-radius: 4px;
width: 30px; width: 30px;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
font-size: 19px; font-size: 19px;
color: red; color: red;
} }
.correct-syntax { .correct-syntax {
font-size: 19px; font-size: 19px;
color: #47a447; color: #47a447;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
line-height: 1.5; line-height: 1.5;
p { p {
font-size: 18px;
color: #888; color: #888;
} }
...@@ -36,10 +37,14 @@ ...@@ -36,10 +37,14 @@
} }
} }
.login-box { p {
background: #fafafa; font-size: 13px;
border-radius: 10px; }
box-shadow: 0 0 2px #ccc;
.login-box, .omniauth-container {
box-shadow: 0 0 0 1px $border-color;
border-bottom-right-radius: 2px;
border-bottom-left-radius: 2px;
padding: 15px; padding: 15px;
.login-heading h3 { .login-heading h3 {
...@@ -58,42 +63,127 @@ ...@@ -58,42 +63,127 @@
a.forgot { a.forgot {
float: right; float: right;
padding-top: 6px padding-top: 6px;
} }
.nav .active a { .nav .active a {
background: transparent; background: transparent;
} }
// Styles the glowing border of focused input for username async validation
.login-body {
font-size: 13px;
input + p {
margin-top: 5px;
} }
.form-control { .gl-field-success-outline {
font-size: 14px; border: 1px solid $green-normal;
padding: 10px 8px;
width: 100%;
height: auto;
&.top { &:focus {
border-radius: 5px 5px 0 0; box-shadow: 0 0 0 1px $green-normal inset, 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 4px 0 $green-normal;
margin-bottom: 0; border: 0 none;
}
} }
&.bottom { .gl-field-error-outline {
border-radius: 0 0 5px 5px; border: 1px solid $red-normal;
border-top: 0;
margin-bottom: 20px; &:focus {
box-shadow: 0 0 0 1px $red-normal inset, 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 4px 0 rgba(210, 40, 82, 0.6);
border: 0 none;
}
} }
&.middle { .username .validation-success,
border-top: 0; .gl-field-success-message {
margin-bottom: 0; color: $green-normal;
border-radius: 0; }
.username .validation-error,
.gl-field-error-message {
color: $red-normal;
}
.gl-field-hint {
color: $gl-text-color;
} }
}
}
.omniauth-container {
p {
margin: 0;
}
}
.new-session-tabs {
display: -webkit-flex;
display: flex;
box-shadow: 0 0 0 1px $border-color;
border-top-right-radius: 2px;
border-top-left-radius: 2px;
li {
flex: 1;
text-align: center;
&:last-of-type {
border-left: 1px solid $border-color;
}
&:not(.active) {
background-color: $gray-light;
}
a {
width: 100%;
font-size: 18px;
&:hover {
border: 1px solid transparent;
}
}
&.active {
border-bottom: 1px solid $border-color;
a {
border: none;
border-bottom: 2px solid $link-underline-blue;
color: $black;
&:hover {
border-bottom: 2px solid $link-underline-blue;
}
}
}
}
}
.form-control {
&:active, &:focus { &:active, &:focus {
background-color: #fff; background-color: #fff;
} }
} }
label {
font-weight: normal;
}
.submit-container {
margin-top: 16px;
}
input[type="submit"] {
@extend .btn-block;
margin-bottom: 0;
}
.devise-errors { .devise-errors {
h2 { h2 {
margin-top: 0; margin-top: 0;
...@@ -101,14 +191,6 @@ ...@@ -101,14 +191,6 @@
color: #a00; color: #a00;
} }
} }
.remember-me {
margin-top: -10px;
label {
font-weight: normal;
}
}
} }
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
...@@ -127,3 +209,35 @@ ...@@ -127,3 +209,35 @@
height: 32px; height: 32px;
} }
} }
.devise-layout-html {
margin: 0;
padding: 0;
height: 100%;
}
// Fixes footer container to bottom of viewport
.devise-layout-html body {
// offset height of fixed header + 1 to avoid scroll
height: calc(100% - 51px);
margin: 0;
padding: 0;
.page-wrap {
min-height: 100%;
position: relative;
}
.footer-container, hr.footer-fixed {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 40px;
background: $white-light;
}
.navless-container {
padding: 65px; // height of footer + bottom padding of email confirmation link
}
}
.project-members-title {
padding-bottom: 10px;
border-bottom: 1px solid $border-color;
}
.member {
.list-item-name {
@media (min-width: $screen-sm-min) {
float: left;
width: 50%;
}
strong {
font-weight: 600;
}
}
.controls {
@media (min-width: $screen-sm-min) {
display: -webkit-flex;
display: flex;
width: 400px;
max-width: 50%;
}
}
.form-horizontal {
margin-top: 5px;
@media (min-width: $screen-sm-min) {
display: -webkit-flex;
display: flex;
width: 100%;
margin-top: 3px;
}
}
.btn-remove {
width: 100%;
@media (min-width: $screen-sm-min) {
width: auto;
}
}
}
.member-form-control {
@media (max-width: $screen-xs-max) {
padding: 5px 0;
margin-left: 0;
margin-right: 0;
}
@media (min-width: $screen-sm-min) {
width: 50%;
}
}
.member-access-text {
margin-left: auto;
line-height: 43px;
}
.member.existing-title {
@media (min-width: $screen-sm-min) {
float: left;
}
}
.member-search-form {
position: relative;
@media (min-width: $screen-sm-min) {
float: right;
}
.form-control {
width: 100%;
padding-right: 35px;
@media (min-width: $screen-sm-min) {
width: 350px;
}
}
}
.member-search-btn {
position: absolute;
right: 0;
top: 0;
height: 35px;
padding-left: 10px;
padding-right: 10px;
color: $gray-darkest;
background: transparent;
border: 0;
outline: 0;
}
...@@ -131,6 +131,7 @@ $colors: ( ...@@ -131,6 +131,7 @@ $colors: (
} }
} }
} }
&.head { &.head {
background-color: map-get($colors, #{$color}_header_head_neutral); background-color: map-get($colors, #{$color}_header_head_neutral);
border-color: map-get($colors, #{$color}_header_head_neutral); border-color: map-get($colors, #{$color}_header_head_neutral);
...@@ -174,6 +175,7 @@ $colors: ( ...@@ -174,6 +175,7 @@ $colors: (
background-color: map-get($colors, #{$color}_line_not_chosen); background-color: map-get($colors, #{$color}_line_not_chosen);
} }
} }
&.head { &.head {
background-color: map-get($colors, #{$color}_line_head_neutral); background-color: map-get($colors, #{$color}_line_head_neutral);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
form { form {
margin-bottom: 0; margin-bottom: 0;
.clearfix { .clearfix {
margin-bottom: 0; margin-bottom: 0;
} }
...@@ -46,6 +47,7 @@ ...@@ -46,6 +47,7 @@
&.right { &.right {
float: right; float: right;
a { a {
color: $gl-gray; color: $gl-gray;
} }
...@@ -121,6 +123,10 @@ ...@@ -121,6 +123,10 @@
color: #5c5d5e; color: #5c5d5e;
} }
.js-deployment-link {
display: inline-block;
}
.mr-widget-body { .mr-widget-body {
h4 { h4 {
font-weight: 600; font-weight: 600;
...@@ -188,6 +194,7 @@ ...@@ -188,6 +194,7 @@
padding-top: 2px; padding-top: 2px;
padding-bottom: 2px; padding-bottom: 2px;
list-style: none; list-style: none;
&:hover { &:hover {
background: none; background: none;
} }
...@@ -211,6 +218,7 @@ ...@@ -211,6 +218,7 @@
padding-top: 20px; padding-top: 20px;
padding-bottom: 10px; padding-bottom: 10px;
} }
svg { svg {
width: 230px; width: 230px;
} }
...@@ -276,12 +284,6 @@ ...@@ -276,12 +284,6 @@
line-height: 31px; line-height: 31px;
} }
.builds {
.table-holder {
overflow-x: auto;
}
}
.panel-new-merge-request { .panel-new-merge-request {
.panel-heading { .panel-heading {
padding: 5px 10px; padding: 5px 10px;
...@@ -369,7 +371,7 @@ ...@@ -369,7 +371,7 @@
} }
.table-holder { .table-holder {
.builds { .ci-table {
th { th {
background-color: $white-light; background-color: $white-light;
...@@ -433,3 +435,12 @@ ...@@ -433,3 +435,12 @@
margin-bottom: 20px; margin-bottom: 20px;
} }
} }
.merge-request-tabs {
background-color: #fff;
&.affix {
top: 100px;
z-index: 9;
}
}
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
color: $gl-placeholder-color; color: $gl-placeholder-color;
margin-right: 5px; margin-right: 5px;
} }
.avatar { .avatar {
float: none; float: none;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
filter: alpha(opacity=100); filter: alpha(opacity=100);
} }
} }
.diff-file, .diff-file,
.discussion { .discussion {
.new-note { .new-note {
...@@ -194,6 +195,7 @@ ...@@ -194,6 +195,7 @@
min-height: 140px; min-height: 140px;
max-height: 500px; max-height: 500px;
} }
.note-form-actions { .note-form-actions {
background: transparent; background: transparent;
} }
......
...@@ -147,9 +147,18 @@ ul.notes { ...@@ -147,9 +147,18 @@ ul.notes {
// Diff code in discussion view // Diff code in discussion view
.discussion-body .diff-file { .discussion-body .diff-file {
.file-title {
cursor: default;
&:hover {
background-color: $gray-light;
}
}
.diff-header > span { .diff-header > span {
margin-right: 10px; margin-right: 10px;
} }
.line_content { .line_content {
white-space: pre-wrap; white-space: pre-wrap;
} }
...@@ -345,6 +354,7 @@ ul.notes { ...@@ -345,6 +354,7 @@ ul.notes {
width: 32px; width: 32px;
// "hide" it by default // "hide" it by default
display: none; display: none;
&:hover { &:hover {
background: $gl-info; background: $gl-info;
color: #fff; color: #fff;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
margin: 4px; margin: 4px;
} }
.table.builds { .table.ci-table {
min-width: 1200px; min-width: 1200px;
.branch-commit { .branch-commit {
...@@ -44,13 +44,20 @@ ...@@ -44,13 +44,20 @@
overflow: auto; overflow: auto;
} }
.table.builds { .table.ci-table {
min-width: 900px; min-width: 900px;
&.pipeline { &.pipeline {
min-width: 650px; min-width: 650px;
} }
&.builds-page {
tr {
height: 71px;
}
}
tr { tr {
th { th {
padding: 16px 8px; padding: 16px 8px;
...@@ -176,7 +183,7 @@ ...@@ -176,7 +183,7 @@
&::after { &::after {
content: ''; content: '';
width: 8px; width: 8px;
position: absolute;; position: absolute;
right: -7px; right: -7px;
bottom: 8px; bottom: 8px;
border-bottom: 2px solid $border-color; border-bottom: 2px solid $border-color;
...@@ -353,6 +360,7 @@ ...@@ -353,6 +360,7 @@
&:hover { &:hover {
background-color: $gray-lighter; background-color: $gray-lighter;
.dropdown-menu-toggle { .dropdown-menu-toggle {
background-color: transparent; background-color: transparent;
} }
...@@ -536,6 +544,7 @@ ...@@ -536,6 +544,7 @@
height: 29px; height: 29px;
top: -9px; top: -9px;
} }
.curve { .curve {
display: block; display: block;
} }
...@@ -621,7 +630,9 @@ ...@@ -621,7 +630,9 @@
} }
} }
.pipelines.tab-pane { .tab-pane {
&.pipelines {
.content-list.pipelines { .content-list.pipelines {
overflow: auto; overflow: auto;
...@@ -635,6 +646,16 @@ ...@@ -635,6 +646,16 @@
.pipeline-actions { .pipeline-actions {
min-width: initial; min-width: initial;
} }
}
&.builds {
.ci-table {
tr {
height: 71px;
}
}
}
} }
.ci-status-icon-created { .ci-status-icon-created {
......
...@@ -243,6 +243,7 @@ ...@@ -243,6 +243,7 @@
.btn { .btn {
-webkit-flex-grow: 1; -webkit-flex-grow: 1;
flex-grow: 1; flex-grow: 1;
&:first-child { &:first-child {
margin-left: 0; margin-left: 0;
} }
......
...@@ -17,34 +17,43 @@ ...@@ -17,34 +17,43 @@
&.features .control-label { &.features .control-label {
font-weight: normal; font-weight: normal;
} }
.form-group { .form-group {
margin-bottom: 5px; margin-bottom: 5px;
} }
&> .form-group { &> .form-group {
padding-left: 0; padding-left: 0;
} }
} }
.help-block { .help-block {
margin-bottom: 10px; margin-bottom: 10px;
} }
.project-path { .project-path {
padding-right: 0; padding-right: 0;
.form-control { .form-control {
border-radius: $border-radius-base; border-radius: $border-radius-base;
} }
} }
.input-group > div { .input-group > div {
&:last-child { &:last-child {
padding-right: 0; padding-right: 0;
} }
} }
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
.input-group > div { .input-group > div {
margin-bottom: 14px; margin-bottom: 14px;
&:last-child { &:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
} }
fieldset > .form-group:first-child { fieldset > .form-group:first-child {
padding-right: 0; padding-right: 0;
} }
...@@ -56,6 +65,7 @@ ...@@ -56,6 +65,7 @@
border-radius: 3px; border-radius: 3px;
border: 1px solid #e5e5e5; border: 1px solid #e5e5e5;
} }
&+ .select2 a { &+ .select2 a {
border-top-left-radius: 0; border-top-left-radius: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
...@@ -201,6 +211,7 @@ ...@@ -201,6 +211,7 @@
pointer-events: none; pointer-events: none;
} }
} }
.count { .count {
@include btn-gray; @include btn-gray;
display: inline-block; display: inline-block;
...@@ -361,10 +372,12 @@ a.deploy-project-label { ...@@ -361,10 +372,12 @@ a.deploy-project-label {
margin: $gl-padding; margin: $gl-padding;
text-align: center; text-align: center;
width: 169px; width: 169px;
&:hover, &.forked { &:hover, &.forked {
background-color: $row-hover; background-color: $row-hover;
border-color: $row-hover-border; border-color: $row-hover-border;
} }
.no-avatar { .no-avatar {
width: 100px; width: 100px;
height: 100px; height: 100px;
...@@ -372,17 +385,20 @@ a.deploy-project-label { ...@@ -372,17 +385,20 @@ a.deploy-project-label {
border: 1px solid $gray-dark; border: 1px solid $gray-dark;
margin: 0 auto; margin: 0 auto;
border-radius: 50%; border-radius: 50%;
i { i {
font-size: 100px; font-size: 100px;
color: $gray-dark; color: $gray-dark;
} }
} }
a { a {
display: block; display: block;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding-top: $gl-padding; padding-top: $gl-padding;
color: $gl-gray; color: $gl-gray;
.caption { .caption {
min-height: 30px; min-height: 30px;
padding: $gl-padding 0; padding: $gl-padding 0;
...@@ -644,6 +660,7 @@ pre.light-well { ...@@ -644,6 +660,7 @@ pre.light-well {
.clone-options { .clone-options {
display: table-cell; display: table-cell;
a.btn { a.btn {
width: 100%; width: 100%;
} }
...@@ -832,6 +849,7 @@ pre.light-well { ...@@ -832,6 +849,7 @@ pre.light-well {
.form-control { .form-control {
min-width: 100px; min-width: 100px;
} }
.select2-choice { .select2-choice {
border-top-right-radius: 0; border-top-right-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
&.runner-state-shared { &.runner-state-shared {
background: #32b186; background: #32b186;
} }
&.runner-state-specific { &.runner-state-specific {
background: #3498db; background: #3498db;
} }
......
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
.ci-status-icon-success { .ci-status-icon-success {
color: $gl-success; color: $gl-success;
} }
.ci-status-icon-failed { .ci-status-icon-failed {
color: $gl-danger; color: $gl-danger;
} }
...@@ -77,6 +78,7 @@ ...@@ -77,6 +78,7 @@
.ci-status-icon-running { .ci-status-icon-running {
color: $blue-normal; color: $blue-normal;
} }
.ci-status-icon-canceled, .ci-status-icon-canceled,
.ci-status-icon-disabled, .ci-status-icon-disabled,
.ci-status-icon-not-found, .ci-status-icon-not-found,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
.file-finder { .file-finder {
width: 50%; width: 50%;
.file-finder-input { .file-finder-input {
width: 95%; width: 95%;
display: inline-block; display: inline-block;
......
This diff is collapsed.
...@@ -45,6 +45,10 @@ class ApplicationController < ActionController::Base ...@@ -45,6 +45,10 @@ class ApplicationController < ActionController::Base
redirect_to request.referer.present? ? :back : default, options redirect_to request.referer.present? ? :back : default, options
end end
def not_found
render_404
end
protected protected
# This filter handles both private tokens and personal access tokens # This filter handles both private tokens and personal access tokens
......
class Projects::GroupLinksController < Projects::ApplicationController class Projects::GroupLinksController < Projects::ApplicationController
layout 'project_settings' layout 'project_settings'
before_action :authorize_admin_project! before_action :authorize_admin_project!
before_action :authorize_admin_project_member!, only: [:update]
def index def index
@group_links = project.project_group_links.all @group_links = project.project_group_links.all
...@@ -27,9 +28,26 @@ class Projects::GroupLinksController < Projects::ApplicationController ...@@ -27,9 +28,26 @@ class Projects::GroupLinksController < Projects::ApplicationController
redirect_to namespace_project_group_links_path(project.namespace, project) redirect_to namespace_project_group_links_path(project.namespace, project)
end end
def update
@group_link = @project.project_group_links.find(params[:id])
@group_link.update_attributes(group_link_params)
end
def destroy def destroy
project.project_group_links.find(params[:id]).destroy project.project_group_links.find(params[:id]).destroy
respond_to do |format|
format.html do
redirect_to namespace_project_group_links_path(project.namespace, project) redirect_to namespace_project_group_links_path(project.namespace, project)
end end
format.js { head :ok }
end
end
protected
def group_link_params
params.require(:group_link).permit(:group_access, :expires_at)
end
end end
...@@ -10,7 +10,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -10,7 +10,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_action :module_enabled before_action :module_enabled
before_action :merge_request, only: [ before_action :merge_request, only: [
:edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines, :merge, :merge_check, :edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines, :merge, :merge_check,
:ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues :ci_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues
] ]
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds, :pipelines] before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds, :pipelines]
before_action :define_show_vars, only: [:show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines] before_action :define_show_vars, only: [:show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines]
...@@ -413,6 +413,30 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -413,6 +413,30 @@ class Projects::MergeRequestsController < Projects::ApplicationController
render json: response render json: response
end end
def ci_environments_status
environments =
begin
@merge_request.environments.map do |environment|
next unless can?(current_user, :read_environment, environment)
project = environment.project
deployment = environment.first_deployment_for(@merge_request.diff_head_commit)
{
id: environment.id,
name: environment.name,
url: namespace_project_environment_path(project.namespace, project, environment),
external_url: environment.external_url,
external_url_formatted: environment.formatted_external_url,
deployed_at: deployment.try(:created_at),
deployed_at_formatted: deployment.try(:formatted_deployment_time)
}
end.compact
end
render json: environments
end
protected protected
def selected_target_project def selected_target_project
......
...@@ -5,34 +5,23 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -5,34 +5,23 @@ class Projects::ProjectMembersController < Projects::ApplicationController
before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access] before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
def index def index
@group_links = @project.project_group_links
@project_members = @project.project_members @project_members = @project.project_members
@project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project) @project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
if params[:search].present? if params[:search].present?
users = @project.users.search(params[:search]).to_a users = @project.users.search(params[:search]).to_a
@project_members = @project_members.where(user_id: users) @project_members = @project_members.where(user_id: users)
end
@project_members = @project_members.order('access_level DESC')
@group = @project.group
if @group @group_links = @project.project_group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id))
@group_members = @group.group_members
@group_members = @group_members.non_invite unless can?(current_user, :admin_group, @group)
if params[:search].present?
users = @group.users.search(params[:search]).to_a
@group_members = @group_members.where(user_id: users)
end end
@group_members = @group_members.order('access_level DESC') @project_members = @project_members.order(access_level: :desc).page(params[:page])
end
@requesters = AccessRequestsFinder.new(@project).execute(current_user) @requesters = AccessRequestsFinder.new(@project).execute(current_user)
@project_member = @project.project_members.new @project_member = @project.project_members.new
@project_group_links = @project.project_group_links
end end
def create def create
...@@ -43,6 +32,21 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -43,6 +32,21 @@ class Projects::ProjectMembersController < Projects::ApplicationController
current_user: current_user current_user: current_user
) )
if params[:group_ids].present?
group_ids = params[:group_ids].split(',')
groups = Group.where(id: group_ids)
groups.each do |group|
next unless can?(current_user, :read_group, group)
project.project_group_links.create(
group: group,
group_access: params[:access_level],
expires_at: params[:expires_at]
)
end
end
redirect_to namespace_project_project_members_path(@project.namespace, @project) redirect_to namespace_project_project_members_path(@project.namespace, @project)
end end
......
class UsersController < ApplicationController class UsersController < ApplicationController
skip_before_action :authenticate_user! skip_before_action :authenticate_user!
before_action :user before_action :user, except: [:exists]
before_action :authorize_read_user!, only: [:show] before_action :authorize_read_user!, only: [:show]
def show def show
...@@ -85,6 +85,10 @@ class UsersController < ApplicationController ...@@ -85,6 +85,10 @@ class UsersController < ApplicationController
render 'calendar_activities', layout: false render 'calendar_activities', layout: false
end end
def exists
render json: { exists: Namespace.where(path: params[:username].downcase).any? }
end
private private
def authorize_read_user! def authorize_read_user!
......
module Ci module Ci
class Build < CommitStatus class Build < CommitStatus
include TokenAuthenticatable include TokenAuthenticatable
include AfterCommitQueue
belongs_to :runner, class_name: 'Ci::Runner' belongs_to :runner, class_name: 'Ci::Runner'
belongs_to :trigger_request, class_name: 'Ci::TriggerRequest' belongs_to :trigger_request, class_name: 'Ci::TriggerRequest'
...@@ -75,25 +76,20 @@ module Ci ...@@ -75,25 +76,20 @@ module Ci
state_machine :status do state_machine :status do
after_transition pending: :running do |build| after_transition pending: :running do |build|
build.execute_hooks build.run_after_commit do
BuildHooksWorker.perform_async(id)
end
end end
after_transition any => [:success, :failed, :canceled] do |build| after_transition any => [:success, :failed, :canceled] do |build|
build.update_coverage build.run_after_commit do
build.execute_hooks BuildFinishedWorker.perform_async(id)
end
end end
after_transition any => [:success] do |build| after_transition any => [:success] do |build|
if build.environment.present? build.run_after_commit do
service = CreateDeploymentService.new( BuildSuccessWorker.perform_async(id)
build.project, build.user,
environment: build.environment,
sha: build.sha,
ref: build.ref,
tag: build.tag,
options: build.options.to_h[:environment],
variables: build.variables)
service.execute(build)
end end
end end
end end
......
...@@ -76,7 +76,11 @@ module Ci ...@@ -76,7 +76,11 @@ module Ci
end end
after_transition do |pipeline, transition| after_transition do |pipeline, transition|
pipeline.execute_hooks unless transition.loopback? next if transition.loopback?
pipeline.run_after_commit do
PipelineHooksWorker.perform_async(id)
end
end end
end end
......
...@@ -84,6 +84,10 @@ class Deployment < ActiveRecord::Base ...@@ -84,6 +84,10 @@ class Deployment < ActiveRecord::Base
take take
end end
def formatted_deployment_time
created_at.to_time.in_time_zone.to_s(:medium)
end
private private
def ref_path def ref_path
......
...@@ -48,7 +48,22 @@ class Environment < ActiveRecord::Base ...@@ -48,7 +48,22 @@ class Environment < ActiveRecord::Base
self.name == "production" self.name == "production"
end end
def first_deployment_for(commit)
ref = project.repository.ref_name_for_sha(ref_path, commit.sha)
return nil unless ref
deployment_id = ref.split('/').last
deployments.find(deployment_id)
end
def ref_path def ref_path
"refs/environments/#{Shellwords.shellescape(name)}" "refs/environments/#{Shellwords.shellescape(name)}"
end end
def formatted_external_url
return nil unless external_url
external_url.gsub(/\A.*?:\/\//, '')
end
end end
...@@ -688,6 +688,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -688,6 +688,8 @@ class MergeRequest < ActiveRecord::Base
def environments def environments
return [] unless diff_head_commit return [] unless diff_head_commit
@environments ||=
begin
environments = source_project.environments_for( environments = source_project.environments_for(
source_branch, diff_head_commit) source_branch, diff_head_commit)
environments += target_project.environments_for( environments += target_project.environments_for(
...@@ -695,6 +697,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -695,6 +697,7 @@ class MergeRequest < ActiveRecord::Base
environments.uniq environments.uniq
end end
end
def state_human_name def state_human_name
if merged? if merged?
......
...@@ -490,7 +490,7 @@ class Project < ActiveRecord::Base ...@@ -490,7 +490,7 @@ class Project < ActiveRecord::Base
end end
def import_url def import_url
if import_data && super if import_data && super.present?
import_url = Gitlab::UrlSanitizer.new(super, credentials: import_data.credentials) import_url = Gitlab::UrlSanitizer.new(super, credentials: import_data.credentials)
import_url.full_url import_url.full_url
else else
...@@ -829,11 +829,6 @@ class Project < ActiveRecord::Base ...@@ -829,11 +829,6 @@ class Project < ActiveRecord::Base
end end
end end
def update_merge_requests(oldrev, newrev, ref, user)
MergeRequests::RefreshService.new(self, user).
execute(oldrev, newrev, ref)
end
def valid_repo? def valid_repo?
repository.exists? repository.exists?
rescue rescue
......
...@@ -719,6 +719,14 @@ class Repository ...@@ -719,6 +719,14 @@ class Repository
end end
end end
def ref_name_for_sha(ref_path, sha)
args = %W(#{Gitlab.config.git.bin_path} for-each-ref --count=1 #{ref_path} --contains #{sha})
# Not found -> ["", 0]
# Found -> ["b8d95eb4969eefacb0a58f6a28f6803f8070e7b9 commit\trefs/environments/production/77\n", 0]
Gitlab::Popen.popen(args, path_to_repo).first.split.last
end
def refs_contains_sha(ref_type, sha) def refs_contains_sha(ref_type, sha)
args = %W(#{Gitlab.config.git.bin_path} #{ref_type} --contains #{sha}) args = %W(#{Gitlab.config.git.bin_path} #{ref_type} --contains #{sha})
names = Gitlab::Popen.popen(args, path_to_repo).first names = Gitlab::Popen.popen(args, path_to_repo).first
......
...@@ -2,25 +2,35 @@ require_relative 'base_service' ...@@ -2,25 +2,35 @@ require_relative 'base_service'
class CreateDeploymentService < BaseService class CreateDeploymentService < BaseService
def execute(deployable = nil) def execute(deployable = nil)
environment = find_or_create_environment return unless executable?
deployment = project.deployments.create( ActiveRecord::Base.transaction do
environment: environment, @deployable = deployable
ref: params[:ref], @environment = prepare_environment
tag: params[:tag],
sha: params[:sha],
user: current_user,
deployable: deployable
)
deploy.tap do |deployment|
deployment.update_merge_request_metrics! deployment.update_merge_request_metrics!
end
deployment end
end end
private private
def find_or_create_environment def executable?
project && name.present?
end
def deploy
project.deployments.create(
environment: @environment,
ref: params[:ref],
tag: params[:tag],
sha: params[:sha],
user: current_user,
deployable: @deployable)
end
def prepare_environment
project.environments.find_or_create_by(name: expanded_name) do |environment| project.environments.find_or_create_by(name: expanded_name) do |environment|
environment.external_url = expanded_url environment.external_url = expanded_url
end end
......
...@@ -63,13 +63,12 @@ class GitPushService < BaseService ...@@ -63,13 +63,12 @@ class GitPushService < BaseService
protected protected
def update_merge_requests def update_merge_requests
@project.update_merge_requests(params[:oldrev], params[:newrev], params[:ref], current_user) UpdateMergeRequestsWorker.perform_async(@project.id, current_user.id, params[:oldrev], params[:newrev], params[:ref])
EventCreateService.new.push(@project, current_user, build_push_data) EventCreateService.new.push(@project, current_user, build_push_data)
SystemHooksService.new.execute_hooks(build_push_data_system_hook.dup, :push_hooks)
@project.execute_hooks(build_push_data.dup, :push_hooks) @project.execute_hooks(build_push_data.dup, :push_hooks)
@project.execute_services(build_push_data.dup, :push_hooks) @project.execute_services(build_push_data.dup, :push_hooks)
Ci::CreatePipelineService.new(project, current_user, build_push_data).execute Ci::CreatePipelineService.new(@project, current_user, build_push_data).execute
ProjectCacheWorker.perform_async(@project.id) ProjectCacheWorker.perform_async(@project.id)
end end
...@@ -148,16 +147,6 @@ class GitPushService < BaseService ...@@ -148,16 +147,6 @@ class GitPushService < BaseService
push_commits) push_commits)
end end
def build_push_data_system_hook
@push_data_system ||= Gitlab::DataBuilder::Push.build(
@project,
current_user,
params[:oldrev],
params[:newrev],
params[:ref],
[])
end
def push_to_existing_branch? def push_to_existing_branch?
# Return if this is not a push to a branch (e.g. new commits) # Return if this is not a push to a branch (e.g. new commits)
Gitlab::Git.branch_ref?(params[:ref]) && !Gitlab::Git.blank_ref?(params[:oldrev]) Gitlab::Git.branch_ref?(params[:ref]) && !Gitlab::Git.blank_ref?(params[:oldrev])
......
- page_title "Preview | Appearance" = render 'devise/shared/tab_single', tab_title: 'Sign in preview'
.login-box .login-box
.login-heading %form.show-gl-field-errors
%h3 Existing user? Sign in .form-group
%form = label_tag :login
= text_field_tag :login, nil, class: "form-control top", placeholder: "Username or Email" = text_field_tag :login, nil, class: "form-control top", title: 'Please provide your username or email address.'
= password_field_tag :password, nil, class: "form-control bottom", placeholder: "Password" .form-group
= label_tag :password
= password_field_tag :password, nil, class: "form-control bottom", title: 'This field is required.'
.form-group
= button_tag "Sign in", class: "btn-create btn" = button_tag "Sign in", class: "btn-create btn"
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
.col-md-6 .col-md-6
%h4 Recent builds served by this Runner %h4 Recent builds served by this Runner
%table.table.builds.runner-builds %table.table.ci-table.runner-builds
%thead %thead
%tr %tr
%th Build %th Build
......
= render 'devise/shared/tab_single', tab_title: 'Resend confirmation instructions'
.login-box .login-box
.login-heading
%h3 Resend confirmation instructions
.login-body .login-body
= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: 'show-gl-field-errors' }) do |f|
.devise-errors .devise-errors
= devise_error_messages! = devise_error_messages!
.clearfix.append-bottom-20 .form-group
= f.email_field :email, placeholder: 'Email', class: "form-control", required: true = f.label :email
= f.email_field :email, class: "form-control", required: true, title: 'Please provide a valid email address.'
.clearfix .clearfix
= f.submit "Resend confirmation instructions", class: 'btn btn-success' = f.submit "Resend", class: 'btn btn-success'
.clearfix.prepend-top-20 .clearfix.prepend-top-20
= render 'devise/shared/sign_in_link' = render 'devise/shared/sign_in_link'
= render 'devise/shared/tab_single', tab_title:'Change your password'
.login-box .login-box
.login-heading
%h3 Change your password
.login-body .login-body
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, class: 'show-gl-field-errors' }) do |f|
.devise-errors .devise-errors
= devise_error_messages! = devise_error_messages!
= f.hidden_field :reset_password_token = f.hidden_field :reset_password_token
%div .form-group
= f.password_field :password, class: "form-control top", placeholder: "New password", required: true = f.label 'New password', for: :password
%div = f.password_field :password, class: "form-control top", required: true, title: 'This field is required'
= f.password_field :password_confirmation, class: "form-control bottom", placeholder: "Confirm new password", required: true .form-group
= f.label 'Confirm new password', for: :password_confirmation
= f.password_field :password_confirmation, class: "form-control bottom", title: 'This field is required', required: true
.clearfix .clearfix
= f.submit "Change your password", class: "btn btn-primary" = f.submit "Change your password", class: "btn btn-primary"
.clearfix.prepend-top-20 .clearfix.prepend-top-20
%p %p
= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %span.light Didn't receive a confirmation email?
= render 'devise/shared/sign_in_link' = link_to "Request a new one", new_confirmation_path(resource_name)
= render 'devise/shared/sign_in_link'
= render 'devise/shared/tab_single', tab_title: 'Reset Password'
.login-box .login-box
.login-heading
%h3 Reset password
.login-body .login-body
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: 'show-gl-field-errors' }) do |f|
.devise-errors .devise-errors
= devise_error_messages! = devise_error_messages!
.clearfix.append-bottom-20 .form-group
= f.email_field :email, placeholder: "Email", class: "form-control", required: true, value: params[:user_email], autofocus: true = f.label :email
= f.email_field :email, class: "form-control", required: true, value: params[:user_email], autofocus: true, title: 'Please provide a valid email address.'
.clearfix .clearfix
= f.submit "Reset password", class: "btn-primary btn" = f.submit "Reset password", class: "btn-primary btn"
......
= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| = form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: 'new_user show-gl-field-errors', 'aria-live' => 'assertive'}) do |f|
= f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off" %div.form-group
= f.password_field :password, class: "form-control bottom", placeholder: "Password" = f.label "Username or email", for: :login
= f.text_field :login, class: "form-control top", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off", required: true, title: "This field is required."
%div.form-group
= f.label :password
= f.password_field :password, class: "form-control bottom", required: true, title: "This field is required."
- if devise_mapping.rememberable? - if devise_mapping.rememberable?
.remember-me.checkbox .remember-me.checkbox
%label{for: "user_remember_me"} %label{for: "user_remember_me"}
...@@ -8,5 +12,5 @@ ...@@ -8,5 +12,5 @@
%span Remember me %span Remember me
.pull-right .pull-right
= link_to "Forgot your password?", new_password_path(resource_name) = link_to "Forgot your password?", new_password_path(resource_name)
%div %div.submit-container
= f.submit "Sign in", class: "btn btn-save" = f.submit "Sign in", class: "btn btn-save"
= form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user' ) do = form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user', class: 'show-gl-field-errors') do
= text_field_tag :username, nil, {class: "form-control top", placeholder: "Username", autofocus: "autofocus"} .form-group
= password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"} = label_tag 'Username or email', for: :username
= text_field_tag :username, nil, {class: "form-control top", title: "This field is required", autofocus: "autofocus", required: true }
.form-group
= label_tag :password
= password_field_tag :password, nil, { class: "form-control bottom", title: "This field is required.", required: true }
- if devise_mapping.rememberable? - if devise_mapping.rememberable?
.remember-me.checkbox .remember-me.checkbox
%label{for: "remember_me"} %label{for: "remember_me"}
......
= form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user') do = form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user', class: "show-gl-field-errors") do
= text_field_tag :username, nil, {class: "form-control top", placeholder: "#{server['label']} Login", autofocus: "autofocus"} .form-group
= password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"} = label_tag "#{server['label']} Login", for: :username
= text_field_tag :username, nil, {class: "form-control top", title: "This field is required.", autofocus: "autofocus", required: true }
.form-group
= label_tag :password
= password_field_tag :password, nil, { class: "form-control bottom", title: "This field is required.", required: true }
- if devise_mapping.rememberable? - if devise_mapping.rememberable?
.remember-me.checkbox .remember-me.checkbox
%label{for: "remember_me"} %label{for: "remember_me"}
......
- page_title "Sign in" - page_title "Sign in"
%div %div
- if form_based_providers.any?
= render 'devise/shared/tabs_ldap'
- else
= render 'devise/shared/tabs_normal'
.tab-content
- if signin_enabled? || ldap_enabled? || crowd_enabled? - if signin_enabled? || ldap_enabled? || crowd_enabled?
= render 'devise/shared/signin_box' = render 'devise/shared/signin_box'
-# Omniauth fits between signin/ldap signin and signup and does not have a surrounding box
- if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
.clearfix.prepend-top-20
= render 'devise/shared/omniauth_box'
-# Signup only makes sense if you can also sign-in -# Signup only makes sense if you can also sign-in
- if signin_enabled? && signup_enabled? - if signin_enabled? && signup_enabled?
.prepend-top-20
= render 'devise/shared/signup_box' = render 'devise/shared/signup_box'
-# Show a message if none of the mechanisms above are enabled -# Show a message if none of the mechanisms above are enabled
- if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) - if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
%div %div
No authentication methods configured. No authentication methods configured.
- if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
.clearfix
= render 'devise/shared/omniauth_box'
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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