Commit a2eff1a8 authored by Phil Hughes's avatar Phil Hughes

Merge branch 'master' into issue-board-sidebar

parents 13f170fc 3d174c71
...@@ -210,7 +210,7 @@ rake brakeman: *exec ...@@ -210,7 +210,7 @@ rake brakeman: *exec
rake flay: *exec rake flay: *exec
license_finder: *exec license_finder: *exec
rake downtime_check: *exec rake downtime_check: *exec
rake ce_to_ee_merge_check: rake ee_compat_check:
<<: *exec <<: *exec
only: only:
- branches - branches
...@@ -279,16 +279,20 @@ bundler:audit: ...@@ -279,16 +279,20 @@ bundler:audit:
migration paths: migration paths:
stage: test stage: test
<<: *use-db <<: *use-db
variables:
SETUP_DB: "false"
only: only:
- master@gitlab-org/gitlab-ce - master@gitlab-org/gitlab-ce
script: script:
- git checkout HEAD . - git checkout HEAD .
- git fetch --tags - git fetch --tags
- git checkout v8.5.9 - git checkout v8.5.9
- 'echo test: unix:/var/opt/gitlab/redis/redis.socket > config/resque.yml' - cp config/resque.yml.example config/resque.yml
- sed -i 's/localhost/redis/g' config/resque.yml
- bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}" --retry=3 - bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}" --retry=3
- rake db:drop db:create db:schema:load db:seed_fu - rake db:drop db:create db:schema:load db:seed_fu
- git checkout $CI_BUILD_REF - git checkout $CI_BUILD_REF
- source scripts/prepare_build.sh
- rake db:migrate - rake db:migrate
coverage: coverage:
......
...@@ -5,7 +5,7 @@ require: ...@@ -5,7 +5,7 @@ require:
inherit_from: .rubocop_todo.yml inherit_from: .rubocop_todo.yml
AllCops: AllCops:
TargetRubyVersion: 2.3 TargetRubyVersion: 2.1
# Cop names are not d§splayed in offense messages by default. Change behavior # Cop names are not d§splayed in offense messages by default. Change behavior
# by overriding DisplayCopNames, or by giving the -D/--display-cop-names # by overriding DisplayCopNames, or by giving the -D/--display-cop-names
# option. # option.
......
...@@ -172,7 +172,7 @@ linters: ...@@ -172,7 +172,7 @@ linters:
# Split selectors onto separate lines after each comma, and have each # Split selectors onto separate lines after each comma, and have each
# individual selector occupy a single line. # individual selector occupy a single line.
SingleLinePerSelector: SingleLinePerSelector:
enabled: false enabled: true
# Commas in lists should be followed by a space. # Commas in lists should be followed by a space.
SpaceAfterComma: SpaceAfterComma:
...@@ -191,7 +191,7 @@ linters: ...@@ -191,7 +191,7 @@ linters:
# Variables should be formatted with a single space separating the colon # Variables should be formatted with a single space separating the colon
# from the variable's value. # from the variable's value.
SpaceAfterVariableColon: SpaceAfterVariableColon:
enabled: false enabled: true
# Variables should be formatted with no space between the name and the # Variables should be formatted with no space between the name and the
# colon. # colon.
...@@ -201,7 +201,7 @@ linters: ...@@ -201,7 +201,7 @@ linters:
# Operators should be formatted with a single space on both sides of an # Operators should be formatted with a single space on both sides of an
# infix operator. # infix operator.
SpaceAroundOperator: SpaceAroundOperator:
enabled: false enabled: true
# Opening braces should be preceded by a single space. # Opening braces should be preceded by a single space.
SpaceBeforeBrace: SpaceBeforeBrace:
...@@ -223,7 +223,7 @@ linters: ...@@ -223,7 +223,7 @@ linters:
# Reports lines containing trailing whitespace. # Reports lines containing trailing whitespace.
TrailingWhitespace: TrailingWhitespace:
enabled: false enabled: true
# Don't write trailing zeros for numeric values with a decimal point. # Don't write trailing zeros for numeric values with a decimal point.
TrailingZero: TrailingZero:
......
...@@ -2,11 +2,39 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -2,11 +2,39 @@ Please view this file on the master branch, on stable branches it's out of date.
## 8.14.0 (2016-11-22) ## 8.14.0 (2016-11-22)
- Adds user project membership expired event to clarify why user was removed (Callum Dryden) - Adds user project membership expired event to clarify why user was removed (Callum Dryden)
- Trim leading and trailing whitespace on project_path (Linus Thiel)
- Prevent award emoji via notes for issues/MRs authored by user (barthc)
- Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO)
- Fix extra space on Build sidebar on Firefox !7060
- Fix HipChat notifications rendering (airatshigapov, eisnerd)
- Add hover to trash icon in notes !7008 (blackst0ne)
- Escape ref and path for relative links !6050 (winniehell)
- Simpler arguments passed to named_route on toggle_award_url helper method - Simpler arguments passed to named_route on toggle_award_url helper method
- Fix: Backup restore doesn't clear cache
- Replace jquery.cookie plugin with js.cookie !7085
- Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method
- Fix Sign in page 'Forgot your password?' link overlaps on medium-large screens
- Fix documents and comments on Build API `scope`
- Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov)
## 8.13.1 (unreleased)
- Fix bug where labels would be assigned to issues that were moved
- Fix error in generating labels
- Fix reply-by-email not working due to queue name mismatch
- Fixed hidden pipeline graph on commit and MR page !6895
- Expire and build repository cache after project import
- Reduce overhead of LabelFinder by avoiding #presence call !7094
- Fix 404 for group pages when GitLab setup uses relative url
- Simpler arguments passed to named_route on toggle_award_url helper method
- Fix unauthorized users dragging on issue boards
- Better handle when no users were selected for adding to group or project. (Linus Thiel)
- Only show register tab if signup enabled.
- Only schedule ProjectCacheWorker jobs when needed
## 8.13.0 (2016-10-22) ## 8.13.0 (2016-10-22)
- Removes extra line for empty issue description. (!7045)
- Fix save button on project pipeline settings page. (!6955) - Fix save button on project pipeline settings page. (!6955)
- All Sidekiq workers now use their own queue
- Avoid race condition when asynchronously removing expired artifacts. (!6881) - Avoid race condition when asynchronously removing expired artifacts. (!6881)
- Improve Merge When Build Succeeds triggers and execute on pipeline success. (!6675) - Improve Merge When Build Succeeds triggers and execute on pipeline success. (!6675)
- Respond with 404 Not Found for non-existent tags (Linus Thiel) - Respond with 404 Not Found for non-existent tags (Linus Thiel)
...@@ -22,27 +50,35 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -22,27 +50,35 @@ Please view this file on the master branch, on stable branches it's out of date.
- Add `/projects/visible` API endpoint (Ben Boeckel) - Add `/projects/visible` API endpoint (Ben Boeckel)
- Fix centering of custom header logos (Ashley Dumaine) - Fix centering of custom header logos (Ashley Dumaine)
- Keep around commits only pipeline creation as pipeline data doesn't change over time - Keep around commits only pipeline creation as pipeline data doesn't change over time
- Update duration at the end of pipeline
- ExpireBuildArtifactsWorker query builds table without ordering enqueuing one job per build to cleanup - ExpireBuildArtifactsWorker query builds table without ordering enqueuing one job per build to cleanup
- Add group level labels. (!6425) - Add group level labels. (!6425)
- Fix Cycle analytics not showing correct data when filtering by date. !6906
- Add an example for testing a phoenix application with Gitlab CI in the docs (Manthan Mallikarjun) - Add an example for testing a phoenix application with Gitlab CI in the docs (Manthan Mallikarjun)
- Cancelled pipelines could be retried. !6927 - Cancelled pipelines could be retried. !6927
- Updating verbiage on git basics to be more intuitive - Updating verbiage on git basics to be more intuitive
- Fix project_feature record not generated on project creation
- Clarify documentation for Runners API (Gennady Trafimenkov) - Clarify documentation for Runners API (Gennady Trafimenkov)
- The instrumentation for Banzai::Renderer has been restored - The instrumentation for Banzai::Renderer has been restored
- Change user & group landing page routing from /u/:username to /:username - Change user & group landing page routing from /u/:username to /:username
- Fixed issue boards user link when in subdirectory
- Added documentation for .gitattributes files - Added documentation for .gitattributes files
- Move Pipeline Metrics to separate worker - Move Pipeline Metrics to separate worker
- AbstractReferenceFilter caches project_refs on RequestStore when active - AbstractReferenceFilter caches project_refs on RequestStore when active
- Replaced the check sign to arrow in the show build view. !6501 - Replaced the check sign to arrow in the show build view. !6501
- Add a /wip slash command to toggle the Work In Progress status of a merge request. !6259 (tbalthazar) - Add a /wip slash command to toggle the Work In Progress status of a merge request. !6259 (tbalthazar)
- ProjectCacheWorker updates caches at most once per 15 minutes per project
- Fix Error 500 when viewing old merge requests with bad diff data - Fix Error 500 when viewing old merge requests with bad diff data
- Create a new /templates namespace for the /licenses, /gitignores and /gitlab_ci_ymls API endpoints. !5717 (tbalthazar) - Create a new /templates namespace for the /licenses, /gitignores and /gitlab_ci_ymls API endpoints. !5717 (tbalthazar)
- Fix viewing merged MRs when the source project has been removed !6991
- Speed-up group milestones show page - Speed-up group milestones show page
- Fix inconsistent options dropdown caret on mobile viewports (ClemMakesApps) - Fix inconsistent options dropdown caret on mobile viewports (ClemMakesApps)
- Extract project#update_merge_requests and SystemHooks to its own worker from GitPushService - Extract project#update_merge_requests and SystemHooks to its own worker from GitPushService
- Fix discussion thread from emails for merge requests. !7010
- Don't include archived projects when creating group milestones. !4940 (Jeroen Jacobs) - Don't include archived projects when creating group milestones. !4940 (Jeroen Jacobs)
- Add tag shortcut from the Commit page. !6543 - Add tag shortcut from the Commit page. !6543
- Keep refs for each deployment - Keep refs for each deployment
- Close open tooltips on page navigation (Linus Thiel)
- Allow browsing branches that end with '.atom' - Allow browsing branches that end with '.atom'
- Log LDAP lookup errors and don't swallow unrelated exceptions. !6103 (Markus Koller) - Log LDAP lookup errors and don't swallow unrelated exceptions. !6103 (Markus Koller)
- Replace unique keyframes mixin with keyframe mixin with specific names (ClemMakesApps) - Replace unique keyframes mixin with keyframe mixin with specific names (ClemMakesApps)
...@@ -70,12 +106,14 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -70,12 +106,14 @@ Please view this file on the master branch, on stable branches it's out of date.
- Add RTL support to markdown renderer (Ebrahim Byagowi) - Add RTL support to markdown renderer (Ebrahim Byagowi)
- Add word-wrap to issue title on issue and milestone boards (ClemMakesApps) - Add word-wrap to issue title on issue and milestone boards (ClemMakesApps)
- Fix todos page mobile viewport layout (ClemMakesApps) - Fix todos page mobile viewport layout (ClemMakesApps)
- Make issues search less finicky
- Fix inconsistent highlighting of already selected activity nav-links (ClemMakesApps) - Fix inconsistent highlighting of already selected activity nav-links (ClemMakesApps)
- Remove redundant mixins (ClemMakesApps) - Remove redundant mixins (ClemMakesApps)
- Added 'Download' button to the Snippets page (Justin DiPierro) - Added 'Download' button to the Snippets page (Justin DiPierro)
- Add visibility level to project repository - Add visibility level to project repository
- Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison) - Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison)
- Close open merge request without source project (Katarzyna Kobierska Ula Budziszewska) - Close open merge request without source project (Katarzyna Kobierska Ula Budziszewska)
- Fix showing commits from source project for merge request !6658
- Fix that manual jobs would no longer block jobs in the next stage. !6604 - Fix that manual jobs would no longer block jobs in the next stage. !6604
- Add configurable email subject suffix (Fu Xu) - Add configurable email subject suffix (Fu Xu)
- Use defined colour for a language when available !6748 (nilsding) - Use defined colour for a language when available !6748 (nilsding)
...@@ -136,6 +174,7 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -136,6 +174,7 @@ Please view this file on the master branch, on stable branches it's out of date.
- Fix buggy iOS tooltip layering behavior. - Fix buggy iOS tooltip layering behavior.
- Make guests unable to view MRs on private projects - Make guests unable to view MRs on private projects
- Fix broken Project API docs (Takuya Noguchi) - Fix broken Project API docs (Takuya Noguchi)
- Migrate invalid project members (owner -> master)
## 8.12.7 ## 8.12.7
...@@ -369,6 +408,7 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -369,6 +408,7 @@ Please view this file on the master branch, on stable branches it's out of date.
- Fix inconsistent checkbox alignment (ClemMakesApps) - Fix inconsistent checkbox alignment (ClemMakesApps)
- Use the default branch for displaying the project icon instead of master !5792 (Hannes Rosenögger) - Use the default branch for displaying the project icon instead of master !5792 (Hannes Rosenögger)
- Adds response mime type to transaction metric action when it's not HTML - Adds response mime type to transaction metric action when it's not HTML
- Fix branch protection API !6215
- Fix hover leading space bug in pipeline graph !5980 - Fix hover leading space bug in pipeline graph !5980
- Avoid conflict with admin labels when importing GitHub labels - Avoid conflict with admin labels when importing GitHub labels
- User can edit closed MR with deleted fork (Katarzyna Kobierska Ula Budziszewska) !5496 - User can edit closed MR with deleted fork (Katarzyna Kobierska Ula Budziszewska) !5496
......
...@@ -24,9 +24,7 @@ ...@@ -24,9 +24,7 @@
var filter = sender.attr("id").split("_")[0]; var filter = sender.attr("id").split("_")[0];
$('.event-filter .active').removeClass("active"); $('.event-filter .active').removeClass("active");
$.cookie("event_filter", filter, { Cookies.set("event_filter", filter);
path: gon.relative_url_root || '/'
});
sender.closest('li').toggleClass("active"); sender.closest('li').toggleClass("active");
}; };
......
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
/*= require jquery-ui/effect-highlight */ /*= require jquery-ui/effect-highlight */
/*= require jquery-ui/sortable */ /*= require jquery-ui/sortable */
/*= require jquery_ujs */ /*= require jquery_ujs */
/*= require jquery.cookie */
/*= require jquery.endless-scroll */ /*= require jquery.endless-scroll */
/*= require jquery.highlight */ /*= require jquery.highlight */
/*= require jquery.waitforimages */ /*= require jquery.waitforimages */
/*= require jquery.atwho */ /*= require jquery.atwho */
/*= require jquery.scrollTo */ /*= require jquery.scrollTo */
/*= require jquery.turbolinks */ /*= require jquery.turbolinks */
/*= require js.cookie */
/*= require turbolinks */ /*= require turbolinks */
/*= require autosave */ /*= require autosave */
/*= require bootstrap/affix */ /*= require bootstrap/affix */
...@@ -83,14 +83,15 @@ ...@@ -83,14 +83,15 @@
}; };
// Disable button if text field is empty // Disable button if text field is empty
window.disableButtonIfEmptyField = function(field_selector, button_selector) { window.disableButtonIfEmptyField = function(field_selector, button_selector, event_name) {
event_name = event_name || 'input';
var closest_submit, field; var closest_submit, field;
field = $(field_selector); field = $(field_selector);
closest_submit = field.closest('form').find(button_selector); closest_submit = field.closest('form').find(button_selector);
if (rstrip(field.val()) === "") { if (rstrip(field.val()) === "") {
closest_submit.disable(); closest_submit.disable();
} }
return field.on('input', function() { return field.on(event_name, function() {
if (rstrip($(this).val()) === "") { if (rstrip($(this).val()) === "") {
return closest_submit.disable(); return closest_submit.disable();
} else { } else {
...@@ -123,15 +124,11 @@ ...@@ -123,15 +124,11 @@
return str.replace(/<(?:.|\n)*?>/gm, ''); return str.replace(/<(?:.|\n)*?>/gm, '');
}; };
window.unbindEvents = function() {
return $(document).off('scroll');
};
window.shiftWindow = function() { window.shiftWindow = function() {
return scrollBy(0, -100); return scrollBy(0, -100);
}; };
document.addEventListener("page:fetch", unbindEvents); document.addEventListener("page:fetch", gl.utils.cleanupBeforeFetch);
window.addEventListener("hashchange", shiftWindow); window.addEventListener("hashchange", shiftWindow);
...@@ -148,6 +145,10 @@ ...@@ -148,6 +145,10 @@
$document = $(document); $document = $(document);
$window = $(window); $window = $(window);
$body = $('body'); $body = $('body');
// Set the default path for all cookies to GitLab's root directory
Cookies.defaults.path = gon.relative_url_root || '/';
gl.utils.preventDisabledButtons(); gl.utils.preventDisabledButtons();
bootstrapBreakpoint = bp.getBreakpointSize(); bootstrapBreakpoint = bp.getBreakpointSize();
$(".nav-sidebar").niceScroll({ $(".nav-sidebar").niceScroll({
......
...@@ -322,21 +322,18 @@ ...@@ -322,21 +322,18 @@
var frequentlyUsedEmojis; var frequentlyUsedEmojis;
frequentlyUsedEmojis = this.getFrequentlyUsedEmojis(); frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();
frequentlyUsedEmojis.push(emoji); frequentlyUsedEmojis.push(emoji);
return $.cookie('frequently_used_emojis', frequentlyUsedEmojis.join(','), { Cookies.set('frequently_used_emojis', frequentlyUsedEmojis.join(','), { expires: 365 });
path: gon.relative_url_root || '/',
expires: 365
});
}; };
AwardsHandler.prototype.getFrequentlyUsedEmojis = function() { AwardsHandler.prototype.getFrequentlyUsedEmojis = function() {
var frequentlyUsedEmojis; var frequentlyUsedEmojis;
frequentlyUsedEmojis = ($.cookie('frequently_used_emojis') || '').split(','); frequentlyUsedEmojis = (Cookies.get('frequently_used_emojis') || '').split(',');
return _.compact(_.uniq(frequentlyUsedEmojis)); return _.compact(_.uniq(frequentlyUsedEmojis));
}; };
AwardsHandler.prototype.renderFrequentlyUsedBlock = function() { AwardsHandler.prototype.renderFrequentlyUsedBlock = function() {
var emoji, frequentlyUsedEmojis, i, len, ul; var emoji, frequentlyUsedEmojis, i, len, ul;
if ($.cookie('frequently_used_emojis')) { if (Cookies.get('frequently_used_emojis')) {
frequentlyUsedEmojis = this.getFrequentlyUsedEmojis(); frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();
ul = $("<ul class='clearfix emoji-menu-list frequent-emojis'>"); ul = $("<ul class='clearfix emoji-menu-list frequent-emojis'>");
for (i = 0, len = frequentlyUsedEmojis.length; i < len; i++) { for (i = 0, len = frequentlyUsedEmojis.length; i < len; i++) {
......
...@@ -68,14 +68,10 @@ ...@@ -68,14 +68,10 @@
// To be implemented on the extending class // To be implemented on the extending class
// e.g. // e.g.
// Api.gitignoreText item.name, @requestFileSuccess.bind(@) // Api.gitignoreText item.name, @requestFileSuccess.bind(@)
requestFileSuccess(file, { skipFocus, append } = {}) { requestFileSuccess(file, { skipFocus } = {}) {
const oldValue = this.editor.getValue(); const oldValue = this.editor.getValue();
let newValue = file.content; let newValue = file.content;
if (append && oldValue.length && oldValue !== newValue) {
newValue = oldValue + '\n\n' + newValue;
}
this.editor.setValue(newValue, 1); this.editor.setValue(newValue, 1);
if (!skipFocus) this.editor.focus(); if (!skipFocus) this.editor.focus();
...@@ -99,4 +95,3 @@ ...@@ -99,4 +95,3 @@
global.TemplateSelector = TemplateSelector; global.TemplateSelector = TemplateSelector;
})(window.gl || ( window.gl = {})); })(window.gl || ( window.gl = {}));
...@@ -61,12 +61,12 @@ ...@@ -61,12 +61,12 @@
removeBlankState () { removeBlankState () {
this.removeList('blank'); this.removeList('blank');
$.cookie('issue_board_welcome_hidden', 'true', { Cookies.set('issue_board_welcome_hidden', 'true', {
expires: 365 * 10 expires: 365 * 10
}); });
}, },
welcomeIsHidden () { welcomeIsHidden () {
return $.cookie('issue_board_welcome_hidden') === 'true'; return Cookies.get('issue_board_welcome_hidden') === 'true';
}, },
removeList (id, type = 'blank') { removeList (id, type = 'blank') {
const list = this.findList('id', id, type); const list = this.findList('id', id, type);
......
...@@ -148,7 +148,7 @@ ...@@ -148,7 +148,7 @@
}; };
Build.prototype.translateSidebar = function(e) { Build.prototype.translateSidebar = function(e) {
var newPosition = this.sidebarTranslationLimits.max - document.body.scrollTop; var newPosition = this.sidebarTranslationLimits.max - (document.body.scrollTop || document.documentElement.scrollTop);
if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min; if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min;
this.$sidebar.css({ this.$sidebar.css({
top: newPosition top: newPosition
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
const store = gl.cycleAnalyticsStore = { const store = gl.cycleAnalyticsStore = {
isLoading: true, isLoading: true,
hasError: false, hasError: false,
isHelpDismissed: $.cookie(COOKIE_NAME), isHelpDismissed: Cookies.get(COOKIE_NAME),
analytics: {} analytics: {}
}; };
...@@ -36,7 +36,11 @@ ...@@ -36,7 +36,11 @@
method: 'GET', method: 'GET',
dataType: 'json', dataType: 'json',
contentType: 'application/json', contentType: 'application/json',
data: { start_date: options.startDate } data: {
cycle_analytics: {
start_date: options.startDate
}
}
}).done((data) => { }).done((data) => {
this.decorateData(data); this.decorateData(data);
this.initDropdown(); this.initDropdown();
...@@ -71,9 +75,7 @@ ...@@ -71,9 +75,7 @@
dismissLanding() { dismissLanding() {
store.isHelpDismissed = true; store.isHelpDismissed = true;
$.cookie(COOKIE_NAME, true, { Cookies.set(COOKIE_NAME, true);
path: gon.relative_url_root || '/'
});
} }
initDropdown() { initDropdown() {
......
...@@ -117,6 +117,9 @@ ...@@ -117,6 +117,9 @@
new ZenMode(); new ZenMode();
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
break; break;
case 'projects:commit:builds':
new gl.Pipelines();
break;
case 'projects:commits:show': case 'projects:commits:show':
case 'projects:activity': case 'projects:activity':
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
......
Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatches;
Element.prototype.closest = function closest(selector, selectedElement = this) {
if (!selectedElement) return;
return selectedElement.matches(selector) ? selectedElement : Element.prototype.closest(selector, selectedElement.parentElement);
};
...@@ -137,8 +137,11 @@ ...@@ -137,8 +137,11 @@
} }
initValidators () { initValidators () {
// select all non-hidden inputs in form // register selectors here as needed
this.state.inputs = this.form.find(':input:not([type=hidden])').toArray() const validateSelectors = [':text', ':password', '[type=email]']
.map((selector) => `input${selector}`).join(',');
this.state.inputs = this.form.find(validateSelectors).toArray()
.filter((input) => !input.classList.contains(customValidationFlag)) .filter((input) => !input.classList.contains(customValidationFlag))
.map((input) => new GlFieldError({ input, formErrors: this })); .map((input) => new GlFieldError({ input, formErrors: this }));
......
...@@ -15,16 +15,61 @@ ...@@ -15,16 +15,61 @@
return Issuable.labelRow = _.template('<% _.each(labels, function(label){ %> <span class="label-row btn-group" role="group" aria-label="<%- label.title %>" style="color: <%- label.text_color %>;"> <a href="#" class="btn btn-transparent has-tooltip" style="background-color: <%- label.color %>;" title="<%- label.description %>" data-container="body"> <%- label.title %> </a> <button type="button" class="btn btn-transparent label-remove js-label-filter-remove" style="background-color: <%- label.color %>;" data-label="<%- label.title %>"> <i class="fa fa-times"></i> </button> </span> <% }); %>'); return Issuable.labelRow = _.template('<% _.each(labels, function(label){ %> <span class="label-row btn-group" role="group" aria-label="<%- label.title %>" style="color: <%- label.text_color %>;"> <a href="#" class="btn btn-transparent has-tooltip" style="background-color: <%- label.color %>;" title="<%- label.description %>" data-container="body"> <%- label.title %> </a> <button type="button" class="btn btn-transparent label-remove js-label-filter-remove" style="background-color: <%- label.color %>;" data-label="<%- label.title %>"> <i class="fa fa-times"></i> </button> </span> <% }); %>');
}, },
initSearch: function() { initSearch: function() {
const $searchInput = $('#issuable_search');
Issuable.initSearchState($searchInput);
// `immediate` param set to false debounces on the `trailing` edge, lets user finish typing // `immediate` param set to false debounces on the `trailing` edge, lets user finish typing
const debouncedExecSearch = _.debounce(Issuable.executeSearch, 500, false); const debouncedExecSearch = _.debounce(Issuable.executeSearch, 1000, false);
$('#issuable_search').off('keyup').on('keyup', debouncedExecSearch); $searchInput.off('keyup').on('keyup', debouncedExecSearch);
// ensures existing filters are preserved when manually submitted // ensures existing filters are preserved when manually submitted
$('#issue_search_form').on('submit', (e) => { $('#issuable_search_form').on('submit', (e) => {
e.preventDefault(); e.preventDefault();
debouncedExecSearch(e); debouncedExecSearch(e);
}); });
},
initSearchState: function($searchInput) {
const currentSearchVal = $searchInput.val();
Issuable.searchState = {
elem: $searchInput,
current: currentSearchVal
};
Issuable.maybeFocusOnSearch();
},
accessSearchPristine: function(set) {
// store reference to previous value to prevent search on non-mutating keyup
const state = Issuable.searchState;
const currentSearchVal = state.elem.val();
if (set) {
state.current = currentSearchVal;
} else {
return state.current === currentSearchVal;
}
},
maybeFocusOnSearch: function() {
const currentSearchVal = Issuable.searchState.current;
if (currentSearchVal && currentSearchVal !== '') {
const queryLength = currentSearchVal.length;
const $searchInput = Issuable.searchState.elem;
/* The following ensures that the cursor is initially placed at
* the end of search input when focus is applied. It accounts
* for differences in browser implementations of `setSelectionRange`
* and cursor placement for elements in focus.
*/
$searchInput.focus();
if ($searchInput.setSelectionRange) {
$searchInput.setSelectionRange(queryLength, queryLength);
} else {
$searchInput.val(currentSearchVal);
}
}
}, },
executeSearch: function(e) { executeSearch: function(e) {
const $search = $('#issuable_search'); const $search = $('#issuable_search');
...@@ -32,6 +77,11 @@ ...@@ -32,6 +77,11 @@
const $searchValue = $search.val(); const $searchValue = $search.val();
const $filtersForm = $('.js-filter-form'); const $filtersForm = $('.js-filter-form');
const $input = $(`input[name='${$searchName}']`, $filtersForm); const $input = $(`input[name='${$searchName}']`, $filtersForm);
const isPristine = Issuable.accessSearchPristine();
if (isPristine) {
return;
}
if (!$input.length) { if (!$input.length) {
$filtersForm.append(`<input type='hidden' name='${$searchName}' value='${_.escape($searchValue)}'/>`); $filtersForm.append(`<input type='hidden' name='${$searchName}' value='${_.escape($searchValue)}'/>`);
......
...@@ -43,6 +43,14 @@ ...@@ -43,6 +43,14 @@
parser.href = url; parser.href = url;
return parser; return parser;
}; };
gl.utils.cleanupBeforeFetch = function() {
// Unbind scroll events
$(document).off('scroll');
// Close any open tooltips
$('.has-tooltip, [data-toggle="tooltip"]').tooltip('destroy');
};
return jQuery.timefor = function(time, suffix, expiredLabel) { return jQuery.timefor = function(time, suffix, expiredLabel) {
var suffixFromNow, timefor; var suffixFromNow, timefor;
if (!time) { if (!time) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
$('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow); $('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow);
$('.js-member-update-control').off('change').on('change', this.formSubmit); $('.js-member-update-control').off('change').on('change', this.formSubmit);
$('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess); $('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess);
disableButtonIfEmptyField('#user_ids', 'input[name=commit]', 'change');
} }
removeRow(e) { removeRow(e) {
......
((global) => { ((global) => {
global.mergeConflicts = global.mergeConflicts || {}; global.mergeConflicts = global.mergeConflicts || {};
const diffViewType = $.cookie('diff_view'); const diffViewType = Cookies.get('diff_view');
const HEAD_HEADER_TEXT = 'HEAD//our changes'; const HEAD_HEADER_TEXT = 'HEAD//our changes';
const ORIGIN_HEADER_TEXT = 'origin//their changes'; const ORIGIN_HEADER_TEXT = 'origin//their changes';
const HEAD_BUTTON_TITLE = 'Use ours'; const HEAD_BUTTON_TITLE = 'Use ours';
...@@ -180,9 +180,7 @@ ...@@ -180,9 +180,7 @@
this.state.diffView = viewType; this.state.diffView = viewType;
this.state.isParallel = viewType === VIEW_TYPES.PARALLEL; this.state.isParallel = viewType === VIEW_TYPES.PARALLEL;
$.cookie('diff_view', viewType, { Cookies.set('diff_view', viewType);
path: gon.relative_url_root || '/'
});
}, },
getHeadHeaderLine(id) { getHeadHeaderLine(id) {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// Handles persisting and restoring the current tab selection and lazily-loading // Handles persisting and restoring the current tab selection and lazily-loading
// content on the MergeRequests#show page. // content on the MergeRequests#show page.
// //
/*= require jquery.cookie */ /*= require js.cookie */
// //
// ### Example Markup // ### Example Markup
...@@ -282,6 +282,7 @@ ...@@ -282,6 +282,7 @@
document.querySelector("div#builds").innerHTML = data.html; document.querySelector("div#builds").innerHTML = data.html;
gl.utils.localTimeAgo($('.js-timeago', 'div#builds')); gl.utils.localTimeAgo($('.js-timeago', 'div#builds'));
_this.buildsLoaded = true; _this.buildsLoaded = true;
if (!this.pipelines) this.pipelines = new gl.Pipelines();
return _this.scrollToElement("#builds"); return _this.scrollToElement("#builds");
}; };
})(this) })(this)
...@@ -367,7 +368,7 @@ ...@@ -367,7 +368,7 @@
MergeRequestTabs.prototype.expandView = function() { MergeRequestTabs.prototype.expandView = function() {
var $gutterIcon; var $gutterIcon;
if ($.cookie('collapsed_gutter') === 'true') { if (Cookies.get('collapsed_gutter') === 'true') {
return; return;
} }
$gutterIcon = $('.js-sidebar-toggle i:visible'); $gutterIcon = $('.js-sidebar-toggle i:visible');
...@@ -388,28 +389,25 @@ ...@@ -388,28 +389,25 @@
// So we dont affix the tabs on these // So we dont affix the tabs on these
if (Breakpoints.get().getBreakpointSize() === 'xs' || !$tabs.length) return; if (Breakpoints.get().getBreakpointSize() === 'xs' || !$tabs.length) return;
var tabsWidth = $tabs.outerWidth(), var $diffTabs = $('#diff-notes-app'),
$diffTabs = $('#diff-notes-app'), $fixedNav = $('.navbar-fixed-top'),
offsetTop = $tabs.offset().top - ($('.navbar-fixed-top').height() + $('.layout-nav').height()); $layoutNav = $('.layout-nav');
$tabs.off('affix.bs.affix affix-top.bs.affix') $tabs.off('affix.bs.affix affix-top.bs.affix')
.affix({ .affix({
offset: { offset: {
top: offsetTop top: function () {
var tabsTop = $diffTabs.offset().top - $tabs.height();
tabsTop = tabsTop - ($fixedNav.height() + $layoutNav.height());
return tabsTop;
}
} }
}).on('affix.bs.affix', function () { }).on('affix.bs.affix', function () {
$tabs.css({
left: $tabs.offset().left,
width: tabsWidth
});
$diffTabs.css({ $diffTabs.css({
marginTop: $tabs.height() marginTop: $tabs.height()
}); });
}).on('affix-top.bs.affix', function () { }).on('affix-top.bs.affix', function () {
$tabs.css({
left: '',
width: ''
});
$diffTabs.css({ $diffTabs.css({
marginTop: '' marginTop: ''
}); });
......
...@@ -2,36 +2,39 @@ ...@@ -2,36 +2,39 @@
class Pipelines { class Pipelines {
constructor() { constructor() {
$(document).off('click', '.toggle-pipeline-btn').on('click', '.toggle-pipeline-btn', this.toggleGraph); this.initGraphToggle();
this.addMarginToBuildColumns(); this.addMarginToBuildColumns();
} }
toggleGraph() { initGraphToggle() {
const $pipelineBtn = $(this).closest('.toggle-pipeline-btn'); this.pipelineGraph = document.querySelector('.pipeline-graph');
const $pipelineGraph = $(this).closest('.row-content-block').next('.pipeline-graph'); this.toggleButton = document.querySelector('.toggle-pipeline-btn');
const $btnText = $(this).find('.toggle-btn-text'); this.toggleButtonText = this.toggleButton.querySelector('.toggle-btn-text');
const graphCollapsed = $pipelineGraph.hasClass('graph-collapsed'); this.toggleButton.addEventListener('click', this.toggleGraph.bind(this));
}
$($pipelineBtn).add($pipelineGraph).toggleClass('graph-collapsed');
graphCollapsed ? $btnText.text('Hide') : $btnText.text('Expand') toggleGraph() {
const graphCollapsed = this.pipelineGraph.classList.contains('graph-collapsed');
this.toggleButton.classList.toggle('graph-collapsed');
this.pipelineGraph.classList.toggle('graph-collapsed');
this.toggleButtonText.textContent = graphCollapsed ? 'Hide' : 'Expand';
} }
addMarginToBuildColumns() { addMarginToBuildColumns() {
const $secondChildBuildNode = $('.build:nth-child(2)'); const secondChildBuildNodes = this.pipelineGraph.querySelectorAll('.build:nth-child(2)');
if ($secondChildBuildNode.length) { for (buildNodeIndex in secondChildBuildNodes) {
const $firstChildBuildNode = $secondChildBuildNode.prev('.build'); const buildNode = secondChildBuildNodes[buildNodeIndex];
const $multiBuildColumn = $secondChildBuildNode.closest('.stage-column'); const firstChildBuildNode = buildNode.previousElementSibling;
const $previousColumn = $multiBuildColumn.prev('.stage-column'); if (!firstChildBuildNode || !firstChildBuildNode.matches('.build')) continue;
$multiBuildColumn.addClass('left-margin'); const multiBuildColumn = buildNode.closest('.stage-column');
$firstChildBuildNode.addClass('left-connector'); const previousColumn = multiBuildColumn.previousElementSibling;
$previousColumn.each(function() { if (!previousColumn || !previousColumn.matches('.stage-column')) continue;
$this = $(this); multiBuildColumn.classList.add('left-margin');
if ($('.build', $this).length === 1) $this.addClass('no-margin'); firstChildBuildNode.classList.add('left-connector');
}); const columnBuilds = previousColumn.querySelectorAll('.build');
if (columnBuilds.length === 1) previousColumn.classList.add('no-margin');
} }
$('.pipeline-graph').removeClass('hidden'); this.pipelineGraph.classList.remove('hidden');
} }
} }
......
...@@ -23,16 +23,12 @@ ...@@ -23,16 +23,12 @@
return $(this).parents('form').submit(); return $(this).parents('form').submit();
}); });
$('.hide-no-ssh-message').on('click', function(e) { $('.hide-no-ssh-message').on('click', function(e) {
$.cookie('hide_no_ssh_message', 'false', { Cookies.set('hide_no_ssh_message', 'false');
path: gon.relative_url_root || '/'
});
$(this).parents('.no-ssh-key-message').remove(); $(this).parents('.no-ssh-key-message').remove();
return e.preventDefault(); return e.preventDefault();
}); });
$('.hide-no-password-message').on('click', function(e) { $('.hide-no-password-message').on('click', function(e) {
$.cookie('hide_no_password_message', 'false', { Cookies.set('hide_no_password_message', 'false');
path: gon.relative_url_root || '/'
});
$(this).parents('.no-password-message').remove(); $(this).parents('.no-password-message').remove();
return e.preventDefault(); return e.preventDefault();
}); });
......
...@@ -38,9 +38,7 @@ ...@@ -38,9 +38,7 @@
$('.page-with-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); $('.page-with-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
} }
if (!triggered) { if (!triggered) {
return $.cookie("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed'), { return Cookies.set("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed'));
path: gon.relative_url_root || '/'
});
} }
}); });
return $(document).off('click', '.js-issuable-todo').on('click', '.js-issuable-todo', this.toggleTodo); return $(document).off('click', '.js-issuable-todo').on('click', '.js-issuable-todo', this.toggleTodo);
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
} }
init() { init() {
this.isPinned = $.cookie(pinnedStateCookie) === 'true'; this.isPinned = Cookies.get(pinnedStateCookie) === 'true';
this.isExpanded = ( this.isExpanded = (
window.innerWidth >= sidebarBreakpoint && window.innerWidth >= sidebarBreakpoint &&
$(pageSelector).hasClass(expandedPageClass) $(pageSelector).hasClass(expandedPageClass)
...@@ -62,10 +62,7 @@ ...@@ -62,10 +62,7 @@
if (!this.isPinned) { if (!this.isPinned) {
this.isExpanded = false; this.isExpanded = false;
} }
$.cookie(pinnedStateCookie, this.isPinned ? 'true' : 'false', { Cookies.set(pinnedStateCookie, this.isPinned ? 'true' : 'false', { expires: 3650 });
path: gon.relative_url_root || '/',
expires: 3650
});
this.renderState(); this.renderState();
} }
......
...@@ -32,24 +32,22 @@ ...@@ -32,24 +32,22 @@
this.currentTemplate = currentTemplate; this.currentTemplate = currentTemplate;
if (err) return; // Error handled by global AJAX error handler if (err) return; // Error handled by global AJAX error handler
this.stopLoadingSpinner(); this.stopLoadingSpinner();
this.setInputValueToTemplateContent(true); this.setInputValueToTemplateContent();
}); });
return; return;
} }
setInputValueToTemplateContent(append) { setInputValueToTemplateContent() {
// `this.requestFileSuccess` sets the value of the description input field // `this.requestFileSuccess` sets the value of the description input field
// to the content of the template selected. If `append` is true, the // to the content of the template selected.
// template content will be appended to the previous value of the field,
// separated by a blank line if the previous value is non-empty.
if (this.titleInput.val() === '') { if (this.titleInput.val() === '') {
// If the title has not yet been set, focus the title input and // If the title has not yet been set, focus the title input and
// skip focusing the description input by setting `true` as the // skip focusing the description input by setting `true` as the
// `skipFocus` option to `requestFileSuccess`. // `skipFocus` option to `requestFileSuccess`.
this.requestFileSuccess(this.currentTemplate, {skipFocus: true, append}); this.requestFileSuccess(this.currentTemplate, {skipFocus: true});
this.titleInput.focus(); this.titleInput.focus();
} else { } else {
this.requestFileSuccess(this.currentTemplate, {skipFocus: false, append}); this.requestFileSuccess(this.currentTemplate, {skipFocus: false});
} }
return; return;
} }
......
...@@ -23,10 +23,7 @@ ...@@ -23,10 +23,7 @@
hideProjectLimitMessage() { hideProjectLimitMessage() {
$('.hide-project-limit-message').on('click', e => { $('.hide-project-limit-message').on('click', e => {
e.preventDefault(); e.preventDefault();
const path = gon.relative_url_root || '/'; Cookies.set('hide_project_limit_message', 'false');
$.cookie('hide_project_limit_message', 'false', {
path: path
});
$(this).parents('.project-limit-message').remove(); $(this).parents('.project-limit-message').remove();
}); });
} }
......
...@@ -37,7 +37,8 @@ ...@@ -37,7 +37,8 @@
} }
@include keyframes(pulse) { @include keyframes(pulse) {
from, to { from,
to {
@include webkit-prefix(transform, scale3d(1, 1, 1)); @include webkit-prefix(transform, scale3d(1, 1, 1));
} }
......
...@@ -128,7 +128,8 @@ ...@@ -128,7 +128,8 @@
position: relative; position: relative;
.avatar-holder { .avatar-holder {
.avatar, .identicon { .avatar,
.identicon {
margin: 0 auto; margin: 0 auto;
float: none; float: none;
} }
......
...@@ -213,7 +213,8 @@ ...@@ -213,7 +213,8 @@
top: 2px; top: 2px;
} }
svg, .fa { svg,
.fa {
&:not(:last-child) { &:not(:last-child) {
margin-right: 3px; margin-right: 3px;
} }
......
...@@ -143,7 +143,8 @@ li.note { ...@@ -143,7 +143,8 @@ li.note {
} }
} }
.wiki_content code, .readme code { .wiki_content code,
.readme code {
background-color: inherit; background-color: inherit;
} }
...@@ -350,7 +351,8 @@ table { ...@@ -350,7 +351,8 @@ table {
margin-right: 10px; margin-right: 10px;
} }
.alert, .progress { .alert,
.progress {
margin-bottom: $gl-padding; margin-bottom: $gl-padding;
} }
...@@ -372,3 +374,5 @@ table { ...@@ -372,3 +374,5 @@ table {
margin-right: -$gl-padding; margin-right: -$gl-padding;
border-top: 1px solid $border-color; border-top: 1px solid $border-color;
} }
.hide-bottom-border { border-bottom: none !important; }
...@@ -275,7 +275,8 @@ ...@@ -275,7 +275,8 @@
a { a {
padding-left: 25px; padding-left: 25px;
&.is-indeterminate, &.is-active { &.is-indeterminate,
&.is-active {
&::before { &::before {
position: absolute; position: absolute;
left: 5px; left: 5px;
...@@ -373,7 +374,8 @@ ...@@ -373,7 +374,8 @@
} }
} }
.dropdown-input-field, .default-dropdown-input { .dropdown-input-field,
.default-dropdown-input {
width: 100%; width: 100%;
min-height: 30px; min-height: 30px;
padding: 0 7px; padding: 0 7px;
...@@ -402,7 +404,7 @@ ...@@ -402,7 +404,7 @@
.dropdown-content { .dropdown-content {
max-height: 215px; max-height: 215px;
overflow-y: scroll; overflow-y: auto;
} }
.dropdown-footer { .dropdown-footer {
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
margin: 0; margin: 0;
} }
.flash-notice, .flash-alert { .flash-notice,
.flash-alert {
border-radius: $border-radius-default; border-radius: $border-radius-default;
.container-fluid, .container-fluid,
...@@ -30,7 +31,8 @@ ...@@ -30,7 +31,8 @@
&.flash-container-page { &.flash-container-page {
margin-bottom: 0; margin-bottom: 0;
.flash-notice, .flash-alert { .flash-notice,
.flash-alert {
border-radius: 0; border-radius: 0;
} }
} }
......
...@@ -25,7 +25,9 @@ ...@@ -25,7 +25,9 @@
a { a {
color: $color-light; color: $color-light;
&:hover, &:focus, &:active { &:hover,
&:focus,
&:active {
background: $color-dark; background: $color-dark;
} }
......
...@@ -15,7 +15,8 @@ header { ...@@ -15,7 +15,8 @@ header {
margin: 8px 0; margin: 8px 0;
text-align: center; text-align: center;
.tanuki-logo, img { .tanuki-logo,
img {
height: 36px; height: 36px;
} }
} }
...@@ -54,7 +55,9 @@ header { ...@@ -54,7 +55,9 @@ header {
line-height: 28px; line-height: 28px;
text-align: center; text-align: center;
&:hover, &:focus, &:active { &:hover,
&:focus,
&:active {
background-color: $background-color; background-color: $background-color;
} }
...@@ -125,7 +128,8 @@ header { ...@@ -125,7 +128,8 @@ header {
left: -50%; left: -50%;
} }
svg, img { svg,
img {
height: 36px; height: 36px;
} }
...@@ -222,7 +226,8 @@ header { ...@@ -222,7 +226,8 @@ header {
margin: 0; margin: 0;
float: none !important; float: none !important;
.visible-xs, .visable-sm { .visible-xs,
.visable-sm {
display: table-cell !important; display: table-cell !important;
} }
} }
......
...@@ -76,14 +76,16 @@ ...@@ -76,14 +76,16 @@
/** light list with border-bottom between li **/ /** light list with border-bottom between li **/
ul.bordered-list, ul.unstyled-list { ul.bordered-list,
ul.unstyled-list {
@include basic-list; @include basic-list;
&.top-list { &.top-list {
li:first-child { li:first-child {
padding-top: 0; padding-top: 0;
h4, h5 { h4,
h5 {
margin-top: 0; margin-top: 0;
} }
} }
......
...@@ -79,7 +79,8 @@ ...@@ -79,7 +79,8 @@
padding-left: 15px !important; padding-left: 15px !important;
} }
.nav-links, .nav-links { .nav-links,
.nav-links {
li a { li a {
font-size: 14px; font-size: 14px;
padding: 19px 10px; padding: 19px 10px;
...@@ -99,18 +100,21 @@ ...@@ -99,18 +100,21 @@
@media (max-width: $screen-sm-max) { @media (max-width: $screen-sm-max) {
.issues-filters { .issues-filters {
.milestone-filter, .labels-filter { .milestone-filter,
.labels-filter {
display: none; display: none;
} }
} }
.page-title { .page-title {
.note-created-ago, .new-issue-link { .note-created-ago,
.new-issue-link {
display: none; display: none;
} }
} }
.issue_edited_ago, .note_edited_ago { .issue_edited_ago,
.note_edited_ago {
display: none; display: none;
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
padding: 15px; padding: 15px;
.form-actions { .form-actions {
margin: -$gl-padding+1; margin: -$gl-padding + 1;
margin-top: 15px; margin-top: 15px;
} }
......
...@@ -54,7 +54,9 @@ ...@@ -54,7 +54,9 @@
color: #959494; color: #959494;
border-bottom: 2px solid transparent; border-bottom: 2px solid transparent;
&:hover, &:active, &:focus { &:hover,
&:active,
&:focus {
text-decoration: none; text-decoration: none;
outline: none; outline: none;
} }
...@@ -211,7 +213,11 @@ ...@@ -211,7 +213,11 @@
padding-bottom: 0; padding-bottom: 0;
width: 100%; width: 100%;
.btn, form, .dropdown, .dropdown-menu-toggle, .form-control { .btn,
form,
.dropdown,
.dropdown-menu-toggle,
.form-control {
margin: 0 0 10px; margin: 0 0 10px;
display: block; display: block;
width: 100%; width: 100%;
...@@ -245,7 +251,8 @@ ...@@ -245,7 +251,8 @@
} }
&.adjust { &.adjust {
.nav-text, .nav-controls { .nav-text,
.nav-controls {
width: auto; width: auto;
} }
} }
...@@ -309,13 +316,15 @@ ...@@ -309,13 +316,15 @@
padding-top: 10px; padding-top: 10px;
} }
a, i { a,
i {
color: $layout-link-gray; color: $layout-link-gray;
} }
&.active { &.active {
a, i { a,
i {
color: $black; color: $black;
} }
...@@ -328,7 +337,8 @@ ...@@ -328,7 +337,8 @@
} }
&:hover { &:hover {
a, i { a,
i {
color: $black; color: $black;
} }
} }
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
width: 100% !important; width: 100% !important;
} }
.select2-container, .select2-container.select2-drop-above { .select2-container,
.select2-container.select2-drop-above {
.select2-choice { .select2-choice {
background: #fff; background: #fff;
border-color: $input-border; border-color: $input-border;
...@@ -71,7 +72,8 @@ ...@@ -71,7 +72,8 @@
} }
.select2-container-active { .select2-container-active {
.select2-choice, .select2-choices { .select2-choice,
.select2-choices {
box-shadow: none; box-shadow: none;
} }
} }
......
...@@ -185,6 +185,10 @@ header.header-sidebar-pinned { ...@@ -185,6 +185,10 @@ header.header-sidebar-pinned {
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
padding-right: $sidebar_collapsed_width; padding-right: $sidebar_collapsed_width;
.merge-request-tabs-holder.affix {
right: $sidebar_collapsed_width;
}
} }
.sidebar-collapsed-icon { .sidebar-collapsed-icon {
...@@ -207,6 +211,10 @@ header.header-sidebar-pinned { ...@@ -207,6 +211,10 @@ header.header-sidebar-pinned {
@media (min-width: $screen-md-min) { @media (min-width: $screen-md-min) {
padding-right: $gutter_width; padding-right: $gutter_width;
.merge-request-tabs-holder.affix {
right: $gutter_width;
}
} }
&.with-overlay { &.with-overlay {
......
...@@ -23,7 +23,8 @@ table { ...@@ -23,7 +23,8 @@ table {
} }
tr { tr {
td, th { td,
th {
padding: 10px $gl-padding; padding: 10px $gl-padding;
line-height: 20px; line-height: 20px;
vertical-align: middle; vertical-align: middle;
......
...@@ -126,7 +126,8 @@ ...@@ -126,7 +126,8 @@
box-shadow: none; box-shadow: none;
.panel-body { .panel-body {
form, pre { form,
pre {
margin: 0; margin: 0;
} }
......
...@@ -131,12 +131,14 @@ ...@@ -131,12 +131,14 @@
font-weight: inherit; font-weight: inherit;
} }
ul, ol { ul,
ol {
padding: 0; padding: 0;
margin: 3px 0 3px 28px !important; margin: 3px 0 3px 28px !important;
} }
ul:dir(rtl), ol:dir(rtl) { ul:dir(rtl),
ol:dir(rtl) {
margin: 3px 28px 3px 0 !important; margin: 3px 28px 3px 0 !important;
} }
...@@ -144,7 +146,8 @@ ...@@ -144,7 +146,8 @@
line-height: 1.6em; line-height: 1.6em;
} }
a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] { a[href*="/uploads/"],
a[href*="storage.googleapis.com/google-code-attachments/"] {
&:before { &:before {
margin-right: 4px; margin-right: 4px;
...@@ -167,7 +170,12 @@ ...@@ -167,7 +170,12 @@
} }
/* Link to current header. */ /* Link to current header. */
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
position: relative; position: relative;
a.anchor { a.anchor {
...@@ -215,7 +223,12 @@ body { ...@@ -215,7 +223,12 @@ body {
margin: 12px 7px; margin: 12px 7px;
} }
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
color: $gl-title-color; color: $gl-title-color;
font-weight: 600; font-weight: 600;
} }
...@@ -273,7 +286,10 @@ a > code { ...@@ -273,7 +286,10 @@ a > code {
text-decoration: line-through; text-decoration: line-through;
} }
h1, h2, h3, h4 { h1,
h2,
h3,
h4 {
small { small {
color: $gl-gray; color: $gl-gray;
} }
......
/* https://github.com/MozMorris/tomorrow-pygments */ /* https://github.com/MozMorris/tomorrow-pygments */
.code.dark { .code.dark {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: #1d1f21; background-color: #1d1f21;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: rgba(255, 255, 255, 0.3); color: rgba(255, 255, 255, 0.3);
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: #666; border-color: #666;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #1d1f21; background-color: #1d1f21;
color: #c5c8c6; color: #c5c8c6;
} }
...@@ -31,11 +36,13 @@ ...@@ -31,11 +36,13 @@
border-color: darken(#557, 15%); border-color: darken(#557, 15%);
} }
.diff-line-num.new, .line_content.new { .diff-line-num.new,
.line_content.new {
@include diff_background(rgba(51, 255, 51, 0.1), rgba(51, 255, 51, 0.2), #808080); @include diff_background(rgba(51, 255, 51, 0.1), rgba(51, 255, 51, 0.2), #808080);
} }
.diff-line-num.old, .line_content.old { .diff-line-num.old,
.line_content.old {
@include diff_background(rgba(255, 51, 51, 0.2), rgba(255, 51, 51, 0.25), #808080); @include diff_background(rgba(255, 51, 51, 0.2), rgba(255, 51, 51, 0.25), #808080);
} }
......
/* https://github.com/richleland/pygments-css/blob/master/monokai.css */ /* https://github.com/richleland/pygments-css/blob/master/monokai.css */
.code.monokai { .code.monokai {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: #272822; background-color: #272822;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: rgba(255, 255, 255, 0.3); color: rgba(255, 255, 255, 0.3);
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: #555; border-color: #555;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #272822; background-color: #272822;
color: #f8f8f2; color: #f8f8f2;
} }
...@@ -31,11 +36,13 @@ ...@@ -31,11 +36,13 @@
border-color: darken(#49483e, 15%); border-color: darken(#49483e, 15%);
} }
.diff-line-num.new, .line_content.new { .diff-line-num.new,
.line_content.new {
@include diff_background(rgba(166, 226, 46, 0.1), rgba(166, 226, 46, 0.15), #808080); @include diff_background(rgba(166, 226, 46, 0.1), rgba(166, 226, 46, 0.15), #808080);
} }
.diff-line-num.old, .line_content.old { .diff-line-num.old,
.line_content.old {
@include diff_background(rgba(254, 147, 140, 0.15), rgba(254, 147, 140, 0.2), #808080); @include diff_background(rgba(254, 147, 140, 0.15), rgba(254, 147, 140, 0.2), #808080);
} }
......
/* https://gist.github.com/qguv/7936275 */ /* https://gist.github.com/qguv/7936275 */
.code.solarized-dark { .code.solarized-dark {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: #002b36; background-color: #002b36;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: rgba(255, 255, 255, 0.3); color: rgba(255, 255, 255, 0.3);
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: #113b46; border-color: #113b46;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #002b36; background-color: #002b36;
color: #93a1a1; color: #93a1a1;
} }
...@@ -31,11 +36,13 @@ ...@@ -31,11 +36,13 @@
border-color: darken(#174652, 15%); border-color: darken(#174652, 15%);
} }
.diff-line-num.new, .line_content.new { .diff-line-num.new,
.line_content.new {
@include diff_background(rgba(133, 153, 0, 0.15), rgba(133, 153, 0, 0.25), #113b46); @include diff_background(rgba(133, 153, 0, 0.15), rgba(133, 153, 0, 0.25), #113b46);
} }
.diff-line-num.old, .line_content.old { .diff-line-num.old,
.line_content.old {
@include diff_background(rgba(220, 50, 47, 0.3), rgba(220, 50, 47, 0.25), #113b46); @include diff_background(rgba(220, 50, 47, 0.3), rgba(220, 50, 47, 0.25), #113b46);
} }
......
...@@ -7,20 +7,25 @@ ...@@ -7,20 +7,25 @@
.code.solarized-light { .code.solarized-light {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: #fdf6e3; background-color: #fdf6e3;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: $black-transparent; color: $black-transparent;
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: #c5d0d4; border-color: #c5d0d4;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #fdf6e3; background-color: #fdf6e3;
color: #586e75; color: #586e75;
} }
...@@ -37,11 +42,13 @@ ...@@ -37,11 +42,13 @@
border-color: darken(#ddd8c5, 15%); border-color: darken(#ddd8c5, 15%);
} }
.diff-line-num.new, .line_content.new { .diff-line-num.new,
.line_content.new {
@include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.25), #c5d0d4); @include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.25), #c5d0d4);
} }
.diff-line-num.old, .line_content.old { .diff-line-num.old,
.line_content.old {
@include diff_background(rgba(220, 50, 47, 0.2), rgba(220, 50, 47, 0.25), #c5d0d4); @include diff_background(rgba(220, 50, 47, 0.2), rgba(220, 50, 47, 0.25), #c5d0d4);
} }
......
...@@ -7,20 +7,25 @@ ...@@ -7,20 +7,25 @@
.code.white { .code.white {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: $background-color; background-color: $background-color;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: $black-transparent; color: $black-transparent;
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: $table-border-gray; border-color: $table-border-gray;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #fff; background-color: #fff;
color: #333; color: #333;
} }
......
...@@ -56,7 +56,8 @@ ...@@ -56,7 +56,8 @@
padding: 10px; padding: 10px;
text-align: center; text-align: center;
> div, p { > div,
p {
display: inline; display: inline;
margin: 0; margin: 0;
......
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
border-color: $border-color; border-color: $border-color;
} }
th, td { th,
td {
padding: 10px $gl-padding; padding: 10px $gl-padding;
} }
......
...@@ -2,14 +2,16 @@ ...@@ -2,14 +2,16 @@
display: block; display: block;
} }
.commit-author, .commit-committer { .commit-author,
.commit-committer {
display: block; display: block;
color: #999; color: #999;
font-weight: normal; font-weight: normal;
font-style: italic; font-style: italic;
} }
.commit-author strong, .commit-committer strong { .commit-author strong,
.commit-committer strong {
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
......
...@@ -63,7 +63,8 @@ ...@@ -63,7 +63,8 @@
display: inline-block; display: inline-block;
} }
.btn-clipboard, .btn-transparent { .btn-clipboard,
.btn-transparent {
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
} }
...@@ -162,7 +163,8 @@ ...@@ -162,7 +163,8 @@
.branch-commit { .branch-commit {
color: $gl-gray; color: $gl-gray;
.commit-id, .commit-row-message { .commit-id,
.commit-row-message {
color: $gl-gray; color: $gl-gray;
} }
} }
......
...@@ -2,7 +2,12 @@ ...@@ -2,7 +2,12 @@
margin-bottom: 20px; margin-bottom: 20px;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
> h1, h2, h3, h4, h5, h6 { > h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 400; font-weight: 400;
} }
...@@ -10,7 +15,8 @@ ...@@ -10,7 +15,8 @@
margin-bottom: 20px; margin-bottom: 20px;
} }
ul, ol { ul,
ol {
padding-left: 0; padding-left: 0;
} }
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
color: #5c5d5e; color: #5c5d5e;
} }
.issue_created_ago, .author_link { .issue_created_ago,
.author_link {
white-space: nowrap; white-space: nowrap;
} }
} }
......
...@@ -124,7 +124,8 @@ ...@@ -124,7 +124,8 @@
} }
} }
.old_line, .new_line { .old_line,
.new_line {
margin: 0; margin: 0;
padding: 0; padding: 0;
border: none; border: none;
...@@ -281,7 +282,8 @@ ...@@ -281,7 +282,8 @@
position: relative; position: relative;
} }
.frame.added, .frame.deleted { .frame.added,
.frame.deleted {
position: absolute; position: absolute;
display: block; display: block;
top: 0; top: 0;
...@@ -347,7 +349,8 @@ ...@@ -347,7 +349,8 @@
text-align: center; text-align: center;
background: #eee; background: #eee;
ul, li { ul,
li {
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
......
...@@ -91,7 +91,9 @@ ...@@ -91,7 +91,9 @@
} }
} }
.gitignore-selector, .license-selector, .gitlab-ci-yml-selector { .gitignore-selector,
.license-selector,
.gitlab-ci-yml-selector {
.dropdown { .dropdown {
line-height: 21px; line-height: 21px;
} }
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
max-width: 400px; max-width: 400px;
margin: 0 auto; margin: 0 auto;
h1, h2, h3 { h1,
h2,
h3 {
text-align: center; text-align: center;
} }
......
...@@ -43,7 +43,8 @@ ul.related-merge-requests > li { ...@@ -43,7 +43,8 @@ ul.related-merge-requests > li {
} }
} }
.merge-requests-title, .related-branches-title { .merge-requests-title,
.related-branches-title {
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
} }
......
...@@ -41,7 +41,8 @@ ...@@ -41,7 +41,8 @@
font-size: 13px; font-size: 13px;
} }
.login-box, .omniauth-container { .login-box,
.omniauth-container {
box-shadow: 0 0 0 1px $border-color; box-shadow: 0 0 0 1px $border-color;
border-bottom-right-radius: 2px; border-bottom-right-radius: 2px;
border-bottom-left-radius: 2px; border-bottom-left-radius: 2px;
...@@ -53,6 +54,7 @@ ...@@ -53,6 +54,7 @@
margin: 0 0 10px; margin: 0 0 10px;
} }
.login-footer { .login-footer {
margin-top: 10px; margin-top: 10px;
...@@ -142,6 +144,7 @@ ...@@ -142,6 +144,7 @@
&:not(.active) { &:not(.active) {
background-color: $gray-light; background-color: $gray-light;
border-left: 1px solid $border-color;
} }
a { a {
...@@ -169,9 +172,35 @@ ...@@ -169,9 +172,35 @@
} }
} }
// Ldap configurations may need more tabs & the tab labels are user generated (arbitrarily long).
// These styles prevent this from breaking the layout, and only applied when providers are configured.
.new-session-tabs.custom-provider-tabs {
flex-wrap: wrap;
li {
min-width: 85px;
flex-basis: auto;
// This styles tab elements that have wrapped to a second line. We cannot easily predict when this will happen.
// We are making somewhat of an assumption about the configuration here: that users do not have more than
// 3 LDAP servers configured (in addition to standard login) and they are not using especially long names for any
// of them. If either condition is false, this will work as expected. If both are true, there may be a missing border
// above one of the bottom row elements. If you know a better way, please implement it!
&:nth-child(n+5) {
border-top: 1px solid $border-color;
}
}
a {
font-size: 16px;
}
}
.form-control { .form-control {
&:active, &:focus { &:active,
&:focus {
background-color: #fff; background-color: #fff;
} }
} }
...@@ -202,6 +231,7 @@ ...@@ -202,6 +231,7 @@
.login-page { .login-page {
.col-sm-5.pull-right { .col-sm-5.pull-right {
float: none !important; float: none !important;
margin-bottom: 45px;
} }
} }
} }
...@@ -233,7 +263,8 @@ ...@@ -233,7 +263,8 @@
position: relative; position: relative;
} }
.footer-container, hr.footer-fixed { .footer-container,
hr.footer-fixed {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
...@@ -243,6 +274,34 @@ ...@@ -243,6 +274,34 @@
} }
.navless-container { .navless-container {
padding: 65px; // height of footer + bottom padding of email confirmation link padding: 65px 15px; // height of footer + bottom padding of email confirmation link
@media (max-width: $screen-xs-max) {
padding: 0 15px 65px;
}
} }
} }
// For sign in pane only, to improve tab order, the following removes the submit button from
// normal document flow and pins it to the bottom of the form. For context, see !6867 & !6928
.login-box {
.new_user {
position: relative;
padding-bottom: 35px;
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
.forgot-password {
float: none !important;
margin-top: 5px;
}
}
}
.move-submit-down {
position: absolute;
width: 100%;
bottom: 0;
}
}
...@@ -101,7 +101,8 @@ $colors: ( ...@@ -101,7 +101,8 @@ $colors: (
@mixin color-scheme($color) { @mixin color-scheme($color) {
.header.line_content, .diff-line-num { .header.line_content,
.diff-line-num {
&.origin { &.origin {
background-color: map-get($colors, #{$color}_header_origin_neutral); background-color: map-get($colors, #{$color}_header_origin_neutral);
border-color: map-get($colors, #{$color}_header_origin_neutral); border-color: map-get($colors, #{$color}_header_origin_neutral);
......
...@@ -438,11 +438,18 @@ ...@@ -438,11 +438,18 @@
} }
} }
.merge-request-tabs { .merge-request-tabs-holder {
background-color: #fff; background-color: #fff;
&.affix { &.affix {
top: 100px; top: 100px;
left: 0;
z-index: 9; z-index: 9;
transition: right .15s;
}
&:not(.affix) .container-fluid {
padding-left: 0;
padding-right: 0;
} }
} }
...@@ -50,7 +50,8 @@ ...@@ -50,7 +50,8 @@
} }
} }
.issues-sortable-list, .merge_requests-sortable-list { .issues-sortable-list,
.merge_requests-sortable-list {
.issuable-detail { .issuable-detail {
display: block; display: block;
margin-top: 7px; margin-top: 7px;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
.diff-file .diff-content { .diff-file .diff-content {
tr.line_holder:hover > td .line_note_link { tr.line_holder:hover > td .line_note_link {
opacity: 1.0; opacity: 1.0;
filter: alpha(opacity=100); filter: alpha(opacity = 100);
} }
} }
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
display: none; display: none;
} }
.new-note, .note-edit-form { .new-note,
.note-edit-form {
.note-form-actions { .note-form-actions {
margin-top: $gl-padding; margin-top: $gl-padding;
} }
......
...@@ -28,7 +28,8 @@ ul.notes { ...@@ -28,7 +28,8 @@ ul.notes {
} }
} }
.note-created-ago, .note-updated-at { .note-created-ago,
.note-updated-at {
white-space: nowrap; white-space: nowrap;
} }
......
...@@ -248,7 +248,8 @@ ...@@ -248,7 +248,8 @@
font-size: 14px; font-size: 14px;
} }
svg, .fa { svg,
.fa {
margin-right: 0; margin-right: 0;
} }
} }
...@@ -369,10 +370,6 @@ ...@@ -369,10 +370,6 @@
&:hover { &:hover {
background-color: $gray-lighter; background-color: $gray-lighter;
.dropdown-menu-toggle {
background-color: transparent;
}
} }
&.playable { &.playable {
...@@ -402,6 +399,15 @@ ...@@ -402,6 +399,15 @@
} }
} }
.tooltip {
white-space: nowrap;
.tooltip-inner {
overflow: hidden;
text-overflow: ellipsis;
}
}
.ci-status-text { .ci-status-text {
width: 135px; width: 135px;
white-space: nowrap; white-space: nowrap;
...@@ -419,6 +425,7 @@ ...@@ -419,6 +425,7 @@
} }
.dropdown-menu-toggle { .dropdown-menu-toggle {
background-color: transparent;
border: none; border: none;
width: auto; width: auto;
padding: 0; padding: 0;
...@@ -523,7 +530,8 @@ ...@@ -523,7 +530,8 @@
// Connect each build (except for first) with curved lines // Connect each build (except for first) with curved lines
&:not(:first-child) { &:not(:first-child) {
&::after, &::before { &::after,
&::before {
content: ''; content: '';
top: -49px; top: -49px;
position: absolute; position: absolute;
...@@ -549,7 +557,8 @@ ...@@ -549,7 +557,8 @@
// Connect second build to first build with smaller curved line // Connect second build to first build with smaller curved line
&:nth-child(2) { &:nth-child(2) {
&::after, &::before { &::after,
&::before {
height: 29px; height: 29px;
top: -9px; top: -9px;
} }
...@@ -564,7 +573,8 @@ ...@@ -564,7 +573,8 @@
.build { .build {
// Remove right connecting horizontal line from first build in last stage // Remove right connecting horizontal line from first build in last stage
&:first-child { &:first-child {
&::after, &::before { &::after,
&::before {
border: none; border: none;
} }
} }
......
...@@ -253,7 +253,8 @@ ...@@ -253,7 +253,8 @@
} }
table.u2f-registrations { table.u2f-registrations {
th:not(:last-child), td:not(:last-child) { th:not(:last-child),
td:not(:last-child) {
border-right: solid 1px transparent; border-right: solid 1px transparent;
} }
} }
\ No newline at end of file
...@@ -6,16 +6,26 @@ ...@@ -6,16 +6,26 @@
} }
} }
.no-ssh-key-message, .project-limit-message { .no-ssh-key-message,
.project-limit-message {
background-color: #f28d35; background-color: #f28d35;
margin-bottom: 0; margin-bottom: 0;
} }
.new_project, .new_project,
.edit-project { .edit-project {
fieldset { fieldset {
&.features .control-label {
font-weight: normal; &.features {
.label-light {
margin-bottom: 0;
}
.help-block {
margin-top: 0;
}
} }
.form-group { .form-group {
...@@ -40,6 +50,7 @@ ...@@ -40,6 +50,7 @@
} }
.input-group > div { .input-group > div {
&:last-child { &:last-child {
padding-right: 0; padding-right: 0;
} }
...@@ -47,6 +58,7 @@ ...@@ -47,6 +58,7 @@
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
.input-group > div { .input-group > div {
margin-bottom: 14px; margin-bottom: 14px;
&:last-child { &:last-child {
...@@ -60,6 +72,7 @@ ...@@ -60,6 +72,7 @@
} }
.input-group-addon { .input-group-addon {
&.static-namespace { &.static-namespace {
height: 35px; height: 35px;
border-radius: 3px; border-radius: 3px;
...@@ -373,7 +386,8 @@ a.deploy-project-label { ...@@ -373,7 +386,8 @@ a.deploy-project-label {
text-align: center; text-align: center;
width: 169px; width: 169px;
&:hover, &.forked { &:hover,
&.forked {
background-color: $row-hover; background-color: $row-hover;
border-color: $row-hover-border; border-color: $row-hover-border;
} }
...@@ -722,7 +736,8 @@ pre.light-well { ...@@ -722,7 +736,8 @@ pre.light-well {
.table-bordered { .table-bordered {
border-radius: 1px; border-radius: 1px;
th:not(:last-child), td:not(:last-child) { th:not(:last-child),
td:not(:last-child) {
border-right: solid 1px transparent; border-right: solid 1px transparent;
} }
} }
...@@ -745,7 +760,8 @@ pre.light-well { ...@@ -745,7 +760,8 @@ pre.light-well {
} }
} }
.project-refs-form .dropdown-menu, .dropdown-menu-projects { .project-refs-form .dropdown-menu,
.dropdown-menu-projects {
width: 300px; width: 300px;
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
......
...@@ -65,7 +65,8 @@ ...@@ -65,7 +65,8 @@
.search-input-wrap { .search-input-wrap {
width: 100%; width: 100%;
.search-icon, .clear-icon { .search-icon,
.clear-icon {
position: absolute; position: absolute;
right: 5px; right: 5px;
top: 0; top: 0;
...@@ -185,7 +186,8 @@ ...@@ -185,7 +186,8 @@
padding-right: $gl-padding + 15px; padding-right: $gl-padding + 15px;
} }
.btn-search, .btn-new { .btn-search,
.btn-new {
width: 100%; width: 100%;
margin-top: 5px; margin-top: 5px;
......
...@@ -23,7 +23,8 @@ ...@@ -23,7 +23,8 @@
border-bottom: 1px solid $table-border-gray; border-bottom: 1px solid $table-border-gray;
border-top: 1px solid $table-border-gray; border-top: 1px solid $table-border-gray;
td, th { td,
th {
line-height: 21px; line-height: 21px;
} }
...@@ -74,7 +75,8 @@ ...@@ -74,7 +75,8 @@
max-width: 320px; max-width: 320px;
vertical-align: middle; vertical-align: middle;
i, a { i,
a {
color: $gl-dark-link-color; color: $gl-dark-link-color;
} }
......
.wiki h1, .wiki h2, .wiki h3, .wiki h4, .wiki h5, .wiki h6 {margin-top: 17px; } .wiki h1,
.wiki h1 {font-size: 30px;} .wiki h2,
.wiki h2 {font-size: 22px;} .wiki h3,
.wiki h3 {font-size: 18px; font-weight: bold; } .wiki h4,
.wiki h5,
.wiki h6 {
margin-top: 17px;
}
.wiki h1 {
font-size: 30px;
}
.wiki h2 {
font-size: 22px;
}
.wiki h3 {
font-size: 18px;
font-weight: bold;
}
header, header,
nav, nav,
......
...@@ -21,6 +21,10 @@ class Groups::GroupMembersController < Groups::ApplicationController ...@@ -21,6 +21,10 @@ class Groups::GroupMembersController < Groups::ApplicationController
end end
def create def create
if params[:user_ids].blank?
return redirect_to(group_group_members_path(@group), alert: 'No users specified.')
end
@group.add_users( @group.add_users(
params[:user_ids].split(','), params[:user_ids].split(','),
params[:access_level], params[:access_level],
......
...@@ -2,8 +2,8 @@ class Import::GitlabProjectsController < Import::BaseController ...@@ -2,8 +2,8 @@ class Import::GitlabProjectsController < Import::BaseController
before_action :verify_gitlab_project_import_enabled before_action :verify_gitlab_project_import_enabled
def new def new
@namespace_id = project_params[:namespace_id] @namespace = Namespace.find(project_params[:namespace_id])
@namespace_name = Namespace.find(project_params[:namespace_id]).name return render_404 unless current_user.can?(:create_projects, @namespace)
@path = project_params[:path] @path = project_params[:path]
end end
......
...@@ -13,7 +13,7 @@ class Projects::CommitsController < Projects::ApplicationController ...@@ -13,7 +13,7 @@ class Projects::CommitsController < Projects::ApplicationController
@commits = @commits =
if search.present? if search.present?
@repository.find_commits_by_message(search, @ref, @path, @limit, @offset).compact @repository.find_commits_by_message(search, @ref, @path, @limit, @offset)
else else
@repository.commits(@ref, path: @path, limit: @limit, offset: @offset) @repository.commits(@ref, path: @path, limit: @limit, offset: @offset)
end end
......
...@@ -398,7 +398,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -398,7 +398,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
status ||= "preparing" status ||= "preparing"
else else
ci_service = @merge_request.source_project.ci_service ci_service = @merge_request.source_project.try(:ci_service)
status = ci_service.commit_status(merge_request.diff_head_sha, merge_request.source_branch) if ci_service status = ci_service.commit_status(merge_request.diff_head_sha, merge_request.source_branch) if ci_service
if ci_service.respond_to?(:commit_coverage) if ci_service.respond_to?(:commit_coverage)
...@@ -554,7 +554,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -554,7 +554,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def define_pipelines_vars def define_pipelines_vars
@pipelines = @merge_request.all_pipelines @pipelines = @merge_request.all_pipelines
if @pipelines.any? if @pipelines.present?
@pipeline = @pipelines.first @pipeline = @pipelines.first
@statuses = @pipeline.statuses.relevant @statuses = @pipeline.statuses.relevant
end end
......
...@@ -25,6 +25,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -25,6 +25,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController
end end
def create def create
if params[:user_ids].blank?
return redirect_to(namespace_project_project_members_path(@project.namespace, @project), alert: 'No users or groups specified.')
end
@project.team.add_users( @project.team.add_users(
params[:user_ids].split(','), params[:user_ids].split(','),
params[:access_level], params[:access_level],
...@@ -32,22 +36,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -32,22 +36,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
current_user: current_user current_user: current_user
) )
if params[:group_ids].present? redirect_to namespace_project_project_members_path(@project.namespace, @project), notice: 'Users were successfully added.'
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 end
def update def update
......
...@@ -35,8 +35,10 @@ class LabelsFinder < UnionFinder ...@@ -35,8 +35,10 @@ class LabelsFinder < UnionFinder
end end
def with_title(items) def with_title(items)
items = items.where(title: title) if title return items if title.nil?
items return items.none if title.blank?
items.where(title: title)
end end
def group_id def group_id
...@@ -48,11 +50,11 @@ class LabelsFinder < UnionFinder ...@@ -48,11 +50,11 @@ class LabelsFinder < UnionFinder
end end
def projects_ids def projects_ids
params[:project_ids].presence params[:project_ids]
end end
def title def title
params[:title].presence || params[:name].presence params[:title] || params[:name]
end end
def project def project
......
...@@ -5,7 +5,7 @@ module BoardsHelper ...@@ -5,7 +5,7 @@ module BoardsHelper
{ {
endpoint: namespace_project_boards_path(@project.namespace, @project), endpoint: namespace_project_boards_path(@project.namespace, @project),
board_id: board.id, board_id: board.id,
disabled: !can?(current_user, :admin_list, @project), disabled: "#{!can?(current_user, :admin_list, @project)}",
issue_link_base: namespace_project_issues_path(@project.namespace, @project) issue_link_base: namespace_project_issues_path(@project.namespace, @project)
} }
end end
......
...@@ -86,11 +86,15 @@ module MergeRequestsHelper ...@@ -86,11 +86,15 @@ module MergeRequestsHelper
end end
def source_branch_with_namespace(merge_request) def source_branch_with_namespace(merge_request)
branch = link_to(merge_request.source_branch, namespace_project_commits_path(merge_request.source_project.namespace, merge_request.source_project, merge_request.source_branch)) namespace = merge_request.source_project_namespace
branch = merge_request.source_branch
if merge_request.source_branch_exists?
namespace = link_to(namespace, project_path(merge_request.source_project))
branch = link_to(branch, namespace_project_commits_path(merge_request.source_project.namespace, merge_request.source_project, merge_request.source_branch))
end
if merge_request.for_fork? if merge_request.for_fork?
namespace = link_to(merge_request.source_project_namespace,
project_path(merge_request.source_project))
namespace + ":" + branch namespace + ":" + branch
else else
branch branch
......
...@@ -3,8 +3,8 @@ module Ci ...@@ -3,8 +3,8 @@ module Ci
include TokenAuthenticatable include TokenAuthenticatable
include AfterCommitQueue include AfterCommitQueue
belongs_to :runner, class_name: 'Ci::Runner' belongs_to :runner
belongs_to :trigger_request, class_name: 'Ci::TriggerRequest' belongs_to :trigger_request
belongs_to :erased_by, class_name: 'User' belongs_to :erased_by, class_name: 'User'
serialize :options serialize :options
......
...@@ -7,12 +7,12 @@ module Ci ...@@ -7,12 +7,12 @@ module Ci
self.table_name = 'ci_commits' self.table_name = 'ci_commits'
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
belongs_to :user belongs_to :user
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build', foreign_key: :commit_id has_many :builds, foreign_key: :commit_id
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id
validates_presence_of :sha, unless: :importing? validates_presence_of :sha, unless: :importing?
validates_presence_of :ref, unless: :importing? validates_presence_of :ref, unless: :importing?
...@@ -59,9 +59,6 @@ module Ci ...@@ -59,9 +59,6 @@ module Ci
before_transition any => [:success, :failed, :canceled] do |pipeline| before_transition any => [:success, :failed, :canceled] do |pipeline|
pipeline.finished_at = Time.now pipeline.finished_at = Time.now
end
before_transition do |pipeline|
pipeline.update_duration pipeline.update_duration
end end
......
...@@ -6,9 +6,9 @@ module Ci ...@@ -6,9 +6,9 @@ module Ci
AVAILABLE_SCOPES = %w[specific shared active paused online] AVAILABLE_SCOPES = %w[specific shared active paused online]
FORM_EDITABLE = %i[description tag_list active run_untagged locked] FORM_EDITABLE = %i[description tag_list active run_untagged locked]
has_many :builds, class_name: 'Ci::Build' has_many :builds
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject' has_many :runner_projects, dependent: :destroy
has_many :projects, through: :runner_projects, class_name: '::Project', foreign_key: :gl_project_id has_many :projects, through: :runner_projects, foreign_key: :gl_project_id
has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build' has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build'
......
...@@ -2,8 +2,8 @@ module Ci ...@@ -2,8 +2,8 @@ module Ci
class RunnerProject < ActiveRecord::Base class RunnerProject < ActiveRecord::Base
extend Ci::Model extend Ci::Model
belongs_to :runner, class_name: 'Ci::Runner' belongs_to :runner
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
validates_uniqueness_of :runner_id, scope: :gl_project_id validates_uniqueness_of :runner_id, scope: :gl_project_id
end end
......
...@@ -4,8 +4,8 @@ module Ci ...@@ -4,8 +4,8 @@ module Ci
acts_as_paranoid acts_as_paranoid
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest' has_many :trigger_requests, dependent: :destroy
validates_presence_of :token validates_presence_of :token
validates_uniqueness_of :token validates_uniqueness_of :token
......
...@@ -2,9 +2,9 @@ module Ci ...@@ -2,9 +2,9 @@ module Ci
class TriggerRequest < ActiveRecord::Base class TriggerRequest < ActiveRecord::Base
extend Ci::Model extend Ci::Model
belongs_to :trigger, class_name: 'Ci::Trigger' belongs_to :trigger
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id belongs_to :pipeline, foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build' has_many :builds
serialize :variables serialize :variables
......
...@@ -2,7 +2,7 @@ module Ci ...@@ -2,7 +2,7 @@ module Ci
class Variable < ActiveRecord::Base class Variable < ActiveRecord::Base
extend Ci::Model extend Ci::Model
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
validates_uniqueness_of :key, scope: :gl_project_id validates_uniqueness_of :key, scope: :gl_project_id
validates :key, validates :key,
......
...@@ -5,7 +5,7 @@ class CommitStatus < ActiveRecord::Base ...@@ -5,7 +5,7 @@ class CommitStatus < ActiveRecord::Base
self.table_name = 'ci_builds' self.table_name = 'ci_builds'
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
belongs_to :user belongs_to :user
......
module ProtectedBranchAccess module ProtectedBranchAccess
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do
scope :master, -> { where(access_level: Gitlab::Access::MASTER) }
scope :developer, -> { where(access_level: Gitlab::Access::DEVELOPER) }
end
def humanize def humanize
self.class.human_access_levels[self.access_level] self.class.human_access_levels[self.access_level]
end end
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment