summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/build.js36
-rw-r--r--app/assets/javascripts/compare_autocomplete.js.es6 (renamed from app/assets/javascripts/compare_autocomplete.js)13
-rw-r--r--app/assets/javascripts/dispatcher.js.es6 (renamed from app/assets/javascripts/dispatcher.js)14
-rw-r--r--app/assets/javascripts/gl_dropdown.js88
-rw-r--r--app/assets/javascripts/gl_field_errors.js.es6167
-rw-r--r--app/assets/javascripts/groups.js13
-rw-r--r--app/assets/javascripts/member_expiration_date.js8
-rw-r--r--app/assets/javascripts/members.js.es636
-rw-r--r--app/assets/javascripts/merge_request_tabs.js41
-rw-r--r--app/assets/javascripts/pipelines.js.es6 (renamed from app/assets/javascripts/pipeline.js.es6)0
-rw-r--r--app/assets/javascripts/project_members.js10
-rw-r--r--app/assets/javascripts/templates/issuable_template_selector.js.es68
-rw-r--r--app/assets/javascripts/username_validator.js.es6133
-rw-r--r--app/assets/javascripts/users_select.js4
-rw-r--r--app/assets/stylesheets/behaviors.scss1
-rw-r--r--app/assets/stylesheets/framework/blocks.scss2
-rw-r--r--app/assets/stylesheets/framework/buttons.scss9
-rw-r--r--app/assets/stylesheets/framework/callout.scss5
-rw-r--r--app/assets/stylesheets/framework/common.scss39
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss2
-rw-r--r--app/assets/stylesheets/framework/files.scss18
-rw-r--r--app/assets/stylesheets/framework/forms.scss13
-rw-r--r--app/assets/stylesheets/framework/gitlab-theme.scss2
-rw-r--r--app/assets/stylesheets/framework/header.scss1
-rw-r--r--app/assets/stylesheets/framework/lists.scss13
-rw-r--r--app/assets/stylesheets/framework/logo.scss7
-rw-r--r--app/assets/stylesheets/framework/mixins.scss1
-rw-r--r--app/assets/stylesheets/framework/nav.scss1
-rw-r--r--app/assets/stylesheets/framework/panels.scss5
-rw-r--r--app/assets/stylesheets/framework/selects.scss8
-rw-r--r--app/assets/stylesheets/framework/timeline.scss1
-rw-r--r--app/assets/stylesheets/framework/tw_bootstrap.scss10
-rw-r--r--app/assets/stylesheets/framework/typography.scss1
-rw-r--r--app/assets/stylesheets/highlight/dark.scss128
-rw-r--r--app/assets/stylesheets/highlight/monokai.scss118
-rw-r--r--app/assets/stylesheets/highlight/solarized_dark.scss136
-rw-r--r--app/assets/stylesheets/highlight/solarized_light.scss136
-rw-r--r--app/assets/stylesheets/highlight/white.scss2
-rw-r--r--app/assets/stylesheets/mailers/repository_push_email.scss2
-rw-r--r--app/assets/stylesheets/notify.scss10
-rw-r--r--app/assets/stylesheets/pages/admin.scss12
-rw-r--r--app/assets/stylesheets/pages/builds.scss8
-rw-r--r--app/assets/stylesheets/pages/commit.scss6
-rw-r--r--app/assets/stylesheets/pages/commits.scss1
-rw-r--r--app/assets/stylesheets/pages/dashboard.scss2
-rw-r--r--app/assets/stylesheets/pages/diff.scss37
-rw-r--r--app/assets/stylesheets/pages/editor.scss5
-rw-r--r--app/assets/stylesheets/pages/environments.scss4
-rw-r--r--app/assets/stylesheets/pages/events.scss8
-rw-r--r--app/assets/stylesheets/pages/groups.scss15
-rw-r--r--app/assets/stylesheets/pages/help.scss8
-rw-r--r--app/assets/stylesheets/pages/issuable.scss8
-rw-r--r--app/assets/stylesheets/pages/issues.scss1
-rw-r--r--app/assets/stylesheets/pages/labels.scss1
-rw-r--r--app/assets/stylesheets/pages/lint.scss1
-rw-r--r--app/assets/stylesheets/pages/login.scss176
-rw-r--r--app/assets/stylesheets/pages/members.scss98
-rw-r--r--app/assets/stylesheets/pages/merge_conflicts.scss2
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss21
-rw-r--r--app/assets/stylesheets/pages/milestone.scss1
-rw-r--r--app/assets/stylesheets/pages/note_form.scss2
-rw-r--r--app/assets/stylesheets/pages/notes.scss10
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss45
-rw-r--r--app/assets/stylesheets/pages/profile.scss1
-rw-r--r--app/assets/stylesheets/pages/projects.scss18
-rw-r--r--app/assets/stylesheets/pages/runners.scss1
-rw-r--r--app/assets/stylesheets/pages/status.scss2
-rw-r--r--app/assets/stylesheets/pages/tree.scss1
-rw-r--r--app/assets/stylesheets/pages/xterm.scss290
-rw-r--r--app/controllers/application_controller.rb4
-rw-r--r--app/controllers/projects/group_links_controller.rb20
-rw-r--r--app/controllers/projects/project_members_controller.rb36
-rw-r--r--app/controllers/users_controller.rb6
-rw-r--r--app/models/ci/build.rb22
-rw-r--r--app/models/ci/pipeline.rb6
-rw-r--r--app/models/project.rb2
-rw-r--r--app/services/create_deployment_service.rb34
-rw-r--r--app/views/admin/appearances/preview.html.haml17
-rw-r--r--app/views/admin/runners/show.html.haml2
-rw-r--r--app/views/devise/confirmations/new.html.haml12
-rw-r--r--app/views/devise/passwords/edit.html.haml20
-rw-r--r--app/views/devise/passwords/new.html.haml10
-rw-r--r--app/views/devise/sessions/_new_base.html.haml12
-rw-r--r--app/views/devise/sessions/_new_crowd.html.haml10
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml10
-rw-r--r--app/views/devise/sessions/new.html.haml23
-rw-r--r--app/views/devise/sessions/two_factor.html.haml17
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml15
-rw-r--r--app/views/devise/shared/_sign_in_link.html.haml1
-rw-r--r--app/views/devise/shared/_signin_box.html.haml37
-rw-r--r--app/views/devise/shared/_signup_box.html.haml37
-rw-r--r--app/views/devise/shared/_tab_single.html.haml3
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml10
-rw-r--r--app/views/devise/shared/_tabs_normal.html.haml5
-rw-r--r--app/views/devise/unlocks/new.html.haml10
-rw-r--r--app/views/groups/group_members/_new_group_member.html.haml35
-rw-r--r--app/views/groups/group_members/index.html.haml40
-rw-r--r--app/views/groups/group_members/update.js.haml4
-rw-r--r--app/views/layouts/_init_auto_complete.html.haml9
-rw-r--r--app/views/layouts/application.html.haml1
-rw-r--r--app/views/layouts/devise.html.haml59
-rw-r--r--app/views/profiles/accounts/show.html.haml4
-rw-r--r--app/views/projects/_zen.html.haml4
-rw-r--r--app/views/projects/blame/show.html.haml87
-rw-r--r--app/views/projects/blob/edit.html.haml43
-rw-r--r--app/views/projects/builds/_table.html.haml2
-rw-r--r--app/views/projects/builds/show.html.haml95
-rw-r--r--app/views/projects/commit/_pipeline.html.haml2
-rw-r--r--app/views/projects/commit/_pipelines_list.haml2
-rw-r--r--app/views/projects/commit/builds.html.haml11
-rw-r--r--app/views/projects/commit/show.html.haml25
-rw-r--r--app/views/projects/compare/_ref_dropdown.html.haml4
-rw-r--r--app/views/projects/environments/edit.html.haml11
-rw-r--r--app/views/projects/environments/index.html.haml2
-rw-r--r--app/views/projects/environments/new.html.haml11
-rw-r--r--app/views/projects/environments/show.html.haml2
-rw-r--r--app/views/projects/group_links/update.js.haml3
-rw-r--r--app/views/projects/labels/edit.html.haml11
-rw-r--r--app/views/projects/labels/new.html.haml11
-rw-r--r--app/views/projects/merge_requests/_show.html.haml2
-rw-r--r--app/views/projects/milestones/edit.html.haml12
-rw-r--r--app/views/projects/milestones/new.html.haml11
-rw-r--r--app/views/projects/milestones/show.html.haml83
-rw-r--r--app/views/projects/notes/_notes_with_form.html.haml2
-rw-r--r--app/views/projects/pipelines/_head.html.haml2
-rw-r--r--app/views/projects/pipelines/index.html.haml2
-rw-r--r--app/views/projects/pipelines/show.html.haml13
-rw-r--r--app/views/projects/project_members/_group_members.html.haml2
-rw-r--r--app/views/projects/project_members/_groups.html.haml7
-rw-r--r--app/views/projects/project_members/_new_project_member.html.haml35
-rw-r--r--app/views/projects/project_members/_team.html.haml16
-rw-r--r--app/views/projects/project_members/index.html.haml40
-rw-r--r--app/views/projects/project_members/update.js.haml4
-rw-r--r--app/views/shared/issuable/_form.html.haml2
-rw-r--r--app/views/shared/members/_group.html.haml29
-rw-r--r--app/views/shared/members/_member.html.haml108
-rw-r--r--app/views/shared/members/_requests.html.haml2
-rw-r--r--app/views/u2f/_authenticate.html.haml2
-rw-r--r--app/workers/build_coverage_worker.rb9
-rw-r--r--app/workers/build_finished_worker.rb10
-rw-r--r--app/workers/build_hooks_worker.rb9
-rw-r--r--app/workers/build_success_worker.rb27
-rw-r--r--app/workers/pipeline_hooks_worker.rb9
143 files changed, 2311 insertions, 1013 deletions
diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js
index f336bfc36d6..97462a5959c 100644
--- a/app/assets/javascripts/build.js
+++ b/app/assets/javascripts/build.js
@@ -15,18 +15,17 @@
this.hideSidebar = bind(this.hideSidebar, this);
this.toggleSidebar = bind(this.toggleSidebar, this);
this.updateDropdown = bind(this.updateDropdown, this);
+ this.$document = $(document);
clearInterval(Build.interval);
// Init breakpoint checker
this.bp = Breakpoints.get();
- $('.js-build-sidebar').niceScroll();
+ this.initSidebar();
this.populateJobs(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);
- $(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);
this.updateArtifactRemoveDate();
if ($('#build-trace').length) {
@@ -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() {
var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped']
@@ -129,15 +143,23 @@
Build.prototype.toggleSidebar = function() {
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() {
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 {
- return $('.js-build-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
+ return this.$sidebar.removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
}
};
diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js.es6
index 294d2c9052c..9a2082d97e0 100644
--- a/app/assets/javascripts/compare_autocomplete.js
+++ b/app/assets/javascripts/compare_autocomplete.js.es6
@@ -9,7 +9,10 @@
var $dropdown, selected;
$dropdown = $(this);
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) {
return $.ajax({
url: $dropdown.data('refs-url'),
@@ -42,6 +45,14 @@
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');
+ });
});
};
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js.es6
index f3ef13ce20e..f3957ed374b 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js.es6
@@ -8,6 +8,7 @@
Dispatcher = (function() {
function Dispatcher() {
this.initSearch();
+ this.initFieldErrors();
this.initPageScripts();
}
@@ -20,6 +21,9 @@
path = page.split(':');
shortcut_handler = null;
switch (page) {
+ case 'sessions:new':
+ new UsernameValidator();
+ break;
case 'projects:boards:show':
case 'projects:boards:index':
shortcut_handler = new ShortcutsNavigation();
@@ -140,12 +144,12 @@
break;
case 'groups:group_members:index':
new gl.MemberExpirationDate();
- new GroupMembers();
+ new gl.Members();
new UsersSelect();
break;
case 'projects:project_members:index':
new gl.MemberExpirationDate();
- new ProjectMembers();
+ new gl.Members();
new UsersSelect();
break;
case 'groups:new':
@@ -291,6 +295,12 @@
}
};
+ Dispatcher.prototype.initFieldErrors = function() {
+ $('.show-gl-field-errors').each((i, form) => {
+ new gl.GlFieldErrors(form);
+ });
+ };
+
return Dispatcher;
})();
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
index e034ca68645..53762f2965c 100644
--- a/app/assets/javascripts/gl_dropdown.js
+++ b/app/assets/javascripts/gl_dropdown.js
@@ -25,7 +25,7 @@
return function(e) {
e.preventDefault();
e.stopPropagation();
- return _this.input.val('').trigger('keyup').focus();
+ return _this.input.val('').trigger('input').focus();
};
})(this));
// Key events
@@ -37,28 +37,16 @@
e.preventDefault()
}
})
- .on('keyup', function(e) {
- var keyCode;
- keyCode = e.which;
- if (ARROW_KEY_CODES.indexOf(keyCode) >= 0) {
- return;
- }
+ .on('input', function() {
if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.addClass(HAS_VALUE_CLASS);
} else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.removeClass(HAS_VALUE_CLASS);
}
- if (keyCode === 13 && !options.elIsInput) {
- return false;
- }
// Only filter asynchronously only if option remote is set
if (this.options.remote) {
clearTimeout(timeout);
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.callback(data);
}.bind(this));
@@ -255,7 +243,7 @@
_this.fullData = data;
_this.parseData(_this.fullData);
if (_this.options.filterable && _this.filter && _this.filter.input) {
- return _this.filter.input.trigger('keyup');
+ return _this.filter.input.trigger('input');
}
};
// Remote data
@@ -487,7 +475,7 @@
// 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
if (!this.options.persistWhenHide) {
- $input.trigger("keyup");
+ $input.trigger("input");
}
if (this.dropdown.find(".dropdown-toggle-page").length) {
$('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS);
@@ -500,14 +488,27 @@
// Render the full menu
GitLabDropdown.prototype.renderMenu = function(html) {
- var menu_html;
- menu_html = "";
if (this.options.renderMenu) {
- menu_html = this.options.renderMenu(html);
+ return this.options.renderMenu(html);
} 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
@@ -521,7 +522,7 @@
};
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) {
group = false;
}
@@ -529,18 +530,16 @@
// Render the row
index = false;
}
- html = "";
- // Divider
- if (data === "divider") {
- return "<li class='divider'></li>";
- }
- // Separator is a full-width divider
- if (data === "separator") {
- return "<li class='separator'></li>";
+ html = document.createElement('li');
+ if (data === 'divider' || data === 'separator') {
+ html.className = data;
+ return html;
}
// Header
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) {
// Call the render function
@@ -567,24 +566,25 @@
} else {
text = data.text != null ? data.text : '';
}
- cssClass = "";
- if (selected) {
- cssClass = "is-active";
- }
if (this.highlight) {
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) {
- groupAttrs = 'data-group=' + group + ' data-index=' + index;
- } else {
- groupAttrs = '';
+ link.dataset.group = group;
+ link.dataset.index = index;
}
- html = _.template('<li><a href="<%- url %>" <%- groupAttrs %> class="<%- cssClass %>"><%= text %></a></li>')({
- url: url,
- groupAttrs: groupAttrs,
- cssClass: cssClass,
- text: text
- });
+
+ html.appendChild(link);
}
return html;
};
diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6
new file mode 100644
index 00000000000..8657e7b4abf
--- /dev/null
+++ b/app/assets/javascripts/gl_field_errors.js.es6
@@ -0,0 +1,167 @@
+((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 = {}));
diff --git a/app/assets/javascripts/groups.js b/app/assets/javascripts/groups.js
deleted file mode 100644
index 4382dd6860f..00000000000
--- a/app/assets/javascripts/groups.js
+++ /dev/null
@@ -1,13 +0,0 @@
-(function() {
- this.GroupMembers = (function() {
- function GroupMembers() {
- $('li.group_member').bind('ajax:success', function() {
- return $(this).fadeOut();
- });
- }
-
- return GroupMembers;
-
- })();
-
-}).call(this);
diff --git a/app/assets/javascripts/member_expiration_date.js b/app/assets/javascripts/member_expiration_date.js
index 1935af491f7..e1532fd9ec4 100644
--- a/app/assets/javascripts/member_expiration_date.js
+++ b/app/assets/javascripts/member_expiration_date.js
@@ -14,14 +14,18 @@
inputs.datepicker({
dateFormat: 'yy-mm-dd',
minDate: 1,
- onSelect: toggleClearInput
+ onSelect: function () {
+ $(this).trigger('change');
+ toggleClearInput.call(this);
+ }
});
inputs.next('.js-clear-input').on('click', function(event) {
event.preventDefault();
var input = $(this).closest('.clearable-input').find('.js-access-expiration-date');
- input.datepicker('setDate', null);
+ input.datepicker('setDate', null)
+ .trigger('change');
toggleClearInput.call(input);
});
diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js.es6
new file mode 100644
index 00000000000..a0cd20f21e8
--- /dev/null
+++ b/app/assets/javascripts/members.js.es6
@@ -0,0 +1,36 @@
+((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);
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 8045d24a1bb..fd21aa1fefa 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -71,6 +71,7 @@
this._location = location;
this.bindEvents();
this.activateTab(this.opts.action);
+ this.initAffix();
}
MergeRequestTabs.prototype.bindEvents = function() {
@@ -380,6 +381,46 @@
// 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;
})();
diff --git a/app/assets/javascripts/pipeline.js.es6 b/app/assets/javascripts/pipelines.js.es6
index 6bf63ee6979..6bf63ee6979 100644
--- a/app/assets/javascripts/pipeline.js.es6
+++ b/app/assets/javascripts/pipelines.js.es6
diff --git a/app/assets/javascripts/project_members.js b/app/assets/javascripts/project_members.js
deleted file mode 100644
index 78f7b48bc7d..00000000000
--- a/app/assets/javascripts/project_members.js
+++ /dev/null
@@ -1,10 +0,0 @@
-(function() {
- this.ProjectMembers = (function() {
- function ProjectMembers() {
- $('li.project_member').bind('ajax:success', function() {
- return $(this).fadeOut();
- });
- }
- return ProjectMembers;
- })();
-}).call(this);
diff --git a/app/assets/javascripts/templates/issuable_template_selector.js.es6 b/app/assets/javascripts/templates/issuable_template_selector.js.es6
index 2ecf3b18975..bd4e3c3d00d 100644
--- a/app/assets/javascripts/templates/issuable_template_selector.js.es6
+++ b/app/assets/javascripts/templates/issuable_template_selector.js.es6
@@ -16,7 +16,13 @@
if (initialQuery.name) this.requestFile(initialQuery);
$('.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');
});
}
diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js.es6
new file mode 100644
index 00000000000..2517f778365
--- /dev/null
+++ b/app/assets/javascripts/username_validator.js.es6
@@ -0,0 +1,133 @@
+((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);
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index 6aa0e1cd2b6..3020b7cc239 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -325,6 +325,10 @@
};
UsersSelect.prototype.user = function(user_id, callback) {
+ if(!/^\d+$/.test(user_id)) {
+ return false;
+ }
+
var url;
url = this.buildUrl(this.userPath);
url = url.replace(':id', user_id);
diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss
index 897bc49e7df..e3ca7f6373a 100644
--- a/app/assets/stylesheets/behaviors.scss
+++ b/app/assets/stylesheets/behaviors.scss
@@ -5,6 +5,7 @@
display: none;
&.hide { display: block; }
}
+
&.open .content {
display: block;
&.hide { display: none; }
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 8002e56724b..df2e2ea8d2c 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -19,6 +19,7 @@
&.diff-collapsed {
padding: 5px;
+
.click-to-expand {
cursor: pointer;
}
@@ -203,6 +204,7 @@
}
}
}
+
&.user-cover-block {
padding: 24px 0 0;
}
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index a7c8d782e9b..e6656c2d69a 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -25,7 +25,7 @@
&:focus {
background-color: $hover-background;
color: $hover-text;
- border-color: $hover-border;;
+ border-color: $hover-border;
}
}
@@ -152,7 +152,8 @@
@include btn-blue-medium;
}
- &.btn-info {
+ &.btn-info,
+ &.btn-register {
@include btn-blue;
}
@@ -240,6 +241,7 @@
width: 100%;
margin: 0;
margin-bottom: 15px;
+
&.btn {
padding: 6px 0;
}
@@ -321,6 +323,7 @@
.btn-build {
margin-left: 10px;
+
i {
color: $gl-icon-color;
}
@@ -328,6 +331,7 @@
.clone-dropdown-btn a {
color: $dropdown-link-color;
+
&:hover {
text-decoration: none;
}
@@ -337,6 +341,7 @@
background-color: $background-color !important;
border: 1px solid lightgrey;
cursor: default;
+
&:active {
-moz-box-shadow: inset 0 0 0 white;
-webkit-box-shadow: inset 0 0 0 white;
diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss
index da7bab74a32..f3b6ad88ad6 100644
--- a/app/assets/stylesheets/framework/callout.scss
+++ b/app/assets/stylesheets/framework/callout.scss
@@ -13,10 +13,12 @@
color: $text-color;
background: $background-color;
}
+
.bs-callout h4 {
margin-top: 0;
margin-bottom: 5px;
}
+
.bs-callout p:last-child {
margin-bottom: 0;
}
@@ -27,16 +29,19 @@
border-color: #eed3d7;
color: #b94a48;
}
+
.bs-callout-warning {
background-color: #faf8f0;
border-color: #faebcc;
color: #8a6d3b;
}
+
.bs-callout-info {
background-color: #f4f8fa;
border-color: #bce8f1;
color: #34789a;
}
+
.bs-callout-success {
background-color: #dff0d8;
border-color: #5ca64d;
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 5957dce89bc..81e4e264560 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -1,31 +1,31 @@
/** COLORS **/
.cgray { color: $gl-gray; }
-.clgray { color: #bbb }
+.clgray { color: #bbb; }
.cred { color: $gl-text-red; }
.cgreen { color: $gl-text-green; }
-.cdark { color: #444 }
+.cdark { color: #444; }
/** COMMON CLASSES **/
.prepend-top-0 { margin-top: 0; }
.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-20 { margin-top: 20px }
-.prepend-left-5 { margin-left: 5px }
-.prepend-left-10 { margin-left: 10px }
+.prepend-top-20 { margin-top: 20px; }
+.prepend-left-5 { margin-left: 5px; }
+.prepend-left-10 { margin-left: 10px; }
.prepend-left-default { margin-left: $gl-padding; }
-.prepend-left-20 { margin-left: 20px }
-.append-right-5 { margin-right: 5px }
-.append-right-10 { margin-right: 10px }
+.prepend-left-20 { margin-left: 20px; }
+.append-right-5 { margin-right: 5px; }
+.append-right-10 { margin-right: 10px; }
.append-right-default { margin-right: $gl-padding; }
-.append-right-20 { margin-right: 20px }
-.append-bottom-0 { margin-bottom: 0 }
-.append-bottom-10 { margin-bottom: 10px }
-.append-bottom-15 { margin-bottom: 15px }
-.append-bottom-20 { margin-bottom: 20px }
+.append-right-20 { margin-right: 20px; }
+.append-bottom-0 { margin-bottom: 0; }
+.append-bottom-10 { margin-bottom: 10px; }
+.append-bottom-15 { margin-bottom: 15px; }
+.append-bottom-20 { margin-bottom: 20px; }
.append-bottom-default { margin-bottom: $gl-padding; }
-.inline { display: inline-block }
-.center { text-align: center }
+.inline { display: inline-block; }
+.center { text-align: center; }
.underlined-link { text-decoration: underline; }
.hint { font-style: italic; color: #999; }
@@ -97,6 +97,7 @@ span.update-author {
color: #999;
font-weight: normal;
font-style: italic;
+
strong {
font-weight: bold;
font-style: normal;
@@ -128,7 +129,7 @@ p.time {
// Fix issue with notes & lists creating a bunch of bottom borders.
li.note {
- img { max-width: 100% }
+ img { max-width: 100%; }
.note-title {
li {
border-bottom: none !important;
@@ -172,6 +173,7 @@ li.note {
@extend .col-md-6;
text-align: left;
margin-top: 40px;
+
pre {
background: white;
border: none;
@@ -197,6 +199,7 @@ li.note {
background: #c67;
color: #fff;
font-weight: bold;
+
a {
color: #fff;
text-decoration: underline;
@@ -227,6 +230,7 @@ li.note {
&.milestone-closed {
background: $gray-light;
}
+
.progress {
margin-bottom: 0;
margin-top: 4px;
@@ -286,6 +290,7 @@ table {
.footer-links {
margin-bottom: 20px;
+
a {
margin-right: 15px;
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index baa95711329..a839371a6f2 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -12,6 +12,7 @@
.dropdown-menu,
.dropdown-menu-nav {
display: block;
+
@media (max-width: $screen-xs-max) {
width: 100%;
}
@@ -48,6 +49,7 @@
margin-top: -6px;
color: $dropdown-toggle-icon-color;
font-size: 10px;
+
&.fa-spinner {
font-size: 16px;
margin-top: -8px;
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 81520500594..13c1bbf0359 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -26,15 +26,6 @@
padding: 10px $gl-padding;
word-wrap: break-word;
border-radius: 3px 3px 0 0;
- cursor: pointer;
-
- &:hover {
- background-color: $dark-background-color;
- }
-
- .diff-toggle-caret {
- padding-right: 6px;
- }
&.file-title-clear {
padding-left: 0;
@@ -66,6 +57,7 @@
margin-top: -3px;
}
}
+
.file-content {
background: #fff;
@@ -105,22 +97,27 @@
border: none;
margin: 0;
}
+
tr {
border-bottom: 1px solid #eee;
}
+
td {
&:first-child {
border-left: none;
}
+
&:last-child {
border-right: none;
}
}
+
td.blame-commit {
padding: 0 10px;
min-width: 400px;
background: $gray-light;
}
+
td.line-numbers {
float: none;
border-left: 1px solid #ddd;
@@ -130,6 +127,7 @@
margin-right: 0;
}
}
+
td.lines {
padding: 0;
}
@@ -146,8 +144,10 @@
border-left: 1px solid $border-color;
margin-bottom: 0;
background: white;
+
li {
color: #888;
+
p {
margin: 0;
color: #333;
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index 05e8ee0190d..761c07384f4 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -9,7 +9,7 @@ input {
input[type='text'].danger {
background: #f2dede!important;
border-color: #d66;
- text-shadow: 0 1px 1px #fff
+ text-shadow: 0 1px 1px #fff;
}
.datetime-controls {
@@ -73,8 +73,8 @@ label {
}
.form-control {
- box-shadow: none;
- border-radius: 3px;
+ @include box-shadow(none);
+ border-radius: 2px;
padding: $gl-vert-padding $gl-input-padding;
}
@@ -117,9 +117,11 @@ label {
display: table-cell;
width: 200px !important;
}
+
.input-group-addon {
background-color: #f7f8fa;
}
+
.input-group-addon:not(:first-child):not(:last-child) {
border-left: 0;
border-right: 0;
@@ -129,3 +131,8 @@ label {
.help-block {
margin-bottom: 0;
}
+
+.gl-field-error {
+ color: $red-normal;
+}
+
diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss
index 3673b81f183..fe834f4e2f6 100644
--- a/app/assets/stylesheets/framework/gitlab-theme.scss
+++ b/app/assets/stylesheets/framework/gitlab-theme.scss
@@ -62,7 +62,7 @@
}
i {
- color: $white-light
+ color: $white-light;
}
path,
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 9823abdde1f..3a4fdd0da22 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -168,6 +168,7 @@ header {
a {
color: $gl-text-color;
+
&:hover {
text-decoration: underline;
}
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index efc348214c2..4b2627c1b87 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -60,6 +60,7 @@
padding-top: 1px;
margin: 0;
color: $gray-dark;
+
img {
position: relative;
top: 3px;
@@ -128,6 +129,10 @@ ul.content-list {
color: $gl-dark-link-color;
}
+ .member-group-link {
+ color: $blue-normal;
+ }
+
.description {
p {
@include str-truncated;
@@ -168,6 +173,14 @@ ul.content-list {
}
}
+ .member-controls {
+ float: none;
+
+ @media (min-width: $screen-sm-min) {
+ float: right;
+ }
+ }
+
// When dragging a list item
&.ui-sortable-helper {
border-bottom: none;
diff --git a/app/assets/stylesheets/framework/logo.scss b/app/assets/stylesheets/framework/logo.scss
index c214eabcad7..a90e45bb5f4 100644
--- a/app/assets/stylesheets/framework/logo.scss
+++ b/app/assets/stylesheets/framework/logo.scss
@@ -37,6 +37,7 @@
0%, 10%, 100% {
fill: lighten($tanuki-yellow, 25%);
}
+
90% {
fill: $tanuki-yellow;
}
@@ -48,6 +49,7 @@
10%, 80% {
fill: $tanuki-orange;
}
+
20%, 90% {
fill: lighten($tanuki-orange, 25%);
}
@@ -59,6 +61,7 @@
10%, 80% {
fill: $tanuki-red;
}
+
20%, 90% {
fill: lighten($tanuki-red, 25%);
}
@@ -70,6 +73,7 @@
20%, 70% {
fill: $tanuki-red;
}
+
30%, 80% {
fill: lighten($tanuki-red, 25%);
}
@@ -81,6 +85,7 @@
30%, 60% {
fill: $tanuki-orange;
}
+
40%, 70% {
fill: lighten($tanuki-orange, 25%);
}
@@ -92,6 +97,7 @@
30%, 60% {
fill: $tanuki-red;
}
+
40%, 70% {
fill: lighten($tanuki-red, 25%);
}
@@ -103,6 +109,7 @@
40% {
fill: $tanuki-yellow;
}
+
60% {
fill: lighten($tanuki-yellow, 25%);
}
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 7fabf27a558..f84ca36d10f 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -34,6 +34,7 @@
&.active {
background: $gray-light;
+
a {
font-weight: 600;
}
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index ea43f4afc37..899db045b74 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -210,6 +210,7 @@
@media (max-width: $screen-xs-max) {
padding-bottom: 0;
width: 100%;
+
.btn, form, .dropdown, .dropdown-menu-toggle, .form-control {
margin: 0 0 10px;
display: block;
diff --git a/app/assets/stylesheets/framework/panels.scss b/app/assets/stylesheets/framework/panels.scss
index c6f30e144fd..5ba0486177f 100644
--- a/app/assets/stylesheets/framework/panels.scss
+++ b/app/assets/stylesheets/framework/panels.scss
@@ -13,6 +13,11 @@
.dropdown-menu-toggle {
line-height: 20px;
}
+
+ .badge {
+ margin-top: -2px;
+ margin-left: 5px;
+ }
}
.panel-body {
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index 79cd26714a3..e0708c65695 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -93,7 +93,7 @@
background: none;
.select2-search-field input {
- padding: $gl-padding / 2;
+ padding: 5px $gl-padding / 2;
font-size: 13px;
height: auto;
font-family: inherit;
@@ -101,7 +101,7 @@
}
.select2-search-choice {
- margin: 8px 0 0 8px;
+ margin: 5px 0 0 8px;
box-shadow: none;
border-color: $input-border;
color: $gl-text-color;
@@ -137,6 +137,7 @@
.select2-results {
max-height: 350px;
+
.select2-highlighted {
background: $gl-primary;
}
@@ -212,9 +213,11 @@
.group-image {
float: left;
}
+
.group-name {
font-weight: bold;
}
+
.group-path {
color: #999;
}
@@ -239,6 +242,7 @@
color: #aaa;
font-weight: normal;
}
+
.namespace-path {
margin-left: 10px;
font-weight: bolder;
diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss
index 0b0bd80c326..eb63a9f214b 100644
--- a/app/assets/stylesheets/framework/timeline.scss
+++ b/app/assets/stylesheets/framework/timeline.scss
@@ -48,6 +48,7 @@
&:before {
background: none;
}
+
.timeline-entry .timeline-entry-inner {
.timeline-icon {
display: none;
diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss
index e3154657c54..f4106641269 100644
--- a/app/assets/stylesheets/framework/tw_bootstrap.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap.scss
@@ -48,31 +48,40 @@
.clearfix {
@include clearfix();
}
+
.center-block {
@include center-block();
}
+
.pull-right {
float: right !important;
}
+
.pull-left {
float: left !important;
}
+
.hide {
display: none;
}
+
.show {
display: block !important;
}
+
.invisible {
visibility: hidden;
}
+
.text-hide {
@include text-hide();
}
+
.hidden {
display: none !important;
visibility: hidden !important;
}
+
.affix {
position: fixed;
}
@@ -146,6 +155,7 @@
padding: 6px 15px;
font-size: 13px;
font-weight: normal;
+
a {
color: #777;
}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index d099a884f54..8df0067fac1 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -106,6 +106,7 @@
@extend .table-bordered;
margin: 12px 0;
color: #5c5d5e;
+
th {
background: #f8fafc;
}
diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss
index 16ffbe57a99..a3acee299e3 100644
--- a/app/assets/stylesheets/highlight/dark.scss
+++ b/app/assets/stylesheets/highlight/dark.scss
@@ -55,68 +55,68 @@
color: #000 !important;
}
- .hll { background-color: #373b41 }
- .c { color: #969896 } /* Comment */
- .err { color: #c66 } /* Error */
- .k { color: #b294bb } /* Keyword */
- .l { color: #de935f } /* Literal */
- .n { color: #c5c8c6 } /* Name */
- .o { color: #8abeb7 } /* Operator */
- .p { color: #c5c8c6 } /* Punctuation */
- .cm { color: #969896 } /* Comment.Multiline */
- .cp { color: #969896 } /* Comment.Preproc */
- .c1 { color: #969896 } /* Comment.Single */
- .cs { color: #969896 } /* Comment.Special */
- .gd { color: #c66 } /* Generic.Deleted */
- .ge { font-style: italic } /* Generic.Emph */
- .gh { color: #c5c8c6; font-weight: bold } /* Generic.Heading */
- .gi { color: #b5bd68 } /* Generic.Inserted */
- .gp { color: #969896; font-weight: bold } /* Generic.Prompt */
- .gs { font-weight: bold } /* Generic.Strong */
- .gu { color: #8abeb7; font-weight: bold } /* Generic.Subheading */
- .kc { color: #b294bb } /* Keyword.Constant */
- .kd { color: #b294bb } /* Keyword.Declaration */
- .kn { color: #8abeb7 } /* Keyword.Namespace */
- .kp { color: #b294bb } /* Keyword.Pseudo */
- .kr { color: #b294bb } /* Keyword.Reserved */
- .kt { color: #f0c674 } /* Keyword.Type */
- .ld { color: #b5bd68 } /* Literal.Date */
- .m { color: #de935f } /* Literal.Number */
- .s { color: #b5bd68 } /* Literal.String */
- .na { color: #81a2be } /* Name.Attribute */
- .nb { color: #c5c8c6 } /* Name.Builtin */
- .nc { color: #f0c674 } /* Name.Class */
- .no { color: #c66 } /* Name.Constant */
- .nd { color: #8abeb7 } /* Name.Decorator */
- .ni { color: #c5c8c6 } /* Name.Entity */
- .ne { color: #c66 } /* Name.Exception */
- .nf { color: #81a2be } /* Name.Function */
- .nl { color: #c5c8c6 } /* Name.Label */
- .nn { color: #f0c674 } /* Name.Namespace */
- .nx { color: #81a2be } /* Name.Other */
- .py { color: #c5c8c6 } /* Name.Property */
- .nt { color: #8abeb7 } /* Name.Tag */
- .nv { color: #c66 } /* Name.Variable */
- .ow { color: #8abeb7 } /* Operator.Word */
- .w { color: #c5c8c6 } /* Text.Whitespace */
- .mf { color: #de935f } /* Literal.Number.Float */
- .mh { color: #de935f } /* Literal.Number.Hex */
- .mi { color: #de935f } /* Literal.Number.Integer */
- .mo { color: #de935f } /* Literal.Number.Oct */
- .sb { color: #b5bd68 } /* Literal.String.Backtick */
- .sc { color: #c5c8c6 } /* Literal.String.Char */
- .sd { color: #969896 } /* Literal.String.Doc */
- .s2 { color: #b5bd68 } /* Literal.String.Double */
- .se { color: #de935f } /* Literal.String.Escape */
- .sh { color: #b5bd68 } /* Literal.String.Heredoc */
- .si { color: #de935f } /* Literal.String.Interpol */
- .sx { color: #b5bd68 } /* Literal.String.Other */
- .sr { color: #b5bd68 } /* Literal.String.Regex */
- .s1 { color: #b5bd68 } /* Literal.String.Single */
- .ss { color: #b5bd68 } /* Literal.String.Symbol */
- .bp { color: #c5c8c6 } /* Name.Builtin.Pseudo */
- .vc { color: #c66 } /* Name.Variable.Class */
- .vg { color: #c66 } /* Name.Variable.Global */
- .vi { color: #c66 } /* Name.Variable.Instance */
- .il { color: #de935f } /* Literal.Number.Integer.Long */
+ .hll { background-color: #373b41; }
+ .c { color: #969896; } /* Comment */
+ .err { color: #c66; } /* Error */
+ .k { color: #b294bb; } /* Keyword */
+ .l { color: #de935f; } /* Literal */
+ .n { color: #c5c8c6; } /* Name */
+ .o { color: #8abeb7; } /* Operator */
+ .p { color: #c5c8c6; } /* Punctuation */
+ .cm { color: #969896; } /* Comment.Multiline */
+ .cp { color: #969896; } /* Comment.Preproc */
+ .c1 { color: #969896; } /* Comment.Single */
+ .cs { color: #969896; } /* Comment.Special */
+ .gd { color: #c66; } /* Generic.Deleted */
+ .ge { font-style: italic; } /* Generic.Emph */
+ .gh { color: #c5c8c6; font-weight: bold; } /* Generic.Heading */
+ .gi { color: #b5bd68; } /* Generic.Inserted */
+ .gp { color: #969896; font-weight: bold; } /* Generic.Prompt */
+ .gs { font-weight: bold; } /* Generic.Strong */
+ .gu { color: #8abeb7; font-weight: bold; } /* Generic.Subheading */
+ .kc { color: #b294bb; } /* Keyword.Constant */
+ .kd { color: #b294bb; } /* Keyword.Declaration */
+ .kn { color: #8abeb7; } /* Keyword.Namespace */
+ .kp { color: #b294bb; } /* Keyword.Pseudo */
+ .kr { color: #b294bb; } /* Keyword.Reserved */
+ .kt { color: #f0c674; } /* Keyword.Type */
+ .ld { color: #b5bd68; } /* Literal.Date */
+ .m { color: #de935f; } /* Literal.Number */
+ .s { color: #b5bd68; } /* Literal.String */
+ .na { color: #81a2be; } /* Name.Attribute */
+ .nb { color: #c5c8c6; } /* Name.Builtin */
+ .nc { color: #f0c674; } /* Name.Class */
+ .no { color: #c66; } /* Name.Constant */
+ .nd { color: #8abeb7; } /* Name.Decorator */
+ .ni { color: #c5c8c6; } /* Name.Entity */
+ .ne { color: #c66; } /* Name.Exception */
+ .nf { color: #81a2be; } /* Name.Function */
+ .nl { color: #c5c8c6; } /* Name.Label */
+ .nn { color: #f0c674; } /* Name.Namespace */
+ .nx { color: #81a2be; } /* Name.Other */
+ .py { color: #c5c8c6; } /* Name.Property */
+ .nt { color: #8abeb7; } /* Name.Tag */
+ .nv { color: #c66; } /* Name.Variable */
+ .ow { color: #8abeb7; } /* Operator.Word */
+ .w { color: #c5c8c6; } /* Text.Whitespace */
+ .mf { color: #de935f; } /* Literal.Number.Float */
+ .mh { color: #de935f; } /* Literal.Number.Hex */
+ .mi { color: #de935f; } /* Literal.Number.Integer */
+ .mo { color: #de935f; } /* Literal.Number.Oct */
+ .sb { color: #b5bd68; } /* Literal.String.Backtick */
+ .sc { color: #c5c8c6; } /* Literal.String.Char */
+ .sd { color: #969896; } /* Literal.String.Doc */
+ .s2 { color: #b5bd68; } /* Literal.String.Double */
+ .se { color: #de935f; } /* Literal.String.Escape */
+ .sh { color: #b5bd68; } /* Literal.String.Heredoc */
+ .si { color: #de935f; } /* Literal.String.Interpol */
+ .sx { color: #b5bd68; } /* Literal.String.Other */
+ .sr { color: #b5bd68; } /* Literal.String.Regex */
+ .s1 { color: #b5bd68; } /* Literal.String.Single */
+ .ss { color: #b5bd68; } /* Literal.String.Symbol */
+ .bp { color: #c5c8c6; } /* Name.Builtin.Pseudo */
+ .vc { color: #c66; } /* Name.Variable.Class */
+ .vg { color: #c66; } /* Name.Variable.Global */
+ .vi { color: #c66; } /* Name.Variable.Instance */
+ .il { color: #de935f; } /* Literal.Number.Integer.Long */
}
diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss
index 7de920e074b..e9228c94db9 100644
--- a/app/assets/stylesheets/highlight/monokai.scss
+++ b/app/assets/stylesheets/highlight/monokai.scss
@@ -55,65 +55,65 @@
color: #000 !important;
}
- .hll { background-color: #49483e }
- .c { color: #75715e } /* Comment */
- .err { color: #960050; background-color: #1e0010 } /* Error */
- .k { color: #66d9ef } /* Keyword */
- .l { color: #ae81ff } /* Literal */
- .n { color: #f8f8f2 } /* Name */
- .o { color: #f92672 } /* Operator */
- .p { color: #f8f8f2 } /* Punctuation */
- .cm { color: #75715e } /* Comment.Multiline */
- .cp { color: #75715e } /* Comment.Preproc */
- .c1 { color: #75715e } /* Comment.Single */
- .cs { color: #75715e } /* Comment.Special */
- .ge { font-style: italic } /* Generic.Emph */
- .gs { font-weight: bold } /* Generic.Strong */
- .kc { color: #66d9ef } /* Keyword.Constant */
- .kd { color: #66d9ef } /* Keyword.Declaration */
- .kn { color: #f92672 } /* Keyword.Namespace */
- .kp { color: #66d9ef } /* Keyword.Pseudo */
- .kr { color: #66d9ef } /* Keyword.Reserved */
- .kt { color: #66d9ef } /* Keyword.Type */
- .ld { color: #e6db74 } /* Literal.Date */
- .m { color: #ae81ff } /* Literal.Number */
- .s { color: #e6db74 } /* Literal.String */
- .na { color: #a6e22e } /* Name.Attribute */
- .nb { color: #f8f8f2 } /* Name.Builtin */
- .nc { color: #a6e22e } /* Name.Class */
- .no { color: #66d9ef } /* Name.Constant */
- .nd { color: #a6e22e } /* Name.Decorator */
- .ni { color: #f8f8f2 } /* Name.Entity */
- .ne { color: #a6e22e } /* Name.Exception */
- .nf { color: #a6e22e } /* Name.Function */
- .nl { color: #f8f8f2 } /* Name.Label */
- .nn { color: #f8f8f2 } /* Name.Namespace */
- .nx { color: #a6e22e } /* Name.Other */
- .py { color: #f8f8f2 } /* Name.Property */
- .nt { color: #f92672 } /* Name.Tag */
- .nv { color: #f8f8f2 } /* Name.Variable */
- .ow { color: #f92672 } /* Operator.Word */
- .w { color: #f8f8f2 } /* Text.Whitespace */
- .mf { color: #ae81ff } /* Literal.Number.Float */
- .mh { color: #ae81ff } /* Literal.Number.Hex */
- .mi { color: #ae81ff } /* Literal.Number.Integer */
- .mo { color: #ae81ff } /* Literal.Number.Oct */
- .sb { color: #e6db74 } /* Literal.String.Backtick */
- .sc { color: #e6db74 } /* Literal.String.Char */
- .sd { color: #e6db74 } /* Literal.String.Doc */
- .s2 { color: #e6db74 } /* Literal.String.Double */
- .se { color: #ae81ff } /* Literal.String.Escape */
- .sh { color: #e6db74 } /* Literal.String.Heredoc */
- .si { color: #e6db74 } /* Literal.String.Interpol */
- .sx { color: #e6db74 } /* Literal.String.Other */
- .sr { color: #e6db74 } /* Literal.String.Regex */
- .s1 { color: #e6db74 } /* Literal.String.Single */
- .ss { color: #e6db74 } /* Literal.String.Symbol */
- .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
- .vc { color: #f8f8f2 } /* Name.Variable.Class */
- .vg { color: #f8f8f2 } /* Name.Variable.Global */
- .vi { color: #f8f8f2 } /* Name.Variable.Instance */
- .il { color: #ae81ff } /* Literal.Number.Integer.Long */
+ .hll { background-color: #49483e; }
+ .c { color: #75715e; } /* Comment */
+ .err { color: #960050; background-color: #1e0010; } /* Error */
+ .k { color: #66d9ef; } /* Keyword */
+ .l { color: #ae81ff; } /* Literal */
+ .n { color: #f8f8f2; } /* Name */
+ .o { color: #f92672; } /* Operator */
+ .p { color: #f8f8f2; } /* Punctuation */
+ .cm { color: #75715e; } /* Comment.Multiline */
+ .cp { color: #75715e; } /* Comment.Preproc */
+ .c1 { color: #75715e; } /* Comment.Single */
+ .cs { color: #75715e; } /* Comment.Special */
+ .ge { font-style: italic; } /* Generic.Emph */
+ .gs { font-weight: bold; } /* Generic.Strong */
+ .kc { color: #66d9ef; } /* Keyword.Constant */
+ .kd { color: #66d9ef; } /* Keyword.Declaration */
+ .kn { color: #f92672; } /* Keyword.Namespace */
+ .kp { color: #66d9ef; } /* Keyword.Pseudo */
+ .kr { color: #66d9ef; } /* Keyword.Reserved */
+ .kt { color: #66d9ef; } /* Keyword.Type */
+ .ld { color: #e6db74; } /* Literal.Date */
+ .m { color: #ae81ff; } /* Literal.Number */
+ .s { color: #e6db74; } /* Literal.String */
+ .na { color: #a6e22e; } /* Name.Attribute */
+ .nb { color: #f8f8f2; } /* Name.Builtin */
+ .nc { color: #a6e22e; } /* Name.Class */
+ .no { color: #66d9ef; } /* Name.Constant */
+ .nd { color: #a6e22e; } /* Name.Decorator */
+ .ni { color: #f8f8f2; } /* Name.Entity */
+ .ne { color: #a6e22e; } /* Name.Exception */
+ .nf { color: #a6e22e; } /* Name.Function */
+ .nl { color: #f8f8f2; } /* Name.Label */
+ .nn { color: #f8f8f2; } /* Name.Namespace */
+ .nx { color: #a6e22e; } /* Name.Other */
+ .py { color: #f8f8f2; } /* Name.Property */
+ .nt { color: #f92672; } /* Name.Tag */
+ .nv { color: #f8f8f2; } /* Name.Variable */
+ .ow { color: #f92672; } /* Operator.Word */
+ .w { color: #f8f8f2; } /* Text.Whitespace */
+ .mf { color: #ae81ff; } /* Literal.Number.Float */
+ .mh { color: #ae81ff; } /* Literal.Number.Hex */
+ .mi { color: #ae81ff; } /* Literal.Number.Integer */
+ .mo { color: #ae81ff; } /* Literal.Number.Oct */
+ .sb { color: #e6db74; } /* Literal.String.Backtick */
+ .sc { color: #e6db74; } /* Literal.String.Char */
+ .sd { color: #e6db74; } /* Literal.String.Doc */
+ .s2 { color: #e6db74; } /* Literal.String.Double */
+ .se { color: #ae81ff; } /* Literal.String.Escape */
+ .sh { color: #e6db74; } /* Literal.String.Heredoc */
+ .si { color: #e6db74; } /* Literal.String.Interpol */
+ .sx { color: #e6db74; } /* Literal.String.Other */
+ .sr { color: #e6db74; } /* Literal.String.Regex */
+ .s1 { color: #e6db74; } /* Literal.String.Single */
+ .ss { color: #e6db74; } /* Literal.String.Symbol */
+ .bp { color: #f8f8f2; } /* Name.Builtin.Pseudo */
+ .vc { color: #f8f8f2; } /* Name.Variable.Class */
+ .vg { color: #f8f8f2; } /* Name.Variable.Global */
+ .vi { color: #f8f8f2; } /* Name.Variable.Instance */
+ .il { color: #ae81ff; } /* Literal.Number.Integer.Long */
.gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
.gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */
.gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */
diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss
index b11499c71ee..c3c7773b9e2 100644
--- a/app/assets/stylesheets/highlight/solarized_dark.scss
+++ b/app/assets/stylesheets/highlight/solarized_dark.scss
@@ -72,72 +72,72 @@
green #859900 operators, other keywords
*/
- .c { color: #586e75 } /* Comment */
- .err { color: #93a1a1 } /* Error */
- .g { color: #93a1a1 } /* Generic */
- .k { color: #859900 } /* Keyword */
- .l { color: #93a1a1 } /* Literal */
- .n { color: #93a1a1 } /* Name */
- .o { color: #859900 } /* Operator */
- .x { color: #cb4b16 } /* Other */
- .p { color: #93a1a1 } /* Punctuation */
- .cm { color: #586e75 } /* Comment.Multiline */
- .cp { color: #859900 } /* Comment.Preproc */
- .c1 { color: #586e75 } /* Comment.Single */
- .cs { color: #859900 } /* Comment.Special */
- .gd { color: #2aa198 } /* Generic.Deleted */
- .ge { color: #93a1a1; font-style: italic } /* Generic.Emph */
- .gr { color: #dc322f } /* Generic.Error */
- .gh { color: #cb4b16 } /* Generic.Heading */
- .gi { color: #859900 } /* Generic.Inserted */
- .go { color: #93a1a1 } /* Generic.Output */
- .gp { color: #93a1a1 } /* Generic.Prompt */
- .gs { color: #93a1a1; font-weight: bold } /* Generic.Strong */
- .gu { color: #cb4b16 } /* Generic.Subheading */
- .gt { color: #93a1a1 } /* Generic.Traceback */
- .kc { color: #cb4b16 } /* Keyword.Constant */
- .kd { color: #268bd2 } /* Keyword.Declaration */
- .kn { color: #859900 } /* Keyword.Namespace */
- .kp { color: #859900 } /* Keyword.Pseudo */
- .kr { color: #268bd2 } /* Keyword.Reserved */
- .kt { color: #dc322f } /* Keyword.Type */
- .ld { color: #93a1a1 } /* Literal.Date */
- .m { color: #2aa198 } /* Literal.Number */
- .s { color: #2aa198 } /* Literal.String */
- .na { color: #93a1a1 } /* Name.Attribute */
- .nb { color: #b58900 } /* Name.Builtin */
- .nc { color: #268bd2 } /* Name.Class */
- .no { color: #cb4b16 } /* Name.Constant */
- .nd { color: #268bd2 } /* Name.Decorator */
- .ni { color: #cb4b16 } /* Name.Entity */
- .ne { color: #cb4b16 } /* Name.Exception */
- .nf { color: #268bd2 } /* Name.Function */
- .nl { color: #93a1a1 } /* Name.Label */
- .nn { color: #93a1a1 } /* Name.Namespace */
- .nx { color: #93a1a1 } /* Name.Other */
- .py { color: #93a1a1 } /* Name.Property */
- .nt { color: #268bd2 } /* Name.Tag */
- .nv { color: #268bd2 } /* Name.Variable */
- .ow { color: #859900 } /* Operator.Word */
- .w { color: #93a1a1 } /* Text.Whitespace */
- .mf { color: #2aa198 } /* Literal.Number.Float */
- .mh { color: #2aa198 } /* Literal.Number.Hex */
- .mi { color: #2aa198 } /* Literal.Number.Integer */
- .mo { color: #2aa198 } /* Literal.Number.Oct */
- .sb { color: #586e75 } /* Literal.String.Backtick */
- .sc { color: #2aa198 } /* Literal.String.Char */
- .sd { color: #93a1a1 } /* Literal.String.Doc */
- .s2 { color: #2aa198 } /* Literal.String.Double */
- .se { color: #cb4b16 } /* Literal.String.Escape */
- .sh { color: #93a1a1 } /* Literal.String.Heredoc */
- .si { color: #2aa198 } /* Literal.String.Interpol */
- .sx { color: #2aa198 } /* Literal.String.Other */
- .sr { color: #dc322f } /* Literal.String.Regex */
- .s1 { color: #2aa198 } /* Literal.String.Single */
- .ss { color: #2aa198 } /* Literal.String.Symbol */
- .bp { color: #268bd2 } /* Name.Builtin.Pseudo */
- .vc { color: #268bd2 } /* Name.Variable.Class */
- .vg { color: #268bd2 } /* Name.Variable.Global */
- .vi { color: #268bd2 } /* Name.Variable.Instance */
- .il { color: #2aa198 } /* Literal.Number.Integer.Long */
+ .c { color: #586e75; } /* Comment */
+ .err { color: #93a1a1; } /* Error */
+ .g { color: #93a1a1; } /* Generic */
+ .k { color: #859900; } /* Keyword */
+ .l { color: #93a1a1; } /* Literal */
+ .n { color: #93a1a1; } /* Name */
+ .o { color: #859900; } /* Operator */
+ .x { color: #cb4b16; } /* Other */
+ .p { color: #93a1a1; } /* Punctuation */
+ .cm { color: #586e75; } /* Comment.Multiline */
+ .cp { color: #859900; } /* Comment.Preproc */
+ .c1 { color: #586e75; } /* Comment.Single */
+ .cs { color: #859900; } /* Comment.Special */
+ .gd { color: #2aa198; } /* Generic.Deleted */
+ .ge { color: #93a1a1; font-style: italic; } /* Generic.Emph */
+ .gr { color: #dc322f; } /* Generic.Error */
+ .gh { color: #cb4b16; } /* Generic.Heading */
+ .gi { color: #859900; } /* Generic.Inserted */
+ .go { color: #93a1a1; } /* Generic.Output */
+ .gp { color: #93a1a1; } /* Generic.Prompt */
+ .gs { color: #93a1a1; font-weight: bold; } /* Generic.Strong */
+ .gu { color: #cb4b16; } /* Generic.Subheading */
+ .gt { color: #93a1a1; } /* Generic.Traceback */
+ .kc { color: #cb4b16; } /* Keyword.Constant */
+ .kd { color: #268bd2; } /* Keyword.Declaration */
+ .kn { color: #859900; } /* Keyword.Namespace */
+ .kp { color: #859900; } /* Keyword.Pseudo */
+ .kr { color: #268bd2; } /* Keyword.Reserved */
+ .kt { color: #dc322f; } /* Keyword.Type */
+ .ld { color: #93a1a1; } /* Literal.Date */
+ .m { color: #2aa198; } /* Literal.Number */
+ .s { color: #2aa198; } /* Literal.String */
+ .na { color: #93a1a1; } /* Name.Attribute */
+ .nb { color: #b58900; } /* Name.Builtin */
+ .nc { color: #268bd2; } /* Name.Class */
+ .no { color: #cb4b16; } /* Name.Constant */
+ .nd { color: #268bd2; } /* Name.Decorator */
+ .ni { color: #cb4b16; } /* Name.Entity */
+ .ne { color: #cb4b16; } /* Name.Exception */
+ .nf { color: #268bd2; } /* Name.Function */
+ .nl { color: #93a1a1; } /* Name.Label */
+ .nn { color: #93a1a1; } /* Name.Namespace */
+ .nx { color: #93a1a1; } /* Name.Other */
+ .py { color: #93a1a1; } /* Name.Property */
+ .nt { color: #268bd2; } /* Name.Tag */
+ .nv { color: #268bd2; } /* Name.Variable */
+ .ow { color: #859900; } /* Operator.Word */
+ .w { color: #93a1a1; } /* Text.Whitespace */
+ .mf { color: #2aa198; } /* Literal.Number.Float */
+ .mh { color: #2aa198; } /* Literal.Number.Hex */
+ .mi { color: #2aa198; } /* Literal.Number.Integer */
+ .mo { color: #2aa198; } /* Literal.Number.Oct */
+ .sb { color: #586e75; } /* Literal.String.Backtick */
+ .sc { color: #2aa198; } /* Literal.String.Char */
+ .sd { color: #93a1a1; } /* Literal.String.Doc */
+ .s2 { color: #2aa198; } /* Literal.String.Double */
+ .se { color: #cb4b16; } /* Literal.String.Escape */
+ .sh { color: #93a1a1; } /* Literal.String.Heredoc */
+ .si { color: #2aa198; } /* Literal.String.Interpol */
+ .sx { color: #2aa198; } /* Literal.String.Other */
+ .sr { color: #dc322f; } /* Literal.String.Regex */
+ .s1 { color: #2aa198; } /* Literal.String.Single */
+ .ss { color: #2aa198; } /* Literal.String.Symbol */
+ .bp { color: #268bd2; } /* Name.Builtin.Pseudo */
+ .vc { color: #268bd2; } /* Name.Variable.Class */
+ .vg { color: #268bd2; } /* Name.Variable.Global */
+ .vi { color: #268bd2; } /* Name.Variable.Instance */
+ .il { color: #2aa198; } /* Literal.Number.Integer.Long */
}
diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss
index 657bb5e3cd9..5956a28cafe 100644
--- a/app/assets/stylesheets/highlight/solarized_light.scss
+++ b/app/assets/stylesheets/highlight/solarized_light.scss
@@ -78,72 +78,72 @@
green #859900 operators, other keywords
*/
- .c { color: #93a1a1 } /* Comment */
- .err { color: #586e75 } /* Error */
- .g { color: #586e75 } /* Generic */
- .k { color: #859900 } /* Keyword */
- .l { color: #586e75 } /* Literal */
- .n { color: #586e75 } /* Name */
- .o { color: #859900 } /* Operator */
- .x { color: #cb4b16 } /* Other */
- .p { color: #586e75 } /* Punctuation */
- .cm { color: #93a1a1 } /* Comment.Multiline */
- .cp { color: #859900 } /* Comment.Preproc */
- .c1 { color: #93a1a1 } /* Comment.Single */
- .cs { color: #859900 } /* Comment.Special */
- .gd { color: #2aa198 } /* Generic.Deleted */
- .ge { color: #586e75; font-style: italic } /* Generic.Emph */
- .gr { color: #dc322f } /* Generic.Error */
- .gh { color: #cb4b16 } /* Generic.Heading */
- .gi { color: #859900 } /* Generic.Inserted */
- .go { color: #586e75 } /* Generic.Output */
- .gp { color: #586e75 } /* Generic.Prompt */
- .gs { color: #586e75; font-weight: bold } /* Generic.Strong */
- .gu { color: #cb4b16 } /* Generic.Subheading */
- .gt { color: #586e75 } /* Generic.Traceback */
- .kc { color: #cb4b16 } /* Keyword.Constant */
- .kd { color: #268bd2 } /* Keyword.Declaration */
- .kn { color: #859900 } /* Keyword.Namespace */
- .kp { color: #859900 } /* Keyword.Pseudo */
- .kr { color: #268bd2 } /* Keyword.Reserved */
- .kt { color: #dc322f } /* Keyword.Type */
- .ld { color: #586e75 } /* Literal.Date */
- .m { color: #2aa198 } /* Literal.Number */
- .s { color: #2aa198 } /* Literal.String */
- .na { color: #586e75 } /* Name.Attribute */
- .nb { color: #b58900 } /* Name.Builtin */
- .nc { color: #268bd2 } /* Name.Class */
- .no { color: #cb4b16 } /* Name.Constant */
- .nd { color: #268bd2 } /* Name.Decorator */
- .ni { color: #cb4b16 } /* Name.Entity */
- .ne { color: #cb4b16 } /* Name.Exception */
- .nf { color: #268bd2 } /* Name.Function */
- .nl { color: #586e75 } /* Name.Label */
- .nn { color: #586e75 } /* Name.Namespace */
- .nx { color: #586e75 } /* Name.Other */
- .py { color: #586e75 } /* Name.Property */
- .nt { color: #268bd2 } /* Name.Tag */
- .nv { color: #268bd2 } /* Name.Variable */
- .ow { color: #859900 } /* Operator.Word */
- .w { color: #586e75 } /* Text.Whitespace */
- .mf { color: #2aa198 } /* Literal.Number.Float */
- .mh { color: #2aa198 } /* Literal.Number.Hex */
- .mi { color: #2aa198 } /* Literal.Number.Integer */
- .mo { color: #2aa198 } /* Literal.Number.Oct */
- .sb { color: #93a1a1 } /* Literal.String.Backtick */
- .sc { color: #2aa198 } /* Literal.String.Char */
- .sd { color: #586e75 } /* Literal.String.Doc */
- .s2 { color: #2aa198 } /* Literal.String.Double */
- .se { color: #cb4b16 } /* Literal.String.Escape */
- .sh { color: #586e75 } /* Literal.String.Heredoc */
- .si { color: #2aa198 } /* Literal.String.Interpol */
- .sx { color: #2aa198 } /* Literal.String.Other */
- .sr { color: #dc322f } /* Literal.String.Regex */
- .s1 { color: #2aa198 } /* Literal.String.Single */
- .ss { color: #2aa198 } /* Literal.String.Symbol */
- .bp { color: #268bd2 } /* Name.Builtin.Pseudo */
- .vc { color: #268bd2 } /* Name.Variable.Class */
- .vg { color: #268bd2 } /* Name.Variable.Global */
- .vi { color: #268bd2 } /* Name.Variable.Instance */
- .il { color: #2aa198 } /* Literal.Number.Integer.Long */
+ .c { color: #93a1a1; } /* Comment */
+ .err { color: #586e75; } /* Error */
+ .g { color: #586e75; } /* Generic */
+ .k { color: #859900; } /* Keyword */
+ .l { color: #586e75; } /* Literal */
+ .n { color: #586e75; } /* Name */
+ .o { color: #859900; } /* Operator */
+ .x { color: #cb4b16; } /* Other */
+ .p { color: #586e75; } /* Punctuation */
+ .cm { color: #93a1a1; } /* Comment.Multiline */
+ .cp { color: #859900; } /* Comment.Preproc */
+ .c1 { color: #93a1a1; } /* Comment.Single */
+ .cs { color: #859900; } /* Comment.Special */
+ .gd { color: #2aa198; } /* Generic.Deleted */
+ .ge { color: #586e75; font-style: italic; } /* Generic.Emph */
+ .gr { color: #dc322f; } /* Generic.Error */
+ .gh { color: #cb4b16; } /* Generic.Heading */
+ .gi { color: #859900; } /* Generic.Inserted */
+ .go { color: #586e75; } /* Generic.Output */
+ .gp { color: #586e75; } /* Generic.Prompt */
+ .gs { color: #586e75; font-weight: bold; } /* Generic.Strong */
+ .gu { color: #cb4b16; } /* Generic.Subheading */
+ .gt { color: #586e75; } /* Generic.Traceback */
+ .kc { color: #cb4b16; } /* Keyword.Constant */
+ .kd { color: #268bd2; } /* Keyword.Declaration */
+ .kn { color: #859900; } /* Keyword.Namespace */
+ .kp { color: #859900; } /* Keyword.Pseudo */
+ .kr { color: #268bd2; } /* Keyword.Reserved */
+ .kt { color: #dc322f; } /* Keyword.Type */
+ .ld { color: #586e75; } /* Literal.Date */
+ .m { color: #2aa198; } /* Literal.Number */
+ .s { color: #2aa198; } /* Literal.String */
+ .na { color: #586e75; } /* Name.Attribute */
+ .nb { color: #b58900; } /* Name.Builtin */
+ .nc { color: #268bd2; } /* Name.Class */
+ .no { color: #cb4b16; } /* Name.Constant */
+ .nd { color: #268bd2; } /* Name.Decorator */
+ .ni { color: #cb4b16; } /* Name.Entity */
+ .ne { color: #cb4b16; } /* Name.Exception */
+ .nf { color: #268bd2; } /* Name.Function */
+ .nl { color: #586e75; } /* Name.Label */
+ .nn { color: #586e75; } /* Name.Namespace */
+ .nx { color: #586e75; } /* Name.Other */
+ .py { color: #586e75; } /* Name.Property */
+ .nt { color: #268bd2; } /* Name.Tag */
+ .nv { color: #268bd2; } /* Name.Variable */
+ .ow { color: #859900; } /* Operator.Word */
+ .w { color: #586e75; } /* Text.Whitespace */
+ .mf { color: #2aa198; } /* Literal.Number.Float */
+ .mh { color: #2aa198; } /* Literal.Number.Hex */
+ .mi { color: #2aa198; } /* Literal.Number.Integer */
+ .mo { color: #2aa198; } /* Literal.Number.Oct */
+ .sb { color: #93a1a1; } /* Literal.String.Backtick */
+ .sc { color: #2aa198; } /* Literal.String.Char */
+ .sd { color: #586e75; } /* Literal.String.Doc */
+ .s2 { color: #2aa198; } /* Literal.String.Double */
+ .se { color: #cb4b16; } /* Literal.String.Escape */
+ .sh { color: #586e75; } /* Literal.String.Heredoc */
+ .si { color: #2aa198; } /* Literal.String.Interpol */
+ .sx { color: #2aa198; } /* Literal.String.Other */
+ .sr { color: #dc322f; } /* Literal.String.Regex */
+ .s1 { color: #2aa198; } /* Literal.String.Single */
+ .ss { color: #2aa198; } /* Literal.String.Symbol */
+ .bp { color: #268bd2; } /* Name.Builtin.Pseudo */
+ .vc { color: #268bd2; } /* Name.Variable.Class */
+ .vg { color: #268bd2; } /* Name.Variable.Global */
+ .vi { color: #268bd2; } /* Name.Variable.Instance */
+ .il { color: #2aa198; } /* Literal.Number.Integer.Long */
}
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
index 36a80a916b2..6f31a5235c0 100644
--- a/app/assets/stylesheets/highlight/white.scss
+++ b/app/assets/stylesheets/highlight/white.scss
@@ -86,7 +86,7 @@
background-color: #fafe3d !important;
}
- .hll { background-color: #f8f8f8 }
+ .hll { background-color: #f8f8f8; }
.c { color: #998; font-style: italic; }
.err { color: #a61717; background-color: #e3d2d2; }
.k { font-weight: bold; }
diff --git a/app/assets/stylesheets/mailers/repository_push_email.scss b/app/assets/stylesheets/mailers/repository_push_email.scss
index 5bfe9bcb443..8d1a6020ca4 100644
--- a/app/assets/stylesheets/mailers/repository_push_email.scss
+++ b/app/assets/stylesheets/mailers/repository_push_email.scss
@@ -78,7 +78,7 @@ span.highlight_word {
background-color: #fafe3d !important;
}
-.hll { background-color: #f8f8f8 }
+.hll { background-color: #f8f8f8; }
.c { color: #998; font-style: italic; }
.err { color: #a61717; background-color: #e3d2d2; }
.k { font-weight: bold; }
diff --git a/app/assets/stylesheets/notify.scss b/app/assets/stylesheets/notify.scss
index fc12964872d..ced8c4a9907 100644
--- a/app/assets/stylesheets/notify.scss
+++ b/app/assets/stylesheets/notify.scss
@@ -2,22 +2,28 @@ img {
max-width: 100%;
height: auto;
}
+
p.details {
font-style: italic;
- color: #777
+ color: #777;
}
+
.footer > p {
font-size: small;
- color: #777
+ color: #777;
}
+
pre.commit-message {
white-space: pre-wrap;
}
+
.file-stats > a {
text-decoration: none;
+
> .new-file {
color: #090;
}
+
> .deleted-file {
color: #b00;
}
diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss
index 8f71381f5c4..140d589024b 100644
--- a/app/assets/stylesheets/pages/admin.scss
+++ b/app/assets/stylesheets/pages/admin.scss
@@ -22,7 +22,7 @@
.admin-filter form {
.select2-container {
- width: 100%
+ width: 100%;
}
.controls {
@@ -31,7 +31,7 @@
.form-actions {
padding-left: 130px;
- background: #fff
+ background: #fff;
}
.visibility-levels {
@@ -106,26 +106,33 @@
.table {
table-layout: fixed;
}
+
.subheading {
padding-bottom: $gl-padding;
}
+
.message {
word-wrap: break-word;
}
+
.btn {
white-space: normal;
padding: $gl-btn-padding;
}
+
th {
width: 15%;
+
&.wide {
width: 55%;
}
}
+
@media (max-width: $screen-sm-max) {
th {
width: 100%;
}
+
td {
width: 100%;
float: left;
@@ -137,6 +144,7 @@
margin-left: $btn-side-margin;
margin-top: 3px;
}
+
span {
font-size: 19px;
}
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index 194a39a8377..2fbf0cf34bf 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -137,6 +137,7 @@
.retry-link {
color: $gl-link-color;
+
&:hover {
text-decoration: underline;
}
@@ -218,6 +219,7 @@
.build-detail-row {
margin-bottom: 5px;
+
&:last-of-type {
margin-bottom: 0;
}
@@ -233,3 +235,9 @@
right: 0;
margin-top: -17px;
}
+
+@media (min-width: $screen-md-min) {
+ .sub-nav.build {
+ width: calc(100% + #{$gutter_width});
+ }
+}
diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss
index 53ec0002afe..264e7e01a34 100644
--- a/app/assets/stylesheets/pages/commit.scss
+++ b/app/assets/stylesheets/pages/commit.scss
@@ -51,6 +51,7 @@
margin-left: 4px;
}
}
+
.commit-committer-link,
.commit-author-link {
color: $gl-gray;
@@ -108,21 +109,25 @@
line-height: 20px;
}
}
+
.new-file {
a {
color: $gl-text-green;
}
}
+
.renamed-file {
a {
color: $gl-text-orange;
}
}
+
.deleted-file {
a {
color: $gl-text-red;
}
}
+
.edit-file {
a {
color: $gl-text-color;
@@ -158,6 +163,7 @@
position: absolute;
z-index: 1;
}
+
> textarea {
background-color: rgba(0, 0, 0, 0.0);
font-family: inherit;
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index dc57a837155..2b5621e20d6 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -161,6 +161,7 @@
.branch-commit {
color: $gl-gray;
+
.commit-id, .commit-row-message {
color: $gl-gray;
}
diff --git a/app/assets/stylesheets/pages/dashboard.scss b/app/assets/stylesheets/pages/dashboard.scss
index 42928ee279c..76225ed8d06 100644
--- a/app/assets/stylesheets/pages/dashboard.scss
+++ b/app/assets/stylesheets/pages/dashboard.scss
@@ -5,6 +5,7 @@
background: $background-color;
border-top-left-radius: 0;
}
+
border-top-left-radius: 0;
}
}
@@ -17,6 +18,7 @@
float: left;
@extend .col-md-2;
}
+
.btn {
margin-left: 5px;
float: left;
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index b8ef76cc74e..bdc82a8f0f5 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -33,6 +33,19 @@
font-size: smaller;
}
}
+
+ .file-title {
+ cursor: pointer;
+
+ &:hover {
+ background-color: $dark-background-color;
+ }
+
+ .diff-toggle-caret {
+ padding-right: 6px;
+ }
+ }
+
.diff-content {
overflow: auto;
overflow-y: hidden;
@@ -123,15 +136,18 @@
max-width: 50px;
width: 35px;
@include user-select(none);
+
a {
float: left;
width: 35px;
font-weight: normal;
+
&:hover {
text-decoration: underline;
}
}
}
+
.line_content {
display: block;
margin: 0;
@@ -151,10 +167,12 @@
white-space: pre-wrap;
}
}
+
.image {
background: #ddd;
text-align: center;
padding: 30px;
+
.wrap {
display: inline-block;
}
@@ -163,6 +181,7 @@
display: inline-block;
background-color: #fff;
line-height: 0;
+
img {
border: 1px solid #fff;
background-image: linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%),
@@ -171,6 +190,7 @@
background-position: 0 0, 5px 5px;
max-width: 100%;
}
+
&.deleted {
border: 1px solid $deleted;
}
@@ -179,6 +199,7 @@
border: 1px solid $added;
}
}
+
.image-info {
font-size: 12px;
margin: 5px 0 0;
@@ -193,6 +214,7 @@
margin: auto;
position: relative;
}
+
.swipe-wrap {
overflow: hidden;
border-left: 1px solid #999;
@@ -201,10 +223,12 @@
top: 13px;
right: 7px;
}
+
.frame {
top: 0;
right: 0;
position: absolute;
+
&.deleted {
margin: 0;
display: block;
@@ -212,6 +236,7 @@
right: 7px;
}
}
+
.swipe-bar {
display: block;
height: 100%;
@@ -219,14 +244,17 @@
z-index: 100;
position: absolute;
cursor: pointer;
+
&:hover {
.top-handle {
background-position: -15px 3px;
}
+
.bottom-handle {
background-position: -15px -11px;
}
}
+
.top-handle {
display: block;
height: 14px;
@@ -235,6 +263,7 @@
top: 0;
background: image-url('swipemode_sprites.gif') 0 3px no-repeat;
}
+
.bottom-handle {
display: block;
height: 14px;
@@ -252,12 +281,14 @@
margin: auto;
position: relative;
}
+
.frame.added, .frame.deleted {
position: absolute;
display: block;
top: 0;
left: 0;
}
+
.controls {
display: block;
height: 14px;
@@ -311,6 +342,7 @@
}
//.view.onion-skin
}
+
.view-modes {
padding: 10px;
text-align: center;
@@ -328,19 +360,24 @@
border-left: 1px solid #c1c1c1;
padding: 0 12px 0 16px;
cursor: pointer;
+
&:first-child {
border-left: none;
}
+
&:hover {
text-decoration: underline;
}
+
&.active {
&:hover {
text-decoration: none;
}
+
cursor: default;
color: #333;
}
+
&.disabled {
display: none;
}
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index fcc5f32c738..029dabd2138 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -15,6 +15,7 @@
.cancel-btn {
color: #b94a48;
+
&:hover {
color: #b94a48;
}
@@ -70,16 +71,20 @@
.soft-wrap-toggle {
margin: 0 $btn-side-margin;
+
.soft-wrap {
display: block;
}
+
.no-wrap {
display: none;
}
+
&.soft-wrap-active {
.soft-wrap {
display: none;
}
+
.no-wrap {
display: block;
}
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index 3f19e920166..820cc0fc991 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -52,13 +52,13 @@
}
}
-.table.builds.environments {
+.table.ci-table.environments {
.icon-container {
width: 20px;
text-align: center;
}
-
+
.branch-commit {
.commit-id {
margin-right: 0;
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 789d6237df8..5d9a76dac05 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -78,6 +78,7 @@
margin-bottom: 0;
}
}
+
.event-note-icon {
color: #777;
float: left;
@@ -86,6 +87,7 @@
margin-right: 5px;
}
}
+
.event_icon {
position: relative;
float: right;
@@ -95,12 +97,13 @@
background: $gray-light;
margin-left: 10px;
top: -6px;
+
img {
width: 20px;
}
}
- &:last-child { border: none }
+ &:last-child { border: none; }
.event_commits {
li {
@@ -109,6 +112,7 @@
padding: 3px;
padding-left: 0;
border: none;
+
.commit-row-title {
font-size: $gl-font-size;
}
@@ -117,6 +121,7 @@
&.commits-stat {
display: block;
padding: 0 3px 0 0;
+
&:hover {
background: none;
}
@@ -158,6 +163,7 @@
overflow: visible;
max-width: 100%;
}
+
.avatar {
display: none;
}
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index 185ce970e71..ee2a398f031 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -1,17 +1,3 @@
-.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 {
@include str-truncated(90%);
}
@@ -48,6 +34,7 @@
.group-right-buttons {
position: absolute;
right: 16px;
+
.btn {
@include btn-gray;
padding: 3px 10px;
diff --git a/app/assets/stylesheets/pages/help.scss b/app/assets/stylesheets/pages/help.scss
index 00ab42bec5c..a48b4c65db8 100644
--- a/app/assets/stylesheets/pages/help.scss
+++ b/app/assets/stylesheets/pages/help.scss
@@ -23,28 +23,28 @@
color: #555;
tbody:first-child tr:first-child {
- padding-top: 0
+ padding-top: 0;
}
th {
padding-top: 15px;
line-height: 1.5;
color: #333;
- text-align: left
+ text-align: left;
}
td {
padding-top: 3px;
padding-bottom: 3px;
vertical-align: top;
- line-height: 20px
+ line-height: 20px;
}
.shortcut {
padding-right: 10px;
color: #999;
text-align: right;
- white-space: nowrap
+ white-space: nowrap;
}
.key {
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 41079b6eeb5..230b927a17d 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -27,6 +27,7 @@
margin-right: 5px;
margin-bottom: 5px;
display: inline-block;
+
.color-label {
padding: 6px 10px;
}
@@ -128,7 +129,7 @@
}
.selectbox {
- display: none
+ display: none;
}
.btn-clipboard {
@@ -199,7 +200,7 @@
display: none;
/* Small devices (tablets, 768px and up) */
@media (min-width: $screen-sm-min) {
- display: block
+ display: block;
}
width: $sidebar_collapsed_width;
@@ -276,7 +277,7 @@
}
&.btn-primary {
- @extend .btn-primary
+ @extend .btn-primary;
}
}
@@ -400,6 +401,7 @@
.js-issuable-selector {
width: 100%;
}
+
@media (max-width: $screen-sm-max) {
margin-bottom: $gl-padding;
}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 3ac34cbc829..623da67a239 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -37,6 +37,7 @@ ul.related-merge-requests > li {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
+
.merge-request-id {
flex-shrink: 0;
}
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index 701c29a3986..9bac6d46355 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -1,5 +1,6 @@
.suggest-colors {
margin-top: 5px;
+
a {
border-radius: 4px;
width: 30px;
diff --git a/app/assets/stylesheets/pages/lint.scss b/app/assets/stylesheets/pages/lint.scss
index 6926448519e..8290519dc25 100644
--- a/app/assets/stylesheets/pages/lint.scss
+++ b/app/assets/stylesheets/pages/lint.scss
@@ -3,6 +3,7 @@
font-size: 19px;
color: red;
}
+
.correct-syntax {
font-size: 19px;
color: #47a447;
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index a5ca509163d..4c0c0839fe2 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -17,6 +17,7 @@
line-height: 1.5;
p {
+ font-size: 18px;
color: #888;
}
@@ -36,10 +37,14 @@
}
}
- .login-box {
- background: #fafafa;
- border-radius: 10px;
- box-shadow: 0 0 2px #ccc;
+ p {
+ font-size: 13px;
+ }
+
+ .login-box, .omniauth-container {
+ box-shadow: 0 0 0 1px $border-color;
+ border-bottom-right-radius: 2px;
+ border-bottom-left-radius: 2px;
padding: 15px;
.login-heading h3 {
@@ -58,42 +63,127 @@
a.forgot {
float: right;
- padding-top: 6px
+ padding-top: 6px;
}
.nav .active a {
background: transparent;
}
- }
- .form-control {
- font-size: 14px;
- padding: 10px 8px;
- width: 100%;
- height: auto;
-
- &.top {
- border-radius: 5px 5px 0 0;
- margin-bottom: 0;
+ // Styles the glowing border of focused input for username async validation
+ .login-body {
+ font-size: 13px;
+
+
+ input + p {
+ margin-top: 5px;
+ }
+
+ .gl-field-success-outline {
+ border: 1px solid $green-normal;
+
+ &:focus {
+ 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;
+ border: 0 none;
+ }
+ }
+
+ .gl-field-error-outline {
+ border: 1px solid $red-normal;
+
+ &: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;
+ }
+ }
+
+ .username .validation-success,
+ .gl-field-success-message {
+ color: $green-normal;
+ }
+
+ .username .validation-error,
+ .gl-field-error-message {
+ color: $red-normal;
+ }
+
+ .gl-field-hint {
+ color: $gl-text-color;
+ }
+
}
+ }
- &.bottom {
- border-radius: 0 0 5px 5px;
- border-top: 0;
- margin-bottom: 20px;
+ .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;
- &.middle {
- border-top: 0;
- margin-bottom: 0;
- border-radius: 0;
+ &: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 {
background-color: #fff;
}
}
+ label {
+ font-weight: normal;
+ }
+
+ .submit-container {
+ margin-top: 16px;
+ }
+
+ input[type="submit"] {
+ @extend .btn-block;
+ margin-bottom: 0;
+ }
+
.devise-errors {
h2 {
margin-top: 0;
@@ -101,14 +191,6 @@
color: #a00;
}
}
-
- .remember-me {
- margin-top: -10px;
-
- label {
- font-weight: normal;
- }
- }
}
@media (max-width: $screen-xs-max) {
@@ -127,3 +209,35 @@
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
+ }
+}
diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss
new file mode 100644
index 00000000000..756efa9c7fa
--- /dev/null
+++ b/app/assets/stylesheets/pages/members.scss
@@ -0,0 +1,98 @@
+.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;
+}
diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss
index 5ec660799e3..49013d7cac9 100644
--- a/app/assets/stylesheets/pages/merge_conflicts.scss
+++ b/app/assets/stylesheets/pages/merge_conflicts.scss
@@ -131,6 +131,7 @@ $colors: (
}
}
}
+
&.head {
background-color: map-get($colors, #{$color}_header_head_neutral);
border-color: map-get($colors, #{$color}_header_head_neutral);
@@ -174,6 +175,7 @@ $colors: (
background-color: map-get($colors, #{$color}_line_not_chosen);
}
}
+
&.head {
background-color: map-get($colors, #{$color}_line_head_neutral);
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 6a0fae8a3f9..afc4e517fde 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -10,6 +10,7 @@
form {
margin-bottom: 0;
+
.clearfix {
margin-bottom: 0;
}
@@ -46,6 +47,7 @@
&.right {
float: right;
+
a {
color: $gl-gray;
}
@@ -192,6 +194,7 @@
padding-top: 2px;
padding-bottom: 2px;
list-style: none;
+
&:hover {
background: none;
}
@@ -215,6 +218,7 @@
padding-top: 20px;
padding-bottom: 10px;
}
+
svg {
width: 230px;
}
@@ -280,12 +284,6 @@
line-height: 31px;
}
-.builds {
- .table-holder {
- overflow-x: auto;
- }
-}
-
.panel-new-merge-request {
.panel-heading {
padding: 5px 10px;
@@ -373,7 +371,7 @@
}
.table-holder {
- .builds {
+ .ci-table {
th {
background-color: $white-light;
@@ -437,3 +435,12 @@
margin-bottom: 20px;
}
}
+
+.merge-request-tabs {
+ background-color: #fff;
+
+ &.affix {
+ top: 100px;
+ z-index: 9;
+ }
+}
diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss
index 8c2ba3ed58c..dd6d1783667 100644
--- a/app/assets/stylesheets/pages/milestone.scss
+++ b/app/assets/stylesheets/pages/milestone.scss
@@ -59,6 +59,7 @@
color: $gl-placeholder-color;
margin-right: 5px;
}
+
.avatar {
float: none;
}
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index bd875b9823f..17f28959414 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -11,6 +11,7 @@
filter: alpha(opacity=100);
}
}
+
.diff-file,
.discussion {
.new-note {
@@ -194,6 +195,7 @@
min-height: 140px;
max-height: 500px;
}
+
.note-form-actions {
background: transparent;
}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index d399f84a2ff..fffcdc812a7 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -147,9 +147,18 @@ ul.notes {
// Diff code in discussion view
.discussion-body .diff-file {
+ .file-title {
+ cursor: default;
+
+ &:hover {
+ background-color: $gray-light;
+ }
+ }
+
.diff-header > span {
margin-right: 10px;
}
+
.line_content {
white-space: pre-wrap;
}
@@ -345,6 +354,7 @@ ul.notes {
width: 32px;
// "hide" it by default
display: none;
+
&:hover {
background: $gl-info;
color: #fff;
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 7843355f0ab..7b71876b822 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -20,7 +20,7 @@
margin: 4px;
}
- .table.builds {
+ .table.ci-table {
min-width: 1200px;
.branch-commit {
@@ -44,13 +44,20 @@
overflow: auto;
}
-.table.builds {
+.table.ci-table {
min-width: 900px;
&.pipeline {
min-width: 650px;
}
+ &.builds-page {
+
+ tr {
+ height: 71px;
+ }
+ }
+
tr {
th {
padding: 16px 8px;
@@ -176,7 +183,7 @@
&::after {
content: '';
width: 8px;
- position: absolute;;
+ position: absolute;
right: -7px;
bottom: 8px;
border-bottom: 2px solid $border-color;
@@ -353,6 +360,7 @@
&:hover {
background-color: $gray-lighter;
+
.dropdown-menu-toggle {
background-color: transparent;
}
@@ -536,6 +544,7 @@
height: 29px;
top: -9px;
}
+
.curve {
display: block;
}
@@ -621,19 +630,31 @@
}
}
-.pipelines.tab-pane {
+.tab-pane {
- .content-list.pipelines {
- overflow: auto;
- }
+ &.pipelines {
- .stage {
- max-width: 100px;
- width: 100px;
+ .content-list.pipelines {
+ overflow: auto;
+ }
+
+ .stage {
+ max-width: 100px;
+ width: 100px;
+ }
+
+ .pipeline-actions {
+ min-width: initial;
+ }
}
- .pipeline-actions {
- min-width: initial;
+ &.builds {
+
+ .ci-table {
+ tr {
+ height: 71px;
+ }
+ }
}
}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index c7eac5cf4b9..ed80d2beec2 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -243,6 +243,7 @@
.btn {
-webkit-flex-grow: 1;
flex-grow: 1;
+
&:first-child {
margin-left: 0;
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 530fb0c0d05..d30f02340b9 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -17,34 +17,43 @@
&.features .control-label {
font-weight: normal;
}
+
.form-group {
margin-bottom: 5px;
}
+
&> .form-group {
padding-left: 0;
}
}
+
.help-block {
margin-bottom: 10px;
}
+
.project-path {
padding-right: 0;
+
.form-control {
border-radius: $border-radius-base;
}
}
+
.input-group > div {
&:last-child {
padding-right: 0;
}
}
+
@media (max-width: $screen-xs-max) {
.input-group > div {
margin-bottom: 14px;
+
&:last-child {
margin-bottom: 0;
}
}
+
fieldset > .form-group:first-child {
padding-right: 0;
}
@@ -56,6 +65,7 @@
border-radius: 3px;
border: 1px solid #e5e5e5;
}
+
&+ .select2 a {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
@@ -201,6 +211,7 @@
pointer-events: none;
}
}
+
.count {
@include btn-gray;
display: inline-block;
@@ -361,10 +372,12 @@ a.deploy-project-label {
margin: $gl-padding;
text-align: center;
width: 169px;
+
&:hover, &.forked {
background-color: $row-hover;
border-color: $row-hover-border;
}
+
.no-avatar {
width: 100px;
height: 100px;
@@ -372,17 +385,20 @@ a.deploy-project-label {
border: 1px solid $gray-dark;
margin: 0 auto;
border-radius: 50%;
+
i {
font-size: 100px;
color: $gray-dark;
}
}
+
a {
display: block;
width: 100%;
height: 100%;
padding-top: $gl-padding;
color: $gl-gray;
+
.caption {
min-height: 30px;
padding: $gl-padding 0;
@@ -644,6 +660,7 @@ pre.light-well {
.clone-options {
display: table-cell;
+
a.btn {
width: 100%;
}
@@ -832,6 +849,7 @@ pre.light-well {
.form-control {
min-width: 100px;
}
+
.select2-choice {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss
index eec22c5dc96..7b3878c91df 100644
--- a/app/assets/stylesheets/pages/runners.scss
+++ b/app/assets/stylesheets/pages/runners.scss
@@ -6,6 +6,7 @@
&.runner-state-shared {
background: #32b186;
}
+
&.runner-state-specific {
background: #3498db;
}
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index c05f3d5ff32..f1d53c7b8bc 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -65,6 +65,7 @@
.ci-status-icon-success {
color: $gl-success;
}
+
.ci-status-icon-failed {
color: $gl-danger;
}
@@ -77,6 +78,7 @@
.ci-status-icon-running {
color: $blue-normal;
}
+
.ci-status-icon-canceled,
.ci-status-icon-disabled,
.ci-status-icon-not-found,
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 41ad10f07bd..99c0f6362d0 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -5,6 +5,7 @@
.file-finder {
width: 50%;
+
.file-finder-input {
width: 95%;
display: inline-block;
diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss
index c9846103762..3fa7fa3d7e3 100644
--- a/app/assets/stylesheets/pages/xterm.scss
+++ b/app/assets/stylesheets/pages/xterm.scss
@@ -23,15 +23,19 @@
.term-bold {
font-weight: bold;
}
+
.term-italic {
font-style: italic;
}
+
.term-conceal {
visibility: hidden;
}
+
.term-underline {
text-decoration: underline;
}
+
.term-cross {
text-decoration: line-through;
}
@@ -39,48 +43,63 @@
.term-fg-black {
color: $black;
}
+
.term-fg-red {
color: $red;
}
+
.term-fg-green {
color: $green;
}
+
.term-fg-yellow {
color: $yellow;
}
+
.term-fg-blue {
color: $blue;
}
+
.term-fg-magenta {
color: $magenta;
}
+
.term-fg-cyan {
color: $cyan;
}
+
.term-fg-white {
color: $white;
}
+
.term-fg-l-black {
color: $l-black;
}
+
.term-fg-l-red {
color: $l-red;
}
+
.term-fg-l-green {
color: $l-green;
}
+
.term-fg-l-yellow {
color: $l-yellow;
}
+
.term-fg-l-blue {
color: $l-blue;
}
+
.term-fg-l-magenta {
color: $l-magenta;
}
+
.term-fg-l-cyan {
color: $l-cyan;
}
+
.term-fg-l-white {
color: $l-white;
}
@@ -88,818 +107,1087 @@
.term-bg-black {
background-color: $black;
}
+
.term-bg-red {
background-color: $red;
}
+
.term-bg-green {
background-color: $green;
}
+
.term-bg-yellow {
background-color: $yellow;
}
+
.term-bg-blue {
background-color: $blue;
}
+
.term-bg-magenta {
background-color: $magenta;
}
+
.term-bg-cyan {
background-color: $cyan;
}
+
.term-bg-white {
background-color: $white;
}
+
.term-bg-l-black {
background-color: $l-black;
}
+
.term-bg-l-red {
background-color: $l-red;
}
+
.term-bg-l-green {
background-color: $l-green;
}
+
.term-bg-l-yellow {
background-color: $l-yellow;
}
+
.term-bg-l-blue {
background-color: $l-blue;
}
+
.term-bg-l-magenta {
background-color: $l-magenta;
}
+
.term-bg-l-cyan {
background-color: $l-cyan;
}
+
.term-bg-l-white {
background-color: $l-white;
}
-
.xterm-fg-0 {
color: #000;
}
+
.xterm-fg-1 {
color: #800000;
}
+
.xterm-fg-2 {
color: #008000;
}
+
.xterm-fg-3 {
color: #808000;
}
+
.xterm-fg-4 {
color: #000080;
}
+
.xterm-fg-5 {
color: #800080;
}
+
.xterm-fg-6 {
color: #008080;
}
+
.xterm-fg-7 {
color: #c0c0c0;
}
+
.xterm-fg-8 {
color: #808080;
}
+
.xterm-fg-9 {
color: #f00;
}
+
.xterm-fg-10 {
color: #0f0;
}
+
.xterm-fg-11 {
color: #ff0;
}
+
.xterm-fg-12 {
color: #00f;
}
+
.xterm-fg-13 {
color: #f0f;
}
+
.xterm-fg-14 {
color: #0ff;
}
+
.xterm-fg-15 {
color: #fff;
}
+
.xterm-fg-16 {
color: #000;
}
+
.xterm-fg-17 {
color: #00005f;
}
+
.xterm-fg-18 {
color: #000087;
}
+
.xterm-fg-19 {
color: #0000af;
}
+
.xterm-fg-20 {
color: #0000d7;
}
+
.xterm-fg-21 {
color: #00f;
}
+
.xterm-fg-22 {
color: #005f00;
}
+
.xterm-fg-23 {
color: #005f5f;
}
+
.xterm-fg-24 {
color: #005f87;
}
+
.xterm-fg-25 {
color: #005faf;
}
+
.xterm-fg-26 {
color: #005fd7;
}
+
.xterm-fg-27 {
color: #005fff;
}
+
.xterm-fg-28 {
color: #008700;
}
+
.xterm-fg-29 {
color: #00875f;
}
+
.xterm-fg-30 {
color: #008787;
}
+
.xterm-fg-31 {
color: #0087af;
}
+
.xterm-fg-32 {
color: #0087d7;
}
+
.xterm-fg-33 {
color: #0087ff;
}
+
.xterm-fg-34 {
color: #00af00;
}
+
.xterm-fg-35 {
color: #00af5f;
}
+
.xterm-fg-36 {
color: #00af87;
}
+
.xterm-fg-37 {
color: #00afaf;
}
+
.xterm-fg-38 {
color: #00afd7;
}
+
.xterm-fg-39 {
color: #00afff;
}
+
.xterm-fg-40 {
color: #00d700;
}
+
.xterm-fg-41 {
color: #00d75f;
}
+
.xterm-fg-42 {
color: #00d787;
}
+
.xterm-fg-43 {
color: #00d7af;
}
+
.xterm-fg-44 {
color: #00d7d7;
}
+
.xterm-fg-45 {
color: #00d7ff;
}
+
.xterm-fg-46 {
color: #0f0;
}
+
.xterm-fg-47 {
color: #00ff5f;
}
+
.xterm-fg-48 {
color: #00ff87;
}
+
.xterm-fg-49 {
color: #00ffaf;
}
+
.xterm-fg-50 {
color: #00ffd7;
}
+
.xterm-fg-51 {
color: #0ff;
}
+
.xterm-fg-52 {
color: #5f0000;
}
+
.xterm-fg-53 {
color: #5f005f;
}
+
.xterm-fg-54 {
color: #5f0087;
}
+
.xterm-fg-55 {
color: #5f00af;
}
+
.xterm-fg-56 {
color: #5f00d7;
}
+
.xterm-fg-57 {
color: #5f00ff;
}
+
.xterm-fg-58 {
color: #5f5f00;
}
+
.xterm-fg-59 {
color: #5f5f5f;
}
+
.xterm-fg-60 {
color: #5f5f87;
}
+
.xterm-fg-61 {
color: #5f5faf;
}
+
.xterm-fg-62 {
color: #5f5fd7;
}
+
.xterm-fg-63 {
color: #5f5fff;
}
+
.xterm-fg-64 {
color: #5f8700;
}
+
.xterm-fg-65 {
color: #5f875f;
}
+
.xterm-fg-66 {
color: #5f8787;
}
+
.xterm-fg-67 {
color: #5f87af;
}
+
.xterm-fg-68 {
color: #5f87d7;
}
+
.xterm-fg-69 {
color: #5f87ff;
}
+
.xterm-fg-70 {
color: #5faf00;
}
+
.xterm-fg-71 {
color: #5faf5f;
}
+
.xterm-fg-72 {
color: #5faf87;
}
+
.xterm-fg-73 {
color: #5fafaf;
}
+
.xterm-fg-74 {
color: #5fafd7;
}
+
.xterm-fg-75 {
color: #5fafff;
}
+
.xterm-fg-76 {
color: #5fd700;
}
+
.xterm-fg-77 {
color: #5fd75f;
}
+
.xterm-fg-78 {
color: #5fd787;
}
+
.xterm-fg-79 {
color: #5fd7af;
}
+
.xterm-fg-80 {
color: #5fd7d7;
}
+
.xterm-fg-81 {
color: #5fd7ff;
}
+
.xterm-fg-82 {
color: #5fff00;
}
+
.xterm-fg-83 {
color: #5fff5f;
}
+
.xterm-fg-84 {
color: #5fff87;
}
+
.xterm-fg-85 {
color: #5fffaf;
}
+
.xterm-fg-86 {
color: #5fffd7;
}
+
.xterm-fg-87 {
color: #5fffff;
}
+
.xterm-fg-88 {
color: #870000;
}
+
.xterm-fg-89 {
color: #87005f;
}
+
.xterm-fg-90 {
color: #870087;
}
+
.xterm-fg-91 {
color: #8700af;
}
+
.xterm-fg-92 {
color: #8700d7;
}
+
.xterm-fg-93 {
color: #8700ff;
}
+
.xterm-fg-94 {
color: #875f00;
}
+
.xterm-fg-95 {
color: #875f5f;
}
+
.xterm-fg-96 {
color: #875f87;
}
+
.xterm-fg-97 {
color: #875faf;
}
+
.xterm-fg-98 {
color: #875fd7;
}
+
.xterm-fg-99 {
color: #875fff;
}
+
.xterm-fg-100 {
color: #878700;
}
+
.xterm-fg-101 {
color: #87875f;
}
+
.xterm-fg-102 {
color: #878787;
}
+
.xterm-fg-103 {
color: #8787af;
}
+
.xterm-fg-104 {
color: #8787d7;
}
+
.xterm-fg-105 {
color: #8787ff;
}
+
.xterm-fg-106 {
color: #87af00;
}
+
.xterm-fg-107 {
color: #87af5f;
}
+
.xterm-fg-108 {
color: #87af87;
}
+
.xterm-fg-109 {
color: #87afaf;
}
+
.xterm-fg-110 {
color: #87afd7;
}
+
.xterm-fg-111 {
color: #87afff;
}
+
.xterm-fg-112 {
color: #87d700;
}
+
.xterm-fg-113 {
color: #87d75f;
}
+
.xterm-fg-114 {
color: #87d787;
}
+
.xterm-fg-115 {
color: #87d7af;
}
+
.xterm-fg-116 {
color: #87d7d7;
}
+
.xterm-fg-117 {
color: #87d7ff;
}
+
.xterm-fg-118 {
color: #87ff00;
}
+
.xterm-fg-119 {
color: #87ff5f;
}
+
.xterm-fg-120 {
color: #87ff87;
}
+
.xterm-fg-121 {
color: #87ffaf;
}
+
.xterm-fg-122 {
color: #87ffd7;
}
+
.xterm-fg-123 {
color: #87ffff;
}
+
.xterm-fg-124 {
color: #af0000;
}
+
.xterm-fg-125 {
color: #af005f;
}
+
.xterm-fg-126 {
color: #af0087;
}
+
.xterm-fg-127 {
color: #af00af;
}
+
.xterm-fg-128 {
color: #af00d7;
}
+
.xterm-fg-129 {
color: #af00ff;
}
+
.xterm-fg-130 {
color: #af5f00;
}
+
.xterm-fg-131 {
color: #af5f5f;
}
+
.xterm-fg-132 {
color: #af5f87;
}
+
.xterm-fg-133 {
color: #af5faf;
}
+
.xterm-fg-134 {
color: #af5fd7;
}
+
.xterm-fg-135 {
color: #af5fff;
}
+
.xterm-fg-136 {
color: #af8700;
}
+
.xterm-fg-137 {
color: #af875f;
}
+
.xterm-fg-138 {
color: #af8787;
}
+
.xterm-fg-139 {
color: #af87af;
}
+
.xterm-fg-140 {
color: #af87d7;
}
+
.xterm-fg-141 {
color: #af87ff;
}
+
.xterm-fg-142 {
color: #afaf00;
}
+
.xterm-fg-143 {
color: #afaf5f;
}
+
.xterm-fg-144 {
color: #afaf87;
}
+
.xterm-fg-145 {
color: #afafaf;
}
+
.xterm-fg-146 {
color: #afafd7;
}
+
.xterm-fg-147 {
color: #afafff;
}
+
.xterm-fg-148 {
color: #afd700;
}
+
.xterm-fg-149 {
color: #afd75f;
}
+
.xterm-fg-150 {
color: #afd787;
}
+
.xterm-fg-151 {
color: #afd7af;
}
+
.xterm-fg-152 {
color: #afd7d7;
}
+
.xterm-fg-153 {
color: #afd7ff;
}
+
.xterm-fg-154 {
color: #afff00;
}
+
.xterm-fg-155 {
color: #afff5f;
}
+
.xterm-fg-156 {
color: #afff87;
}
+
.xterm-fg-157 {
color: #afffaf;
}
+
.xterm-fg-158 {
color: #afffd7;
}
+
.xterm-fg-159 {
color: #afffff;
}
+
.xterm-fg-160 {
color: #d70000;
}
+
.xterm-fg-161 {
color: #d7005f;
}
+
.xterm-fg-162 {
color: #d70087;
}
+
.xterm-fg-163 {
color: #d700af;
}
+
.xterm-fg-164 {
color: #d700d7;
}
+
.xterm-fg-165 {
color: #d700ff;
}
+
.xterm-fg-166 {
color: #d75f00;
}
+
.xterm-fg-167 {
color: #d75f5f;
}
+
.xterm-fg-168 {
color: #d75f87;
}
+
.xterm-fg-169 {
color: #d75faf;
}
+
.xterm-fg-170 {
color: #d75fd7;
}
+
.xterm-fg-171 {
color: #d75fff;
}
+
.xterm-fg-172 {
color: #d78700;
}
+
.xterm-fg-173 {
color: #d7875f;
}
+
.xterm-fg-174 {
color: #d78787;
}
+
.xterm-fg-175 {
color: #d787af;
}
+
.xterm-fg-176 {
color: #d787d7;
}
+
.xterm-fg-177 {
color: #d787ff;
}
+
.xterm-fg-178 {
color: #d7af00;
}
+
.xterm-fg-179 {
color: #d7af5f;
}
+
.xterm-fg-180 {
color: #d7af87;
}
+
.xterm-fg-181 {
color: #d7afaf;
}
+
.xterm-fg-182 {
color: #d7afd7;
}
+
.xterm-fg-183 {
color: #d7afff;
}
+
.xterm-fg-184 {
color: #d7d700;
}
+
.xterm-fg-185 {
color: #d7d75f;
}
+
.xterm-fg-186 {
color: #d7d787;
}
+
.xterm-fg-187 {
color: #d7d7af;
}
+
.xterm-fg-188 {
color: #d7d7d7;
}
+
.xterm-fg-189 {
color: #d7d7ff;
}
+
.xterm-fg-190 {
color: #d7ff00;
}
+
.xterm-fg-191 {
color: #d7ff5f;
}
+
.xterm-fg-192 {
color: #d7ff87;
}
+
.xterm-fg-193 {
color: #d7ffaf;
}
+
.xterm-fg-194 {
color: #d7ffd7;
}
+
.xterm-fg-195 {
color: #d7ffff;
}
+
.xterm-fg-196 {
color: #f00;
}
+
.xterm-fg-197 {
color: #ff005f;
}
+
.xterm-fg-198 {
color: #ff0087;
}
+
.xterm-fg-199 {
color: #ff00af;
}
+
.xterm-fg-200 {
color: #ff00d7;
}
+
.xterm-fg-201 {
color: #f0f;
}
+
.xterm-fg-202 {
color: #ff5f00;
}
+
.xterm-fg-203 {
color: #ff5f5f;
}
+
.xterm-fg-204 {
color: #ff5f87;
}
+
.xterm-fg-205 {
color: #ff5faf;
}
+
.xterm-fg-206 {
color: #ff5fd7;
}
+
.xterm-fg-207 {
color: #ff5fff;
}
+
.xterm-fg-208 {
color: #ff8700;
}
+
.xterm-fg-209 {
color: #ff875f;
}
+
.xterm-fg-210 {
color: #ff8787;
}
+
.xterm-fg-211 {
color: #ff87af;
}
+
.xterm-fg-212 {
color: #ff87d7;
}
+
.xterm-fg-213 {
color: #ff87ff;
}
+
.xterm-fg-214 {
color: #ffaf00;
}
+
.xterm-fg-215 {
color: #ffaf5f;
}
+
.xterm-fg-216 {
color: #ffaf87;
}
+
.xterm-fg-217 {
color: #ffafaf;
}
+
.xterm-fg-218 {
color: #ffafd7;
}
+
.xterm-fg-219 {
color: #ffafff;
}
+
.xterm-fg-220 {
color: #ffd700;
}
+
.xterm-fg-221 {
color: #ffd75f;
}
+
.xterm-fg-222 {
color: #ffd787;
}
+
.xterm-fg-223 {
color: #ffd7af;
}
+
.xterm-fg-224 {
color: #ffd7d7;
}
+
.xterm-fg-225 {
color: #ffd7ff;
}
+
.xterm-fg-226 {
color: #ff0;
}
+
.xterm-fg-227 {
color: #ffff5f;
}
+
.xterm-fg-228 {
color: #ffff87;
}
+
.xterm-fg-229 {
color: #ffffaf;
}
+
.xterm-fg-230 {
color: #ffffd7;
}
+
.xterm-fg-231 {
color: #fff;
}
+
.xterm-fg-232 {
color: #080808;
}
+
.xterm-fg-233 {
color: #121212;
}
+
.xterm-fg-234 {
color: #1c1c1c;
}
+
.xterm-fg-235 {
color: #262626;
}
+
.xterm-fg-236 {
color: #303030;
}
+
.xterm-fg-237 {
color: #3a3a3a;
}
+
.xterm-fg-238 {
color: #444;
}
+
.xterm-fg-239 {
color: #4e4e4e;
}
+
.xterm-fg-240 {
color: #585858;
}
+
.xterm-fg-241 {
color: #626262;
}
+
.xterm-fg-242 {
color: #6c6c6c;
}
+
.xterm-fg-243 {
color: #767676;
}
+
.xterm-fg-244 {
color: #808080;
}
+
.xterm-fg-245 {
color: #8a8a8a;
}
+
.xterm-fg-246 {
color: #949494;
}
+
.xterm-fg-247 {
color: #9e9e9e;
}
+
.xterm-fg-248 {
color: #a8a8a8;
}
+
.xterm-fg-249 {
color: #b2b2b2;
}
+
.xterm-fg-250 {
color: #bcbcbc;
}
+
.xterm-fg-251 {
color: #c6c6c6;
}
+
.xterm-fg-252 {
color: #d0d0d0;
}
+
.xterm-fg-253 {
color: #dadada;
}
+
.xterm-fg-254 {
color: #e4e4e4;
}
+
.xterm-fg-255 {
color: #eee;
}
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index b3455e04c29..705824502eb 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -45,6 +45,10 @@ class ApplicationController < ActionController::Base
redirect_to request.referer.present? ? :back : default, options
end
+ def not_found
+ render_404
+ end
+
protected
# This filter handles both private tokens and personal access tokens
diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb
index 7a7475a7345..ae060abee5c 100644
--- a/app/controllers/projects/group_links_controller.rb
+++ b/app/controllers/projects/group_links_controller.rb
@@ -1,6 +1,7 @@
class Projects::GroupLinksController < Projects::ApplicationController
layout 'project_settings'
before_action :authorize_admin_project!
+ before_action :authorize_admin_project_member!, only: [:update]
def index
@group_links = project.project_group_links.all
@@ -27,9 +28,26 @@ class Projects::GroupLinksController < Projects::ApplicationController
redirect_to namespace_project_group_links_path(project.namespace, project)
end
+ def update
+ @group_link = @project.project_group_links.find(params[:id])
+
+ @group_link.update_attributes(group_link_params)
+ end
+
def destroy
project.project_group_links.find(params[:id]).destroy
- redirect_to namespace_project_group_links_path(project.namespace, project)
+ respond_to do |format|
+ format.html do
+ redirect_to namespace_project_group_links_path(project.namespace, project)
+ end
+ format.js { head :ok }
+ end
+ end
+
+ protected
+
+ def group_link_params
+ params.require(:group_link).permit(:group_access, :expires_at)
end
end
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index f56b256984b..37a86ed0523 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -5,34 +5,23 @@ class Projects::ProjectMembersController < Projects::ApplicationController
before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
def index
+ @group_links = @project.project_group_links
+
@project_members = @project.project_members
@project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
if params[:search].present?
users = @project.users.search(params[:search]).to_a
@project_members = @project_members.where(user_id: users)
- end
-
- @project_members = @project_members.order('access_level DESC')
-
- @group = @project.group
-
- if @group
- @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
- @group_members = @group_members.order('access_level DESC')
+ @group_links = @project.project_group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id))
end
+ @project_members = @project_members.order(access_level: :desc).page(params[:page])
+
@requesters = AccessRequestsFinder.new(@project).execute(current_user)
@project_member = @project.project_members.new
- @project_group_links = @project.project_group_links
end
def create
@@ -43,6 +32,21 @@ class Projects::ProjectMembersController < Projects::ApplicationController
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)
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 838ecc837e4..6a881b271d7 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,6 +1,6 @@
class UsersController < ApplicationController
skip_before_action :authenticate_user!
- before_action :user
+ before_action :user, except: [:exists]
before_action :authorize_read_user!, only: [:show]
def show
@@ -85,6 +85,10 @@ class UsersController < ApplicationController
render 'calendar_activities', layout: false
end
+ def exists
+ render json: { exists: Namespace.where(path: params[:username].downcase).any? }
+ end
+
private
def authorize_read_user!
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 2911dcaa6a2..a6b606d13de 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -1,6 +1,7 @@
module Ci
class Build < CommitStatus
include TokenAuthenticatable
+ include AfterCommitQueue
belongs_to :runner, class_name: 'Ci::Runner'
belongs_to :trigger_request, class_name: 'Ci::TriggerRequest'
@@ -75,25 +76,20 @@ module Ci
state_machine :status do
after_transition pending: :running do |build|
- build.execute_hooks
+ build.run_after_commit do
+ BuildHooksWorker.perform_async(id)
+ end
end
after_transition any => [:success, :failed, :canceled] do |build|
- build.update_coverage
- build.execute_hooks
+ build.run_after_commit do
+ BuildFinishedWorker.perform_async(id)
+ end
end
after_transition any => [:success] do |build|
- if build.environment.present?
- service = CreateDeploymentService.new(
- 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)
+ build.run_after_commit do
+ BuildSuccessWorker.perform_async(id)
end
end
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 957f6755b2e..4fdb5fef4fb 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -76,7 +76,11 @@ module Ci
end
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
diff --git a/app/models/project.rb b/app/models/project.rb
index 9e68b0016e0..aee74c3dba1 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -491,7 +491,7 @@ class Project < ActiveRecord::Base
end
def import_url
- if import_data && super
+ if import_data && super.present?
import_url = Gitlab::UrlSanitizer.new(super, credentials: import_data.credentials)
import_url.full_url
else
diff --git a/app/services/create_deployment_service.rb b/app/services/create_deployment_service.rb
index 799ad3e1bd0..ff9a8310a8c 100644
--- a/app/services/create_deployment_service.rb
+++ b/app/services/create_deployment_service.rb
@@ -2,25 +2,35 @@ require_relative 'base_service'
class CreateDeploymentService < BaseService
def execute(deployable = nil)
- environment = find_or_create_environment
+ return unless executable?
- deployment = project.deployments.create(
- environment: environment,
+ ActiveRecord::Base.transaction do
+ @deployable = deployable
+ @environment = prepare_environment
+
+ deploy.tap do |deployment|
+ deployment.update_merge_request_metrics!
+ end
+ end
+ end
+
+ private
+
+ 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
- )
-
- deployment.update_merge_request_metrics!
-
- deployment
+ deployable: @deployable)
end
- private
-
- def find_or_create_environment
+ def prepare_environment
project.environments.find_or_create_by(name: expanded_name) do |environment|
environment.external_url = expanded_url
end
diff --git a/app/views/admin/appearances/preview.html.haml b/app/views/admin/appearances/preview.html.haml
index 6c51639b840..acbe17036f7 100644
--- a/app/views/admin/appearances/preview.html.haml
+++ b/app/views/admin/appearances/preview.html.haml
@@ -1,9 +1,12 @@
-- page_title "Preview | Appearance"
+= render 'devise/shared/tab_single', tab_title: 'Sign in preview'
.login-box
- .login-heading
- %h3 Existing user? Sign in
- %form
- = text_field_tag :login, nil, class: "form-control top", placeholder: "Username or Email"
- = password_field_tag :password, nil, class: "form-control bottom", placeholder: "Password"
- = button_tag "Sign in", class: "btn-create btn"
+ %form.show-gl-field-errors
+ .form-group
+ = label_tag :login
+ = text_field_tag :login, nil, class: "form-control top", title: 'Please provide your username or email address.'
+ .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"
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index a5e82e55cc1..10fea1996aa 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -71,7 +71,7 @@
.col-md-6
%h4 Recent builds served by this Runner
- %table.table.builds.runner-builds
+ %table.table.ci-table.runner-builds
%thead
%tr
%th Build
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
index 970ba147111..5d25dd398d6 100644
--- a/app/views/devise/confirmations/new.html.haml
+++ b/app/views/devise/confirmations/new.html.haml
@@ -1,14 +1,14 @@
+= render 'devise/shared/tab_single', tab_title: 'Resend confirmation instructions'
.login-box
- .login-heading
- %h3 Resend confirmation instructions
.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_error_messages!
- .clearfix.append-bottom-20
- = f.email_field :email, placeholder: 'Email', class: "form-control", required: true
+ .form-group
+ = f.label :email
+ = f.email_field :email, class: "form-control", required: true, title: 'Please provide a valid email address.'
.clearfix
- = f.submit "Resend confirmation instructions", class: 'btn btn-success'
+ = f.submit "Resend", class: 'btn btn-success'
.clearfix.prepend-top-20
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index 56048e99c17..b518fae7c95 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -1,19 +1,21 @@
+= render 'devise/shared/tab_single', tab_title:'Change your password'
.login-box
- .login-heading
- %h3 Change your password
.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_error_messages!
= f.hidden_field :reset_password_token
- %div
- = f.password_field :password, class: "form-control top", placeholder: "New password", required: true
- %div
- = f.password_field :password_confirmation, class: "form-control bottom", placeholder: "Confirm new password", required: true
+ .form-group
+ = f.label 'New password', for: :password
+ = f.password_field :password, class: "form-control top", required: true, title: 'This field is required'
+ .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
= f.submit "Change your password", class: "btn btn-primary"
.clearfix.prepend-top-20
%p
- = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name)
- = render 'devise/shared/sign_in_link'
+ %span.light Didn't receive a confirmation email?
+ = link_to "Request a new one", new_confirmation_path(resource_name)
+= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml
index 535e85869e5..1fcfd06419a 100644
--- a/app/views/devise/passwords/new.html.haml
+++ b/app/views/devise/passwords/new.html.haml
@@ -1,12 +1,12 @@
+= render 'devise/shared/tab_single', tab_title: 'Reset Password'
.login-box
- .login-heading
- %h3 Reset password
.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_error_messages!
- .clearfix.append-bottom-20
- = f.email_field :email, placeholder: "Email", class: "form-control", required: true, value: params[:user_email], autofocus: true
+ .form-group
+ = 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
= f.submit "Reset password", class: "btn-primary btn"
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index 9f5520603cd..a96b579c593 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -1,6 +1,10 @@
-= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
- = f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off"
- = f.password_field :password, class: "form-control bottom", placeholder: "Password"
+= form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: 'new_user show-gl-field-errors', 'aria-live' => 'assertive'}) do |f|
+ %div.form-group
+ = 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?
.remember-me.checkbox
%label{for: "user_remember_me"}
@@ -8,5 +12,5 @@
%span Remember me
.pull-right
= link_to "Forgot your password?", new_password_path(resource_name)
- %div
+ %div.submit-container
= f.submit "Sign in", class: "btn btn-save"
diff --git a/app/views/devise/sessions/_new_crowd.html.haml b/app/views/devise/sessions/_new_crowd.html.haml
index b7d3acac2b1..e82a08cdb0c 100644
--- a/app/views/devise/sessions/_new_crowd.html.haml
+++ b/app/views/devise/sessions/_new_crowd.html.haml
@@ -1,6 +1,10 @@
-= form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user' ) do
- = text_field_tag :username, nil, {class: "form-control top", placeholder: "Username", autofocus: "autofocus"}
- = password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"}
+= form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user', class: 'show-gl-field-errors') do
+ .form-group
+ = 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?
.remember-me.checkbox
%label{for: "remember_me"}
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 2ef383960f4..b26efbb4535 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -1,6 +1,10 @@
-= form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user') do
- = text_field_tag :username, nil, {class: "form-control top", placeholder: "#{server['label']} Login", autofocus: "autofocus"}
- = password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"}
+= form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user', class: "show-gl-field-errors") do
+ .form-group
+ = 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?
.remember-me.checkbox
%label{for: "remember_me"}
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 28194506acc..fa8e7979461 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,19 +1,22 @@
- page_title "Sign in"
%div
- - if signin_enabled? || ldap_enabled? || crowd_enabled?
- = render 'devise/shared/signin_box'
+ - 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?
+ = 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
- - if signin_enabled? && signup_enabled?
- .prepend-top-20
+ -# Signup only makes sense if you can also sign-in
+ - if signin_enabled? && signup_enabled?
= render 'devise/shared/signup_box'
-# Show a message if none of the mechanisms above are enabled
- if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
%div
No authentication methods configured.
+
+ - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
+ .clearfix
+ = render 'devise/shared/omniauth_box'
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index e623f7cff88..0e865b807c1 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -3,20 +3,19 @@
= page_specific_javascript_tag('u2f.js')
%div
+ = render 'devise/shared/tab_single', tab_title: 'Two-Factor Authentication'
.login-box
- .login-heading
- %h3 Two-Factor Authentication
.login-body
- if @user.two_factor_otp_enabled?
- %h5 Authenticate via Two-Factor App
- = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f|
+ = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: 'edit_user show-gl-field-errors' }) do |f|
- resource_params = params[resource_name].presence || params
= f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
- = f.text_field :otp_attempt, class: 'form-control', placeholder: 'Two-Factor Authentication code', required: true, autofocus: true, autocomplete: 'off'
- %p.help-block.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.
- .prepend-top-20
- = f.submit "Verify code", class: "btn btn-save"
+ .form-group
+ = f.label 'Two-Factor Authentication code', name: :otp_attempt
+ = f.text_field :otp_attempt, class: 'form-control', required: true, autofocus: true, autocomplete: 'off', title: 'This field is required.'
+ %p.help-block.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.
+ .prepend-top-20
+ = f.submit "Verify code", class: "btn btn-save"
- if @user.two_factor_u2f_enabled?
- %hr
= render "u2f/authenticate", locals: { params: params, resource: resource, resource_name: resource_name }
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 2e7da2747d0..8908b64cdac 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -1,8 +1,9 @@
-%p
- %span.light
- Sign in with &nbsp;
- - providers = enabled_button_based_providers
- - providers.each do |provider|
+%div.omniauth-container
+ %p
%span.light
- - has_icon = provider_has_icon?(provider)
- = link_to provider_image_tag(provider), omniauth_authorize_path(:user, provider), method: :post, class: (has_icon ? 'oauth-image-link' : 'btn'), "data-no-turbolink" => "true"
+ Sign in with &nbsp;
+ - providers = enabled_button_based_providers
+ - providers.each do |provider|
+ %span.light
+ - has_icon = provider_has_icon?(provider)
+ = link_to provider_image_tag(provider), omniauth_authorize_path(:user, provider), method: :post, class: (has_icon ? 'oauth-image-link' : 'btn'), "data-no-turbolink" => "true"
diff --git a/app/views/devise/shared/_sign_in_link.html.haml b/app/views/devise/shared/_sign_in_link.html.haml
index fafc4b82f53..289bf40f3de 100644
--- a/app/views/devise/shared/_sign_in_link.html.haml
+++ b/app/views/devise/shared/_sign_in_link.html.haml
@@ -1,5 +1,4 @@
%p
%span.light
Already have login and password?
- %strong
= link_to "Sign in", new_session_path(resource_name)
diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml
index 2c15e2c4891..810dd5ab687 100644
--- a/app/views/devise/shared/_signin_box.html.haml
+++ b/app/views/devise/shared/_signin_box.html.haml
@@ -1,32 +1,15 @@
-.login-box
- - if signup_enabled?
- .login-heading
- %h3 Existing user? Sign in
- - else
- .login-heading
- %h3 Sign in
+#login-pane.login-box{ role: 'tabpanel', class: 'tab-pane active' }
.login-body
- if form_based_providers.any?
- %ul.nav-links
- - if crowd_enabled?
- %li.active
- = link_to "Crowd", "#tab-crowd", 'data-toggle' => 'tab'
- - @ldap_servers.each_with_index do |server, i|
- %li{class: (:active if i.zero? && !crowd_enabled?)}
- = link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab'
- - if signin_enabled?
- %li
- = link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab'
- .tab-content
- - if crowd_enabled?
- %div.tab-pane.active{id: "tab-crowd"}
- = render 'devise/sessions/new_crowd'
- - @ldap_servers.each_with_index do |server, i|
- %div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero? && !crowd_enabled?)}
- = render 'devise/sessions/new_ldap', server: server
- - if signin_enabled?
- %div#tab-signin.tab-pane
- = render 'devise/sessions/new_base'
+ - if crowd_enabled?
+ %div.tab-pane.active{id: "tab-crowd"}
+ = render 'devise/sessions/new_crowd'
+ - @ldap_servers.each_with_index do |server, i|
+ %div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero? && !crowd_enabled?)}
+ = render 'devise/sessions/new_ldap', server: server
+ - if signin_enabled?
+ %div#tab-signin.tab-pane
+ = render 'devise/sessions/new_base'
- elsif signin_enabled?
= render 'devise/sessions/new_base'
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 905a8dbcd84..d0bbcf3115e 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -1,29 +1,30 @@
-.login-box
- - if signin_enabled?
- .login-heading
- %h3 New user? Create an account
- - else
- .login-heading
- %h3 Create an account
+#register-pane.login-box{ role: 'tabpanel', class: 'tab-pane' }
.login-body
- = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name)) do |f|
+ = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user show-gl-field-errors", "aria-live" => "assertive" }) do |f|
.devise-errors
= devise_error_messages!
- %div
- = f.text_field :name, class: "form-control top", placeholder: "Name", required: true
- %div
- = f.text_field :username, class: "form-control middle", placeholder: "Username", required: true
- %div
- = f.email_field :email, class: "form-control middle", placeholder: "Email", required: true
+ %div.form-group
+ = f.label :name
+ = f.text_field :name, class: "form-control top", required: true, title: "This field is required."
+ %div.username.form-group
+ = f.label :username
+ = f.text_field :username, class: "form-control middle no-gl-field-error", pattern: "[a-zA-Z0-9]+", required: true, title: 'Please create a username with only alphanumeric characters.'
+ %p.validation-error.hide Username is already taken.
+ %p.validation-success.hide Username is available.
+ %p.validation-pending.hide Checking username availability...
+ %div.form-group
+ = f.label :email
+ = f.email_field :email, class: "form-control middle", required: true, title: "Please provide a valid email address."
.form-group.append-bottom-20#password-strength
- = f.password_field :password, class: "form-control bottom", placeholder: "Password - minimum length #{@minimum_password_length} characters", required: true, pattern: ".{#{@minimum_password_length},}", title: "Minimum length is #{@minimum_password_length} characters"
+ = f.label :password
+ = f.password_field :password, class: "form-control bottom", required: true, pattern: ".{#{@minimum_password_length},}", title: "Minimum length is #{@minimum_password_length} characters."
+ %p.gl-field-hint Minimum length is #{@minimum_password_length} characters
%div
- if current_application_settings.recaptcha_enabled
= recaptcha_tags
%div
- = f.submit "Sign up", class: "btn-create btn"
-
-.clearfix.prepend-top-20
+ = f.submit "Register", class: "btn-register btn"
+.clearfix.submit-container
%p
%span.light Didn't receive a confirmation email?
= succeed '.' do
diff --git a/app/views/devise/shared/_tab_single.html.haml b/app/views/devise/shared/_tab_single.html.haml
new file mode 100644
index 00000000000..f943d25e41a
--- /dev/null
+++ b/app/views/devise/shared/_tab_single.html.haml
@@ -0,0 +1,3 @@
+%ul.nav-links.nav-tabs.new-session-tabs.single-tab
+ %li.active
+ %a= tab_title
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
new file mode 100644
index 00000000000..e276e91433a
--- /dev/null
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -0,0 +1,10 @@
+%ul.new-session-tabs.nav-links.nav-tabs
+ - if crowd_enabled?
+ %li.active
+ = link_to "Crowd", "#tab-crowd", 'data-toggle' => 'tab'
+ - @ldap_servers.each_with_index do |server, i|
+ %li{class: (:active if i.zero? && !crowd_enabled?)}
+ = link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab'
+ - if signin_enabled?
+ %li
+ = link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab'
diff --git a/app/views/devise/shared/_tabs_normal.html.haml b/app/views/devise/shared/_tabs_normal.html.haml
new file mode 100644
index 00000000000..79b1d447a92
--- /dev/null
+++ b/app/views/devise/shared/_tabs_normal.html.haml
@@ -0,0 +1,5 @@
+%ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist'}
+ %li.active{ role: 'presentation' }
+ %a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab'} Sign in
+ %li{ role: 'presentation'}
+ %a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab'} Register
diff --git a/app/views/devise/unlocks/new.html.haml b/app/views/devise/unlocks/new.html.haml
index 49c087c0646..49b2f77111f 100644
--- a/app/views/devise/unlocks/new.html.haml
+++ b/app/views/devise/unlocks/new.html.haml
@@ -1,12 +1,12 @@
+= render 'devise/shared/tab_single', tab_title: 'Resend unlock instructions'
.login-box
- .login-heading
- %h3 Resend unlock email
.login-body
- = form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f|
+ = form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post, class: 'show-gl-field-errors' }) do |f|
.devise-errors
= devise_error_messages!
- .clearfix.append-bottom-20
- = f.email_field :email, class: 'form-control', placeholder: 'Email', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off'
+ .form-group.append-bottom-20
+ = f.label :email
+ = f.email_field :email, class: 'form-control', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', title: 'Please provide a valid email address.'
.clearfix
= f.submit 'Resend unlock instructions', class: 'btn btn-success'
diff --git a/app/views/groups/group_members/_new_group_member.html.haml b/app/views/groups/group_members/_new_group_member.html.haml
index 2fb3190ab11..b185b81db7f 100644
--- a/app/views/groups/group_members/_new_group_member.html.haml
+++ b/app/views/groups/group_members/_new_group_member.html.haml
@@ -1,27 +1,22 @@
-= form_for @group_member, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f|
- .form-group
- = f.label :user_ids, "People", class: 'control-label'
- .col-sm-10
- = users_select_tag(:user_ids, multiple: true, class: 'input-large', scope: :all, email_user: true)
- .help-block
+= form_for @group_member, url: group_group_members_path(@group), html: { class: 'users-project-form users-group-form' } do |f|
+ .row
+ .col-md-4.col-lg-6
+ = users_select_tag(:user_ids, multiple: true, class: 'input-clamp', scope: :all, email_user: true)
+ .help-block.append-bottom-10
Search for users by name, username, or email, or invite new ones using their email address.
- .form-group
- = f.label :access_level, "Group Access", class: 'control-label'
- .col-sm-10
- = select_tag :access_level, options_for_select(GroupMember.access_level_roles, @group_member.access_level), class: "project-access-select select2"
- .help-block
- Read more about role permissions
- %strong= link_to "here", help_page_path("user/permissions"), class: "vlink"
+ .col-md-3.col-lg-2
+ = select_tag :access_level, options_for_select(GroupMember.access_level_roles, @group_member.access_level), class: "form-control project-access-select"
+ .help-block.append-bottom-10
+ = link_to "Read more", help_page_path("user/permissions"), class: "vlink"
+ about role permissions
- .form-group
- = f.label :expires_at, 'Access expiration date', class: 'control-label'
- .col-sm-10
+ .col-md-3.col-lg-2
.clearable-input
- = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Select access expiration date'
+ = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
%i.clear-icon.js-clear-input
- .help-block
+ .help-block.append-bottom-10
On this date, the user(s) will automatically lose access to this group and all of its projects.
- .form-actions
- = f.submit 'Add users to group', class: "btn btn-create"
+ .col-md-2
+ = f.submit 'Add to group', class: "btn btn-create btn-block"
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index f789796e942..ebf9aca7700 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -1,35 +1,31 @@
- page_title "Members"
-.group-members-page.prepend-top-default
+.project-members-page.prepend-top-default
+ %h4
+ Members
+ %hr
- if can?(current_user, :admin_group_member, @group)
- .panel.panel-default
- .panel-heading
- Add new user to group
- .panel-body
- %p.light
- Members of group have access to all group projects.
- .new-group-member-holder
- = render "new_group_member"
+ .project-members-new.append-bottom-default
+ %p.clearfix
+ Add new user to
+ %strong= @group.name
+ = render "new_group_member"
= render 'shared/members/requests', membership_source: @group, requesters: @requesters
+ .append-bottom-default.clearfix
+ %h5.member.existing-title
+ Existing users
+ = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do
+ .form-group
+ = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false }
+ %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" }
+ = icon("search")
.panel.panel-default
.panel-heading
+ Users with access to
%strong #{@group.name}
- group members
%span.badge= @members.total_count
- .controls
- = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do
- .form-group
- = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false }
- = button_tag class: 'btn', title: 'Search' do
- = icon("search")
%ul.content-list
= render partial: 'shared/members/member', collection: @members, as: :member
= paginate @members, theme: 'gitlab'
-
-:javascript
- $('form.member-search-form').on('submit', function(event) {
- event.preventDefault();
- Turbolinks.visit(this.action + '?' + $(this).serialize());
- });
diff --git a/app/views/groups/group_members/update.js.haml b/app/views/groups/group_members/update.js.haml
index 3be7ed8432c..de8f53b6b52 100644
--- a/app/views/groups/group_members/update.js.haml
+++ b/app/views/groups/group_members/update.js.haml
@@ -1,3 +1,3 @@
:plain
- $("##{dom_id(@group_member)}").replaceWith('#{escape_javascript(render('shared/members/member', member: @group_member))}');
- new gl.MemberExpirationDate();
+ var $listItem = $('#{escape_javascript(render('shared/members/member', member: @group_member))}');
+ $("##{dom_id(@group_member)} .list-item-name").replaceWith($listItem.find('.list-item-name'));
diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml
index 67ff4b272b9..e138ebab018 100644
--- a/app/views/layouts/_init_auto_complete.html.haml
+++ b/app/views/layouts/_init_auto_complete.html.haml
@@ -1,7 +1,8 @@
- project = @target_project || @project
- noteable_type = @noteable.class if @noteable.present?
-:javascript
- GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: noteable_type, type_id: params[:id])}"
- GitLab.GfmAutoComplete.cachedData = undefined;
- GitLab.GfmAutoComplete.setup();
+- if project
+ :javascript
+ GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: noteable_type, type_id: params[:id])}"
+ GitLab.GfmAutoComplete.cachedData = undefined;
+ GitLab.GfmAutoComplete.setup();
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 15a94ac23c5..6c2285fa2b6 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -11,3 +11,4 @@
= render 'layouts/page', sidebar: sidebar, nav: nav
= yield :scripts_body
+ = render "layouts/init_auto_complete" if @gfm_form
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index a9a384bd5f3..6922f1e153f 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -1,36 +1,37 @@
!!! 5
-%html{ lang: "en"}
+%html{ lang: "en", class: "devise-layout-html"}
= render "layouts/head"
- %body.ui_charcoal.login-page.application.navless
- = Gon::Base.render_data
- = render "layouts/header/empty"
- = render "layouts/broadcast"
- .container.navless-container
- .content
- = render "layouts/flash"
- .row
- .col-sm-5.pull-right
- = yield
- .col-sm-7.brand-holder.pull-left
- %h1
- = brand_title
- - if brand_item
- = brand_image
- = brand_text
- - else
- %h3 Open source software to collaborate on code
+ %body.ui_charcoal.login-page.application.navless{ data: { page: body_data_page }}
+ .page-wrap
+ = Gon::Base.render_data
+ = render "layouts/header/empty"
+ = render "layouts/broadcast"
+ .container.navless-container
+ .content
+ = render "layouts/flash"
+ .row
+ .col-sm-5.pull-right.new-session-forms-container
+ = yield
+ .col-sm-7.brand-holder.pull-left
+ %h1
+ = brand_title
+ - if brand_item
+ = brand_image
+ = brand_text
+ - else
+ %h3 Open source software to collaborate on code
- %p
- Manage git repositories with fine grained access controls that keep your code secure.
- Perform code reviews and enhance collaboration with merge requests.
- Each project can also have an issue tracker and a wiki.
+ %p
+ Manage Git repositories with fine-grained access controls that keep your code secure.
+ Perform code reviews and enhance collaboration with merge requests.
+ Each project can also have an issue tracker and a wiki.
- if current_application_settings.sign_in_text.present?
= markdown_field(current_application_settings, :sign_in_text)
- %hr
- .container
- .footer-links
- = link_to "Explore", explore_root_path
- = link_to "Help", help_path
- = link_to "About GitLab", "https://about.gitlab.com/"
+ %hr.footer-fixed
+ .container.footer-container
+ .footer-links
+ = link_to "Explore", explore_root_path
+ = link_to "Help", help_path
+ = link_to "About GitLab", "https://about.gitlab.com/"
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index c80f22457b4..e2e974ba072 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -86,11 +86,11 @@
= f.label :username, "Path", class: "label-light"
.input-group
.input-group-addon
- = "#{root_url}u/"
+ = root_url
= f.text_field :username, required: true, class: 'form-control'
.help-block
Current path:
- = "#{root_url}u/#{current_user.username}"
+ = "#{root_url}#{current_user.username}"
.prepend-top-default
= f.button class: "btn btn-warning", type: "submit" do
= icon "spinner spin", class: "hidden loading-username"
diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml
index cb97181b9e1..0c8241053e7 100644
--- a/app/views/projects/_zen.html.haml
+++ b/app/views/projects/_zen.html.haml
@@ -1,3 +1,4 @@
+- @gfm_form = true
- supports_slash_commands = local_assigns.fetch(:supports_slash_commands, false)
.zen-backdrop
- classes << ' js-gfm-input js-autosize markdown-area'
@@ -7,6 +8,3 @@
= text_area_tag attr, nil, class: classes, placeholder: placeholder
%a.zen-control.zen-control-leave.js-zen-leave{ href: "#" }
= icon('compress')
-
-- content_for :scripts_body do
- = render "layouts/init_auto_complete" if current_user && (@target_project || @project)
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index 5a98e258b22..dfb96305f48 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -1,45 +1,48 @@
+- @no_container = true
- page_title "Blame", @blob.path, @ref
+= render "projects/commits/head"
-%h3.page-title Blame view
+%div{ class: container_class }
+ %h3.page-title Blame view
-#blob-content-holder.tree-holder
- .file-holder
- .file-title
- = blob_icon @blob.mode, @blob.name
- %strong
- = @path
- %small= number_to_human_size @blob.size
- .file-actions
- = render "projects/blob/actions"
- .table-responsive.file-content.blame.code.js-syntax-highlight
- %table
- - current_line = 1
- - @blame_groups.each do |blame_group|
- %tr
- %td.blame-commit
- .commit
- - commit = blame_group[:commit]
- = author_avatar(commit, size: 36)
- .commit-row-title
- %strong
- = link_to_gfm truncate(commit.title, length: 35), namespace_project_commit_path(@project.namespace, @project, commit.id), class: "cdark"
- .pull-right
- = link_to commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit), class: "monospace"
- &nbsp;
- .light
- = commit_author_link(commit, avatar: false)
- authored
- #{time_ago_with_tooltip(commit.committed_date, skip_js: true)}
- %td.line-numbers
- - line_count = blame_group[:lines].count
- - (current_line...(current_line + line_count)).each do |i|
- %a.diff-line-num{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i}
- = icon("link")
- = i
- \
- - current_line += line_count
- %td.lines
- %pre.code.highlight
- %code
- - blame_group[:lines].each do |line|
- #{line}
+ #blob-content-holder.tree-holder
+ .file-holder
+ .file-title
+ = blob_icon @blob.mode, @blob.name
+ %strong
+ = @path
+ %small= number_to_human_size @blob.size
+ .file-actions
+ = render "projects/blob/actions"
+ .table-responsive.file-content.blame.code.js-syntax-highlight
+ %table
+ - current_line = 1
+ - @blame_groups.each do |blame_group|
+ %tr
+ %td.blame-commit
+ .commit
+ - commit = blame_group[:commit]
+ = author_avatar(commit, size: 36)
+ .commit-row-title
+ %strong
+ = link_to_gfm truncate(commit.title, length: 35), namespace_project_commit_path(@project.namespace, @project, commit.id), class: "cdark"
+ .pull-right
+ = link_to commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit), class: "monospace"
+ &nbsp;
+ .light
+ = commit_author_link(commit, avatar: false)
+ authored
+ #{time_ago_with_tooltip(commit.committed_date, skip_js: true)}
+ %td.line-numbers
+ - line_count = blame_group[:lines].count
+ - (current_line...(current_line + line_count)).each do |i|
+ %a.diff-line-num{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i}
+ = icon("link")
+ = i
+ \
+ - current_line += line_count
+ %td.lines
+ %pre.code.highlight
+ %code
+ - blame_group[:lines].each do |line|
+ #{line}
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index 680e95ac6b5..2a0352a71b7 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -1,28 +1,31 @@
+- @no_container = true
- page_title "Edit", @blob.path, @ref
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/ace.js')
= page_specific_javascript_tag('blob_edit/blob_edit_bundle.js')
+= render "projects/commits/head"
-- if @conflict
- .alert.alert-danger
- Someone edited the file the same time you did. Please check out
- = link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@target_branch, @file_path)), target: "_blank"
- and make sure your changes will not unintentionally remove theirs.
+%div{ class: container_class }
+ - if @conflict
+ .alert.alert-danger
+ Someone edited the file the same time you did. Please check out
+ = link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@target_branch, @file_path)), target: "_blank"
+ and make sure your changes will not unintentionally remove theirs.
-.file-editor
- %ul.nav-links.no-bottom.js-edit-mode
- %li.active
- = link_to '#editor' do
- Edit File
+ .file-editor
+ %ul.nav-links.no-bottom.js-edit-mode
+ %li.active
+ = link_to '#editor' do
+ Edit File
- %li
- = link_to '#preview', 'data-preview-url' => namespace_project_preview_blob_path(@project.namespace, @project, @id) do
- = editing_preview_title(@blob.name)
+ %li
+ = link_to '#preview', 'data-preview-url' => namespace_project_preview_blob_path(@project.namespace, @project, @id) do
+ = editing_preview_title(@blob.name)
- = form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths) do
- = render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data
- = render 'shared/new_commit_form', placeholder: "Update #{@blob.name}"
- = hidden_field_tag 'last_commit_sha', @last_commit_sha
- = hidden_field_tag 'content', '', id: "file-content"
- = hidden_field_tag 'from_merge_request_id', params[:from_merge_request_id]
- = render 'projects/commit_button', ref: @ref, cancel_path: namespace_project_blob_path(@project.namespace, @project, @id)
+ = form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths) do
+ = render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data
+ = render 'shared/new_commit_form', placeholder: "Update #{@blob.name}"
+ = hidden_field_tag 'last_commit_sha', @last_commit_sha
+ = hidden_field_tag 'content', '', id: "file-content"
+ = hidden_field_tag 'from_merge_request_id', params[:from_merge_request_id]
+ = render 'projects/commit_button', ref: @ref, cancel_path: namespace_project_blob_path(@project.namespace, @project, @id)
diff --git a/app/views/projects/builds/_table.html.haml b/app/views/projects/builds/_table.html.haml
index f3747ba2a21..36294c89fa8 100644
--- a/app/views/projects/builds/_table.html.haml
+++ b/app/views/projects/builds/_table.html.haml
@@ -5,7 +5,7 @@
.nothing-here-block No builds to show
- else
.table-holder
- %table.table.builds
+ %table.table.ci-table.builds-page
%thead
%tr
%th Status
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index e4d41288aa6..b5e8b0bf6eb 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -1,56 +1,59 @@
+- @no_container = true
- page_title "#{@build.name} (##{@build.id})", "Builds"
- trace_with_state = @build.trace_with_state
- header_title project_title(@project, "Builds", project_builds_path(@project))
+= render "projects/pipelines/head", build_subnav: true
-.build-page
- = render "header"
+%div{ class: container_class }
+ .build-page
+ = render "header"
- - if @build.stuck?
- - unless @build.any_runners_online?
- .bs-callout.bs-callout-warning
- %p
- - if no_runners_for_project?(@build.project)
- This build is stuck, because the project doesn't have any runners online assigned to it.
- - elsif @build.tags.any?
- This build is stuck, because you don't have any active runners online with any of these tags assigned to them:
- - @build.tags.each do |tag|
- %span.label.label-primary
- = tag
- - else
- This build is stuck, because you don't have any active runners that can run this build.
+ - if @build.stuck?
+ - unless @build.any_runners_online?
+ .bs-callout.bs-callout-warning
+ %p
+ - if no_runners_for_project?(@build.project)
+ This build is stuck, because the project doesn't have any runners online assigned to it.
+ - elsif @build.tags.any?
+ This build is stuck, because you don't have any active runners online with any of these tags assigned to them:
+ - @build.tags.each do |tag|
+ %span.label.label-primary
+ = tag
+ - else
+ This build is stuck, because you don't have any active runners that can run this build.
- %br
- Go to
- = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do
- Runners page
+ %br
+ Go to
+ = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do
+ Runners page
- .prepend-top-default
- - if @build.active?
- .autoscroll-container
- %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll
- - if @build.erased?
- .erased.alert.alert-warning
- - erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by
- Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)}
- - else
- #js-build-scroll.scroll-controls
- = link_to '#build-trace', class: 'btn' do
- %i.fa.fa-angle-up
- = link_to '#down-build-trace', class: 'btn' do
- %i.fa.fa-angle-down
- %pre.build-trace#build-trace
- %code.bash.js-build-output
- = icon("refresh spin", class: "js-build-refresh")
+ .prepend-top-default
+ - if @build.active?
+ .autoscroll-container
+ %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll
+ - if @build.erased?
+ .erased.alert.alert-warning
+ - erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by
+ Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)}
+ - else
+ #js-build-scroll.scroll-controls
+ = link_to '#build-trace', class: 'btn' do
+ %i.fa.fa-angle-up
+ = link_to '#down-build-trace', class: 'btn' do
+ %i.fa.fa-angle-down
+ %pre.build-trace#build-trace
+ %code.bash.js-build-output
+ = icon("refresh spin", class: "js-build-refresh")
- #down-build-trace
+ #down-build-trace
-= render "sidebar"
+ = render "sidebar"
-:javascript
- new Build({
- page_url: "#{namespace_project_build_url(@project.namespace, @project, @build)}",
- build_url: "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}",
- build_status: "#{@build.status}",
- build_stage: "#{@build.stage}",
- state1: "#{trace_with_state[:state]}"
- })
+ :javascript
+ new Build({
+ page_url: "#{namespace_project_build_url(@project.namespace, @project, @build)}",
+ build_url: "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}",
+ build_status: "#{@build.status}",
+ build_stage: "#{@build.stage}",
+ state1: "#{trace_with_state[:state]}"
+ })
diff --git a/app/views/projects/commit/_pipeline.html.haml b/app/views/projects/commit/_pipeline.html.haml
index 288c06d9b67..d6916fb7f1a 100644
--- a/app/views/projects/commit/_pipeline.html.haml
+++ b/app/views/projects/commit/_pipeline.html.haml
@@ -56,7 +56,7 @@
\.gitlab-ci.yml not found in this commit
.table-holder.pipeline-holder
- %table.table.builds.pipeline
+ %table.table.ci-table.pipeline
%thead
%tr
%th Status
diff --git a/app/views/projects/commit/_pipelines_list.haml b/app/views/projects/commit/_pipelines_list.haml
index 998812793a2..640651e93f5 100644
--- a/app/views/projects/commit/_pipelines_list.haml
+++ b/app/views/projects/commit/_pipelines_list.haml
@@ -4,7 +4,7 @@
.nothing-here-block No pipelines to show
- else
.table-holder
- %table.table.builds
+ %table.table.ci-table
%tbody
%th Status
%th Pipeline
diff --git a/app/views/projects/commit/builds.html.haml b/app/views/projects/commit/builds.html.haml
index 2f051fb90e0..f9d7eac3542 100644
--- a/app/views/projects/commit/builds.html.haml
+++ b/app/views/projects/commit/builds.html.haml
@@ -1,7 +1,10 @@
+- @no_container = true
- page_title "Builds", "#{@commit.title} (#{@commit.short_id})", "Commits"
+= render "projects/commits/head"
-.prepend-top-default
- = render "commit_box"
+%div{ class: container_class }
+ .prepend-top-default
+ = render "commit_box"
-= render "ci_menu"
-= render "builds"
+ = render "ci_menu"
+ = render "builds"
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index ed44d86a687..cebf58d63df 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -1,14 +1,17 @@
+- @no_container = true
- page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
- page_description @commit.description
+= render "projects/commits/head"
-.prepend-top-default
- = render "commit_box"
-- if @commit.status
- = render "ci_menu"
-- else
- %div.block-connector
-= render "projects/diffs/diffs", diffs: @diffs
-= render "projects/notes/notes_with_form"
-- if can_collaborate_with_project?
- - %w(revert cherry-pick).each do |type|
- = render "projects/commit/change", type: type, commit: @commit, title: @commit.title
+%div{ class: container_class }
+ .prepend-top-default
+ = render "commit_box"
+ - if @commit.status
+ = render "ci_menu"
+ - else
+ %div.block-connector
+ = render "projects/diffs/diffs", diffs: @diffs
+ = render "projects/notes/notes_with_form"
+ - if can_collaborate_with_project?
+ - %w(revert cherry-pick).each do |type|
+ = render "projects/commit/change", type: type, commit: @commit, title: @commit.title
diff --git a/app/views/projects/compare/_ref_dropdown.html.haml b/app/views/projects/compare/_ref_dropdown.html.haml
index 27d928c87a0..05fb37cdc0f 100644
--- a/app/views/projects/compare/_ref_dropdown.html.haml
+++ b/app/views/projects/compare/_ref_dropdown.html.haml
@@ -1,5 +1,5 @@
.dropdown-menu.dropdown-menu-selectable
- = dropdown_title "Select branch/tag"
- = dropdown_filter "Filter by branch/tag"
+ = dropdown_title "Select Git revision"
+ = dropdown_filter "Filter by Git revision"
= dropdown_content
= dropdown_loading
diff --git a/app/views/projects/environments/edit.html.haml b/app/views/projects/environments/edit.html.haml
index 6d1bdb9320f..3871165763c 100644
--- a/app/views/projects/environments/edit.html.haml
+++ b/app/views/projects/environments/edit.html.haml
@@ -1,6 +1,9 @@
+- @no_container = true
- page_title "Edit", @environment.name, "Environments"
+= render "projects/pipelines/head"
-%h3.page-title
- Edit environment
-%hr
-= render 'form'
+%div{ class: container_class }
+ %h3.page-title
+ Edit environment
+ %hr
+ = render 'form'
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index ab801409722..721ba156334 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -24,7 +24,7 @@
New environment
- else
.table-holder
- %table.table.builds.environments
+ %table.table.ci-table.environments
%tbody
%th Environment
%th Last Deployment
diff --git a/app/views/projects/environments/new.html.haml b/app/views/projects/environments/new.html.haml
index e51667ade2d..24638c77cbb 100644
--- a/app/views/projects/environments/new.html.haml
+++ b/app/views/projects/environments/new.html.haml
@@ -1,6 +1,9 @@
+- @no_container = true
- page_title 'New Environment'
+= render "projects/pipelines/head"
-%h3.page-title
- New environment
-%hr
-= render 'form'
+%div{ class: container_class }
+ %h3.page-title
+ New environment
+ %hr
+ = render 'form'
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 7a8d196cf4e..90c59223a35 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -24,7 +24,7 @@
= link_to "Read more", help_page_path("ci/environments"), class: "btn btn-success"
- else
.table-holder
- %table.table.builds.environments
+ %table.table.ci-table.environments
%thead
%tr
%th ID
diff --git a/app/views/projects/group_links/update.js.haml b/app/views/projects/group_links/update.js.haml
new file mode 100644
index 00000000000..af9a5b19060
--- /dev/null
+++ b/app/views/projects/group_links/update.js.haml
@@ -0,0 +1,3 @@
+:plain
+ var $listItem = $('#{escape_javascript(render('shared/members/group', group_link: @group_link))}');
+ $("#group_member_#{@group_link.id} .list-item-name").replaceWith($listItem.find('.list-item-name'));
diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml
index 6901ba13ab7..52b187e7e58 100644
--- a/app/views/projects/labels/edit.html.haml
+++ b/app/views/projects/labels/edit.html.haml
@@ -1,6 +1,9 @@
+- @no_container = true
- page_title "Edit", @label.name, "Labels"
+= render "projects/issues/head"
-%h3.page-title
- Edit Label
-%hr
-= render 'form'
+%div{ class: container_class }
+ %h3.page-title
+ Edit Label
+ %hr
+ = render 'form'
diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml
index 49ddf901619..a1bb66cfb6c 100644
--- a/app/views/projects/labels/new.html.haml
+++ b/app/views/projects/labels/new.html.haml
@@ -1,6 +1,9 @@
+- @no_container = true
- page_title "New Label"
+= render "projects/issues/head"
-%h3.page-title
- New Label
-%hr
-= render 'form'
+%div{ class: container_class }
+ %h3.page-title
+ New Label
+ %hr
+ = render 'form'
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 47dd51639b5..662463bc72b 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -47,7 +47,7 @@
= link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
- if @commits_count.nonzero?
- %ul.merge-request-tabs.nav-links.no-top.no-bottom
+ %ul.merge-request-tabs.nav-links.no-top.no-bottom{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') }
%li.notes-tab
= link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do
Discussion
diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml
index be682226ab6..11f41e75e63 100644
--- a/app/views/projects/milestones/edit.html.haml
+++ b/app/views/projects/milestones/edit.html.haml
@@ -1,8 +1,12 @@
+- @no_container = true
- page_title "Edit", @milestone.title, "Milestones"
+= render "projects/issues/head"
-%h3.page-title
- Edit Milestone ##{@milestone.iid}
+%div{ class: container_class }
-%hr
+ %h3.page-title
+ Edit Milestone ##{@milestone.iid}
-= render "form"
+ %hr
+
+ = render "form"
diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml
index 7f372b41698..cda093ade81 100644
--- a/app/views/projects/milestones/new.html.haml
+++ b/app/views/projects/milestones/new.html.haml
@@ -1,8 +1,11 @@
+- @no_container = true
- page_title "New Milestone"
+= render "projects/issues/head"
-%h3.page-title
- New Milestone
+%div{ class: container_class }
+ %h3.page-title
+ New Milestone
-%hr
+ %hr
-= render "form"
+ = render "form"
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index e62f810a521..c83818e9199 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -1,49 +1,52 @@
+- @no_container = true
- page_title @milestone.title, "Milestones"
- page_description @milestone.description
+= render "projects/issues/head"
-.detail-page-header
- .status-box{ class: status_box_class(@milestone) }
- - if @milestone.closed?
- Closed
- - elsif @milestone.expired?
- Past due
- - else
- Open
- %span.identifier
- Milestone ##{@milestone.iid}
- - if @milestone.expires_at
- %span.creator
- &middot;
- = @milestone.expires_at
- .pull-right
- - if can?(current_user, :admin_milestone, @project)
- - if @milestone.active?
- = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-nr btn-grouped"
+%div{ class: container_class }
+ .detail-page-header
+ .status-box{ class: status_box_class(@milestone) }
+ - if @milestone.closed?
+ Closed
+ - elsif @milestone.expired?
+ Past due
- else
- = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-nr btn-grouped"
+ Open
+ %span.identifier
+ Milestone ##{@milestone.iid}
+ - if @milestone.expires_at
+ %span.creator
+ &middot;
+ = @milestone.expires_at
+ .pull-right
+ - if can?(current_user, :admin_milestone, @project)
+ - if @milestone.active?
+ = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-nr btn-grouped"
+ - else
+ = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-nr btn-grouped"
- = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped btn-nr" do
- Edit
+ = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped btn-nr" do
+ Edit
- = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-danger" do
- Delete
+ = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-danger" do
+ Delete
-.detail-page-description.milestone-detail
- %h2.title
- = markdown_field(@milestone, :title)
- %div
- - if @milestone.description.present?
- .description
- .wiki
- = preserve do
- = markdown_field(@milestone, :description)
+ .detail-page-description.milestone-detail
+ %h2.title
+ = markdown_field(@milestone, :title)
+ %div
+ - if @milestone.description.present?
+ .description
+ .wiki
+ = preserve do
+ = markdown_field(@milestone, :description)
-- if @milestone.total_items_count(current_user).zero?
- .alert.alert-success.prepend-top-default
- %span Assign some issues to this milestone.
-- elsif @milestone.complete?(current_user) && @milestone.active?
- .alert.alert-success.prepend-top-default
- %span All issues for this milestone are closed. You may close this milestone now.
+ - if @milestone.total_items_count(current_user).zero?
+ .alert.alert-success.prepend-top-default
+ %span Assign some issues to this milestone.
+ - elsif @milestone.complete?(current_user) && @milestone.active?
+ .alert.alert-success.prepend-top-default
+ %span All issues for this milestone are closed. You may close this milestone now.
-= render 'shared/milestones/summary', milestone: @milestone, project: @project
-= render 'shared/milestones/tabs', milestone: @milestone
+ = render 'shared/milestones/summary', milestone: @milestone, project: @project
+ = render 'shared/milestones/tabs', milestone: @milestone
diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml
index 8352eba7446..00b62a595ff 100644
--- a/app/views/projects/notes/_notes_with_form.html.haml
+++ b/app/views/projects/notes/_notes_with_form.html.haml
@@ -14,7 +14,7 @@
.disabled-comment.text-center
.disabled-comment-text.inline
Please
- = link_to "sign up", new_session_path(:user, redirect_to_referer: 'yes')
+ = link_to "register", new_session_path(:user, redirect_to_referer: 'yes')
or
= link_to "sign in", new_session_path(:user, redirect_to_referer: 'yes')
to post a comment
diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml
index 7d421c0e740..b10dd47709f 100644
--- a/app/views/projects/pipelines/_head.html.haml
+++ b/app/views/projects/pipelines/_head.html.haml
@@ -1,7 +1,7 @@
= content_for :sub_nav do
.scrolling-tabs-container.sub-nav-scroll
= render 'shared/nav_scroll'
- .nav-links.sub-nav.scrolling-tabs
+ .nav-links.sub-nav.scrolling-tabs{ class: ('build' if local_assigns.fetch(:build_subnav, false)) }
%ul{ class: (container_class) }
- if project_nav_tab? :pipelines
= nav_link(controller: :pipelines) do
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index 2d1df095bfa..9eeef5f57b4 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -43,7 +43,7 @@
.nothing-here-block No pipelines to show
- else
.table-holder
- %table.table.builds
+ %table.table.ci-table
%thead
%th.col-xs-1.col-sm-1 Status
%th.col-xs-2.col-sm-4 Pipeline
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index 75943c64276..688535ad764 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -1,8 +1,11 @@
+- @no_container = true
- page_title "Pipeline"
+= render "projects/pipelines/head"
-.prepend-top-default
- - if @commit
- = render "projects/pipelines/info"
- %div.block-connector
+%div{ class: container_class }
+ .prepend-top-default
+ - if @commit
+ = render "projects/pipelines/info"
+ %div.block-connector
-= render "projects/commit/pipeline", pipeline: @pipeline
+ = render "projects/commit/pipeline", pipeline: @pipeline
diff --git a/app/views/projects/project_members/_group_members.html.haml b/app/views/projects/project_members/_group_members.html.haml
index e783d8c72c5..9738f369a35 100644
--- a/app/views/projects/project_members/_group_members.html.haml
+++ b/app/views/projects/project_members/_group_members.html.haml
@@ -1,7 +1,7 @@
.panel.panel-default
.panel-heading
+ Group members with access to
%strong #{@group.name}
- group members
%span.badge= members.size
- if can?(current_user, :admin_group_member, @group)
.controls
diff --git a/app/views/projects/project_members/_groups.html.haml b/app/views/projects/project_members/_groups.html.haml
new file mode 100644
index 00000000000..d7f5fa96527
--- /dev/null
+++ b/app/views/projects/project_members/_groups.html.haml
@@ -0,0 +1,7 @@
+.panel.panel-default.project-members-groups
+ .panel-heading
+ Groups with access to
+ %strong #{@project.name}
+ %span.badge= group_links.size
+ %ul.content-list
+ = render partial: 'shared/members/group', collection: group_links, as: :group_link
diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml
index fa8cbf71733..79dcd7a6ee9 100644
--- a/app/views/projects/project_members/_new_project_member.html.haml
+++ b/app/views/projects/project_members/_new_project_member.html.haml
@@ -1,27 +1,22 @@
-= form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project), html: { class: 'form-horizontal users-project-form' } do |f|
- .form-group
- = f.label :user_ids, "People", class: 'control-label'
- .col-sm-10
- = users_select_tag(:user_ids, multiple: true, class: 'input-large', scope: :all, email_user: true)
- .help-block
+= form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project), html: { class: 'users-project-form' } do |f|
+ .row
+ .col-md-4.col-lg-6
+ = users_select_tag(:user_ids, multiple: true, class: "input-clamp", scope: :all, email_user: true)
+ .help-block.append-bottom-10
Search for users by name, username, or email, or invite new ones using their email address.
- .form-group
- = f.label :access_level, "Project Access", class: 'control-label'
- .col-sm-10
- = select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "project-access-select select2"
- .help-block
- Read more about role permissions
- %strong= link_to "here", help_page_path("user/permissions"), class: "vlink"
+ .col-md-3.col-lg-2
+ = select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "form-control project-access-select"
+ .help-block.append-bottom-10
+ = link_to "Read more", help_page_path("user/permissions"), class: "vlink"
+ about role permissions
- .form-group
- = f.label :expires_at, 'Access expiration date', class: 'control-label'
- .col-sm-10
+ .col-md-3.col-lg-2
.clearable-input
- = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Select access expiration date'
+ = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
%i.clear-icon.js-clear-input
- .help-block
+ .help-block.append-bottom-10
On this date, the user(s) will automatically lose access to this project.
- .form-actions
- = f.submit 'Add users to project', class: "btn btn-create"
+ .col-md-2
+ = f.submit "Add to project", class: "btn btn-create btn-block"
diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml
index b0bfdd235f7..c1e894d8f40 100644
--- a/app/views/projects/project_members/_team.html.haml
+++ b/app/views/projects/project_members/_team.html.haml
@@ -1,19 +1,7 @@
.panel.panel-default
.panel-heading
+ Users with access to
%strong #{@project.name}
- project members
- %span.badge= members.size
- .controls
- = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do
- .form-group
- = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false }
- = button_tag class: 'btn', title: 'Search' do
- = icon("search")
+ %span.badge= @project_members.total_count
%ul.content-list
= render partial: 'shared/members/member', collection: members, as: :member
-
-:javascript
- $('form.member-search-form').on('submit', function (event) {
- event.preventDefault();
- Turbolinks.visit(this.action + '?' + $(this).serialize());
- });
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 9d063b3081f..bdeb704b6da 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -1,24 +1,28 @@
- page_title "Members"
-.project-members-page.js-project-members-page.prepend-top-default
+.project-members-page.prepend-top-default
+ %h4.project-members-title.clearfix
+ Members
+ = link_to "Import", import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-default pull-right hidden-xs", title: "Import members from another project"
- if can?(current_user, :admin_project_member, @project)
- .panel.panel-default
- .panel-heading
- Add new user to project
- .controls
- = link_to import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-grouped", title: "Import members from another project" do
- Import members
- .panel-body
- %p.light
- Users with access to this project are listed below.
- = render "new_project_member"
+ .project-members-new.append-bottom-default
+ %p.clearfix
+ Add new user to
+ %strong= @project.name
+ = render "new_project_member"
- = render 'shared/members/requests', membership_source: @project, requesters: @requesters
+ = render 'shared/members/requests', membership_source: @project, requesters: @requesters
- = render 'team', members: @project_members
-
- - if @group
- = render "group_members", members: @group_members
+ .append-bottom-default.clearfix
+ %h5.member.existing-title
+ Existing users and groups
+ = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do
+ .form-group
+ = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false }
+ %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" }
+ = icon("search")
+ - if @group_links.any?
+ = render 'groups', group_links: @group_links
- - if @project_group_links.any? && @project.allowed_to_share_with_group?
- = render "shared_group_members"
+ = render 'team', members: @project_members
+ = paginate @project_members, theme: "gitlab"
diff --git a/app/views/projects/project_members/update.js.haml b/app/views/projects/project_members/update.js.haml
index 37e55dc72a3..91927181efb 100644
--- a/app/views/projects/project_members/update.js.haml
+++ b/app/views/projects/project_members/update.js.haml
@@ -1,3 +1,3 @@
:plain
- $("##{dom_id(@project_member)}").replaceWith('#{escape_javascript(render('shared/members/member', member: @project_member))}');
- new gl.MemberExpirationDate();
+ var $listItem = $('#{escape_javascript(render('shared/members/member', member: @project_member))}');
+ $("##{dom_id(@project_member)} .list-item-name").replaceWith($listItem.find('.list-item-name'));
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index a75653d842f..a7944a60130 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -23,6 +23,8 @@
data: { data: issuable_template_names, field_name: 'issuable_template', selected: selected_template(issuable), project_path: ref_project.path, namespace_path: ref_project.namespace.path } } ) do
%ul.dropdown-footer-list
%li
+ %a.no-template
+ No template
%a.reset-template
Reset template
%div{ class: issuable_template_names.any? ? 'col-sm-7 col-lg-8' : 'col-sm-10' }
diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml
new file mode 100644
index 00000000000..1c0346bbc78
--- /dev/null
+++ b/app/views/shared/members/_group.html.haml
@@ -0,0 +1,29 @@
+- group_link = local_assigns[:group_link]
+- group = group_link.group
+- can_admin_member = can?(current_user, :admin_project_member, @project)
+%li.member.group_member{ id: "group_member_#{group_link.id}" }
+ %span{ class: "list-item-name" }
+ = image_tag group_icon(group), class: "avatar s40", alt: ''
+ %strong
+ = link_to group.name, group_path(group)
+ .cgray
+ Joined #{time_ago_with_tooltip(group.created_at)}
+ - if group_link.expires?
+ ·
+ %span{ class: ('text-warning' if group_link.expires_soon?) }
+ Expires in #{distance_of_time_in_words_to_now(group_link.expires_at)}
+ .controls.member-controls
+ = form_tag namespace_project_group_link_path(@project.namespace, @project, group_link), method: :put, remote: true, class: 'form-horizontal js-edit-member-form' do
+ = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}", disabled: !can_admin_member
+ .prepend-left-5.clearable-input.member-form-control
+ = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}", disabled: !can_admin_member
+ %i.clear-icon.js-clear-input
+ - if can_admin_member
+ = link_to namespace_project_group_link_path(@project.namespace, @project, group_link),
+ remote: true,
+ method: :delete,
+ data: { confirm: "Are you sure you want to remove #{group.name}?" },
+ class: 'btn btn-remove prepend-left-10' do
+ %span.visible-xs-block
+ Delete
+ = icon('trash', class: 'hidden-xs')
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 5f20e4bd42a..432047a1c4e 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -1,59 +1,29 @@
- show_roles = local_assigns.fetch(:show_roles, true)
- show_controls = local_assigns.fetch(:show_controls, true)
-- user = member.user
+- user = local_assigns.fetch(:user, member.user)
+- source = member.source
+- can_admin_member = can?(current_user, action_member_permission(:update, member), member)
-%li.js-toggle-container{ class: dom_class(member), id: dom_id(member) }
- - if show_roles
- .controls
- %strong.control-text= member.human_access
- - if show_controls
- - if !user && can?(current_user, action_member_permission(:admin, member), member.source)
- = link_to 'Resend invite', polymorphic_path([:resend_invite, member]),
- method: :post,
- class: 'btn'
-
- - if can?(current_user, action_member_permission(:update, member), member)
- = button_tag icon('pencil'),
- type: 'button',
- class: 'btn inline js-toggle-button',
- title: 'Edit'
-
- - if member.request?
- = link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]),
- method: :post,
- class: 'btn btn-success',
- title: 'Grant access'
-
- - if can?(current_user, action_member_permission(:destroy, member), member)
- - if current_user == user
- = link_to icon('sign-out', text: 'Leave'), polymorphic_path([:leave, member.source, :members]),
- method: :delete,
- data: { confirm: leave_confirmation_message(member.source) },
- class: 'btn btn-remove'
- - else
- = link_to icon('trash'), member,
- remote: true,
- method: :delete,
- data: { confirm: remove_member_message(member) },
- class: 'btn btn-remove',
- title: remove_member_title(member)
-
-
- %span{ class: ("list-item-name" if show_controls) }
+%li.member{ class: dom_class(member), id: dom_id(member) }
+ %span.list-item-name
- if user
= image_tag avatar_icon(user, 40), class: "avatar s40", alt: ''
%strong
= link_to user.name, user_path(user)
- %span.cgray= user.username
+ %span.cgray= user.to_reference
- if user == current_user
- %span.label.label-success It's you
+ %span.label.label-success.prepend-left-5 It's you
- if user.blocked?
%label.label.label-danger
%strong Blocked
- .cgray
+ - if source.instance_of?(Group) && !@group
+ = link_to source, class: "member-group-link prepend-left-5" do
+ = "· #{source.name}"
+
+ .hidden-xs.cgray
- if member.request?
Requested
= time_ago_with_tooltip(member.requested_at)
@@ -73,20 +43,44 @@
by
= link_to member.created_by.name, user_path(member.created_by)
= time_ago_with_tooltip(member.created_at)
-
- if show_roles
- .edit-member.hide.js-toggle-content
- %br
- = form_for member, remote: true, html: { class: 'form-horizontal' } do |f|
- .form-group
- = label_tag "member_access_level_#{member.id}", 'Project access', class: 'control-label'
- .col-sm-10
- = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control', id: "member_access_level_#{member.id}"
- .form-group
- = label_tag "member_expires_at_#{member.id}", 'Access expiration date', class: 'control-label'
- .col-sm-10
- .clearable-input
- = f.text_field :expires_at, class: 'form-control js-access-expiration-date', placeholder: 'Select access expiration date', id: "member_expires_at_#{member.id}"
+ .controls.member-controls
+ - if show_controls
+ - if user != current_user
+ = form_for member, remote: true, html: { class: 'form-horizontal js-edit-member-form' } do |f|
+ = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can_admin_member
+ .prepend-left-5.clearable-input.member-form-control
+ = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can_admin_member
%i.clear-icon.js-clear-input
- .prepend-top-10
- = f.submit 'Save', class: 'btn btn-save btn-sm'
+ - else
+ %span.member-access-text= member.human_access
+
+ - if member.invite? && can?(current_user, action_member_permission(:admin, member), member.source)
+ = link_to 'Resend invite', polymorphic_path([:resend_invite, member]),
+ method: :post,
+ class: 'btn btn-default prepend-left-10'
+
+ - elsif member.request? && can_admin_member
+ = link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]),
+ method: :post,
+ class: 'btn btn-success prepend-left-10',
+ title: 'Grant access'
+
+ - if can?(current_user, action_member_permission(:destroy, member), member)
+ - if current_user == user
+ = link_to icon('sign-out', text: 'Leave'), polymorphic_path([:leave, member.source, :members]),
+ method: :delete,
+ data: { confirm: leave_confirmation_message(member.source) },
+ class: 'btn btn-remove prepend-left-10'
+ - else
+ = link_to member,
+ remote: true,
+ method: :delete,
+ data: { confirm: remove_member_message(member) },
+ class: 'btn btn-remove prepend-left-10',
+ title: remove_member_title(member) do
+ %span.visible-xs-block
+ Delete
+ = icon('trash', class: 'hidden-xs')
+ - else
+ %span.member-access-text= member.human_access
diff --git a/app/views/shared/members/_requests.html.haml b/app/views/shared/members/_requests.html.haml
index 40b39e850b0..10050adfda5 100644
--- a/app/views/shared/members/_requests.html.haml
+++ b/app/views/shared/members/_requests.html.haml
@@ -1,8 +1,8 @@
- if requesters.any?
.panel.panel-default
.panel-heading
+ Users requesting access to
%strong= membership_source.name
- access requests
%span.badge= requesters.size
%ul.content-list
= render partial: 'shared/members/member', collection: requesters, as: :member
diff --git a/app/views/u2f/_authenticate.html.haml b/app/views/u2f/_authenticate.html.haml
index 9657101ace5..232ca26c1af 100644
--- a/app/views/u2f/_authenticate.html.haml
+++ b/app/views/u2f/_authenticate.html.haml
@@ -6,7 +6,7 @@
%script#js-authenticate-u2f-setup{ type: "text/template" }
%div
%p Insert your security key (if you haven't already), and press the button below.
- %a.btn.btn-info#js-login-u2f-device{ href: 'javascript:void(0)' } Login Via U2F Device
+ %a.btn.btn-info#js-login-u2f-device{ href: 'javascript:void(0)' } Sign in via U2F device
%script#js-authenticate-u2f-in-progress{ type: "text/template" }
%p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.
diff --git a/app/workers/build_coverage_worker.rb b/app/workers/build_coverage_worker.rb
new file mode 100644
index 00000000000..0680645a8db
--- /dev/null
+++ b/app/workers/build_coverage_worker.rb
@@ -0,0 +1,9 @@
+class BuildCoverageWorker
+ include Sidekiq::Worker
+ sidekiq_options queue: :default
+
+ def perform(build_id)
+ Ci::Build.find_by(id: build_id)
+ .try(:update_coverage)
+ end
+end
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
new file mode 100644
index 00000000000..e7286b77ac5
--- /dev/null
+++ b/app/workers/build_finished_worker.rb
@@ -0,0 +1,10 @@
+class BuildFinishedWorker
+ include Sidekiq::Worker
+
+ def perform(build_id)
+ Ci::Build.find_by(id: build_id).try do |build|
+ BuildCoverageWorker.new.perform(build.id)
+ BuildHooksWorker.new.perform(build.id)
+ end
+ end
+end
diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb
new file mode 100644
index 00000000000..e22ececb3fd
--- /dev/null
+++ b/app/workers/build_hooks_worker.rb
@@ -0,0 +1,9 @@
+class BuildHooksWorker
+ include Sidekiq::Worker
+ sidekiq_options queue: :default
+
+ def perform(build_id)
+ Ci::Build.find_by(id: build_id)
+ .try(:execute_hooks)
+ end
+end
diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb
new file mode 100644
index 00000000000..500d357ce31
--- /dev/null
+++ b/app/workers/build_success_worker.rb
@@ -0,0 +1,27 @@
+class BuildSuccessWorker
+ include Sidekiq::Worker
+ sidekiq_options queue: :default
+
+ def perform(build_id)
+ Ci::Build.find_by(id: build_id).try do |build|
+ create_deployment(build)
+ end
+ end
+
+ private
+
+ def create_deployment(build)
+ return if build.environment.blank?
+
+ service = CreateDeploymentService.new(
+ 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
diff --git a/app/workers/pipeline_hooks_worker.rb b/app/workers/pipeline_hooks_worker.rb
new file mode 100644
index 00000000000..ab5e9f6daad
--- /dev/null
+++ b/app/workers/pipeline_hooks_worker.rb
@@ -0,0 +1,9 @@
+class PipelineHooksWorker
+ include Sidekiq::Worker
+ sidekiq_options queue: :default
+
+ def perform(pipeline_id)
+ Ci::Pipeline.find_by(id: pipeline_id)
+ .try(:execute_hooks)
+ end
+end