Commit 2436631d authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'master' into refactor/ci-config-add-logical-validation

* master: (414 commits)
  Remove suggested colors hover underline
  Fix markdown anchor icon interaction
  Fix expiration date picker after update
  Refactored code to rely less on IDs that could change
  Move CHANGELOG entry for !5858 from 8.11 to 8.12
  Hides merge request section in edit project when disabled
  Fix a typo
  Change minimum Unicorns required to two
  Update memory requirements
  Added `.term-bold` declaration.
  Change the inline code to codeblocks for the new features doc guideline
  Fix GitLab import button
  Rename behaviour to behavior in bug issue template for consistency
  Convert datetime coffeescript spec to ES6
  Align add button on repository view
  Update CHANGELOG with 8.11.4 entries.
  removed null return - renamed 'placeTop' to 'placeProfileAvatarsToTop'
  Refactor Ci::Build#raw_trace
  Move CHANGELOG entry to a proper version
  Change widths of content in MR pipeline tab
  ...

Conflicts:
	lib/gitlab/ci/config/node/jobs.rb
parents b3cd41b4 2aaab34b
### Summary
(Summarize the bug encountered concisely)
### Steps to reproduce
(How one can reproduce the issue - this is very important)
### Expected behavior
(What you should see instead)
### Actual behavior
(What actually happens)
### Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.)
### Output of checks
#### Results of GitLab application Check
(For installations with omnibus-gitlab package run and paste the output of:
`sudo gitlab-rake gitlab:check SANITIZE=true`)
(For installations from source run and paste the output of:
`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`)
(we will only investigate if the tests are passing)
#### Results of GitLab environment info
(For installations with omnibus-gitlab package run and paste the output of:
`sudo gitlab-rake gitlab:env:info`)
(For installations from source run and paste the output of:
`sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
### Possible fixes
(If you can, link to the line of code that might be responsible for the problem)
### Description
(Include problem, use cases, benefits, and/or goals)
### Proposal
### Links / references
See the general Documentation guidelines http://docs.gitlab.com/ce/development/doc_styleguide.html.
## What does this MR do?
(briefly describe what this MR is about)
## Moving docs to a new location?
See the guidelines: http://docs.gitlab.com/ce/development/doc_styleguide.html#changing-document-location
- [ ] Make sure the old link is not removed and has its contents replaced with a link to the new location.
- [ ] Make sure internal links pointing to the document in question are not broken.
- [ ] Search and replace any links referring to old docs in GitLab Rails app, specifically under the `app/views/` directory.
- [ ] If working on CE, submit an MR to EE with the changes as well.
...@@ -5,8 +5,8 @@ require: ...@@ -5,8 +5,8 @@ require:
inherit_from: .rubocop_todo.yml inherit_from: .rubocop_todo.yml
AllCops: AllCops:
TargetRubyVersion: 2.1 TargetRubyVersion: 2.3
# Cop names are not displayed 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.
DisplayCopNames: true DisplayCopNames: true
...@@ -192,6 +192,9 @@ Style/FlipFlop: ...@@ -192,6 +192,9 @@ Style/FlipFlop:
Style/For: Style/For:
Enabled: true Enabled: true
# Checks if there is a magic comment to enforce string literals
Style/FrozenStringLiteralComment:
Enabled: false
# Do not introduce global variables. # Do not introduce global variables.
Style/GlobalVars: Style/GlobalVars:
Enabled: true Enabled: true
......
This diff is collapsed.
...@@ -129,7 +129,7 @@ request that potentially fixes it. ...@@ -129,7 +129,7 @@ request that potentially fixes it.
### Feature proposals ### Feature proposals
To create a feature proposal for CE and CI, open an issue on the To create a feature proposal for CE, open an issue on the
[issue tracker of CE][ce-tracker]. [issue tracker of CE][ce-tracker].
For feature proposals for EE, open an issue on the For feature proposals for EE, open an issue on the
...@@ -144,16 +144,7 @@ code snippet right after your description in a new line: `~"feature proposal"`. ...@@ -144,16 +144,7 @@ code snippet right after your description in a new line: `~"feature proposal"`.
Please keep feature proposals as small and simple as possible, complex ones Please keep feature proposals as small and simple as possible, complex ones
might be edited to make them small and simple. might be edited to make them small and simple.
You are encouraged to use the template below for feature proposals. Please submit Feature Proposals using the ['Feature Proposal' issue template](.gitlab/issue_templates/Feature Proposal.md) provided on the issue tracker.
```
## Description
Include problem, use cases, benefits, and/or goals
## Proposal
## Links / references
```
For changes in the interface, it can be helpful to create a mockup first. For changes in the interface, it can be helpful to create a mockup first.
If you want to create something yourself, consider opening an issue first to If you want to create something yourself, consider opening an issue first to
...@@ -166,55 +157,11 @@ submitting your own, there's a good chance somebody else had the same issue or ...@@ -166,55 +157,11 @@ submitting your own, there's a good chance somebody else had the same issue or
feature proposal. Show your support with an award emoji and/or join the feature proposal. Show your support with an award emoji and/or join the
discussion. discussion.
Please submit bugs using the following template in the issue description area. Please submit bugs using the ['Bug' issue template](.gitlab/issue_templates/Bug.md) provided on the issue tracker.
The text in the parenthesis is there to help you with what to include. Omit it The text in the parenthesis is there to help you with what to include. Omit it
when submitting the actual issue. You can copy-paste it and then edit as you when submitting the actual issue. You can copy-paste it and then edit as you
see fit. see fit.
```
## Summary
(Summarize your issue in one sentence - what goes wrong, what did you expect to happen)
## Steps to reproduce
(How one can reproduce the issue - this is very important)
## Expected behavior
(What you should see instead)
## Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.)
## Output of checks
### Results of GitLab Application Check
(For installations with omnibus-gitlab package run and paste the output of:
sudo gitlab-rake gitlab:check SANITIZE=true)
(For installations from source run and paste the output of:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true)
(we will only investigate if the tests are passing)
### Results of GitLab Environment Info
(For installations with omnibus-gitlab package run and paste the output of:
sudo gitlab-rake gitlab:env:info)
(For installations from source run and paste the output of:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production)
## Possible fixes
(If you can, link to the line of code that might be responsible for the problem)
```
### Issue weight ### Issue weight
Issue weight allows us to get an idea of the amount of work required to solve Issue weight allows us to get an idea of the amount of work required to solve
...@@ -340,6 +287,8 @@ request is as follows: ...@@ -340,6 +287,8 @@ request is as follows:
migrations on a fresh database before the MR is reviewed. If the review leads migrations on a fresh database before the MR is reviewed. If the review leads
to large changes in the MR, do this again once the review is complete. to large changes in the MR, do this again once the review is complete.
1. For more complex migrations, write tests. 1. For more complex migrations, write tests.
1. Merge requests **must** adhere to the [merge request performance
guidelines](doc/development/merge_request_performance_guidelines.md).
The **official merge window** is in the beginning of the month from the 1st to The **official merge window** is in the beginning of the month from the 1st to
the 7th day of the month. This is the best time to submit an MR and get the 7th day of the month. This is the best time to submit an MR and get
......
...@@ -53,7 +53,7 @@ gem 'browser', '~> 2.2' ...@@ -53,7 +53,7 @@ gem 'browser', '~> 2.2'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem 'gitlab_git', '~> 10.4.7' gem 'gitlab_git', '~> 10.5'
# LDAP Auth # LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes # GitLab fork with several improvements to original library. For full list of changes
...@@ -97,9 +97,6 @@ gem 'fog-rackspace', '~> 0.1.1' ...@@ -97,9 +97,6 @@ gem 'fog-rackspace', '~> 0.1.1'
# for aws storage # for aws storage
gem 'unf', '~> 0.1.4' gem 'unf', '~> 0.1.4'
# Authorization
gem 'six', '~> 0.2.0'
# Seed data # Seed data
gem 'seed-fu', '~> 2.3.5' gem 'seed-fu', '~> 2.3.5'
...@@ -349,5 +346,5 @@ gem 'paranoia', '~> 2.0' ...@@ -349,5 +346,5 @@ gem 'paranoia', '~> 2.0'
gem 'health_check', '~> 2.1.0' gem 'health_check', '~> 2.1.0'
# System information # System information
gem 'vmstat', '~> 2.1.1' gem 'vmstat', '~> 2.2'
gem 'sys-filesystem', '~> 1.1.6' gem 'sys-filesystem', '~> 1.1.6'
...@@ -279,7 +279,7 @@ GEM ...@@ -279,7 +279,7 @@ GEM
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
mime-types (>= 1.16, < 3) mime-types (>= 1.16, < 3)
posix-spawn (~> 0.3) posix-spawn (~> 0.3)
gitlab_git (10.4.7) gitlab_git (10.5.0)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.3)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
...@@ -683,7 +683,6 @@ GEM ...@@ -683,7 +683,6 @@ GEM
rack (~> 1.5) rack (~> 1.5)
rack-protection (~> 1.4) rack-protection (~> 1.4)
tilt (>= 1.3, < 3) tilt (>= 1.3, < 3)
six (0.2.0)
slack-notifier (1.2.1) slack-notifier (1.2.1)
slop (3.6.0) slop (3.6.0)
spinach (0.8.10) spinach (0.8.10)
...@@ -772,7 +771,7 @@ GEM ...@@ -772,7 +771,7 @@ GEM
coercible (~> 1.0) coercible (~> 1.0)
descendants_tracker (~> 0.0, >= 0.0.3) descendants_tracker (~> 0.0, >= 0.0.3)
equalizer (~> 0.0, >= 0.0.9) equalizer (~> 0.0, >= 0.0.9)
vmstat (2.1.1) vmstat (2.2.0)
warden (1.2.6) warden (1.2.6)
rack (>= 1.0) rack (>= 1.0)
web-console (2.3.0) web-console (2.3.0)
...@@ -859,7 +858,7 @@ DEPENDENCIES ...@@ -859,7 +858,7 @@ DEPENDENCIES
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
github-markup (~> 1.4) github-markup (~> 1.4)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab_git (~> 10.4.7) gitlab_git (~> 10.5)
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1) gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.2) gollum-lib (~> 4.2)
...@@ -954,7 +953,6 @@ DEPENDENCIES ...@@ -954,7 +953,6 @@ DEPENDENCIES
sidekiq-cron (~> 0.4.0) sidekiq-cron (~> 0.4.0)
simplecov (= 0.12.0) simplecov (= 0.12.0)
sinatra (~> 1.4.4) sinatra (~> 1.4.4)
six (~> 0.2.0)
slack-notifier (~> 1.2.0) slack-notifier (~> 1.2.0)
spinach-rails (~> 0.2.1) spinach-rails (~> 0.2.1)
spinach-rerun-reporter (~> 0.0.2) spinach-rerun-reporter (~> 0.0.2)
...@@ -980,7 +978,7 @@ DEPENDENCIES ...@@ -980,7 +978,7 @@ DEPENDENCIES
unicorn-worker-killer (~> 0.4.2) unicorn-worker-killer (~> 0.4.2)
version_sorter (~> 2.1.0) version_sorter (~> 2.1.0)
virtus (~> 1.0.1) virtus (~> 1.0.1)
vmstat (~> 2.1.1) vmstat (~> 2.2)
web-console (~> 2.0) web-console (~> 2.0)
webmock (~> 1.21.0) webmock (~> 1.21.0)
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
......
...@@ -50,7 +50,7 @@ etc.). ...@@ -50,7 +50,7 @@ etc.).
The most important thing is making sure valid issues receive feedback from the The most important thing is making sure valid issues receive feedback from the
development team. Therefore the priority is mentioning developers that can help development team. Therefore the priority is mentioning developers that can help
on those issue. Please select someone with relevant experience from on those issues. Please select someone with relevant experience from
[GitLab core team][core-team]. If there is nobody mentioned with that expertise [GitLab core team][core-team]. If there is nobody mentioned with that expertise
look in the commit history for the affected files to find someone. Avoid look in the commit history for the affected files to find someone. Avoid
mentioning the lead developer, this is the person that is least likely to give a mentioning the lead developer, this is the person that is least likely to give a
......
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#333" fill-rule="evenodd" d="M9.683 6.676l-.047-.048C8.27 5.26 6.07 5.243 4.726 6.588l-2.29 2.29c-1.344 1.344-1.328 3.544.04 4.91 1.366 1.368 3.564 1.385 4.908.04l1.753-1.752c-.695.074-1.457-.078-2.176-.444L5.934 12.66c-.634.634-1.67.625-2.312-.017-.642-.643-.65-1.677-.017-2.312L6.035 7.9c.634-.634 1.67-.625 2.312.017.024.024.048.05.07.075l.003-.002c.36.36.943.366 1.3.01.355-.356.35-.938-.01-1.3l-.027-.024zM6.58 9.586l.048.05c1.367 1.366 3.565 1.384 4.91.04l2.29-2.292c1.344-1.343 1.328-3.542-.04-4.91-1.366-1.366-3.564-1.384-4.908-.04L7.127 4.187c.695-.074 1.457.078 2.176.444l1.028-1.027c.635-.634 1.67-.624 2.313.017.643.644.652 1.678.018 2.312l-2.43 2.432c-.635.634-1.67.624-2.313-.018-.024-.024-.048-.05-.07-.075l-.003.004c-.36-.362-.943-.367-1.3-.01-.355.355-.35.937.01 1.3.01.007.018.015.027.023z"/></svg>
\ No newline at end of file
window.gl = window.gl || {};
((global) => { ((global) => {
const MAX_MESSAGE_LENGTH = 500; const MAX_MESSAGE_LENGTH = 500;
const MESSAGE_CELL_SELECTOR = '.abuse-reports .message'; const MESSAGE_CELL_SELECTOR = '.abuse-reports .message';
...@@ -36,4 +35,4 @@ window.gl = window.gl || {}; ...@@ -36,4 +35,4 @@ window.gl = window.gl || {};
} }
global.AbuseReports = AbuseReports; global.AbuseReports = AbuseReports;
})(window.gl); })(window.gl || (window.gl = {}));
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
} }
Activities.prototype.updateTooltips = function() { Activities.prototype.updateTooltips = function() {
return gl.utils.localTimeAgo($('.js-timeago', '#activity')); return gl.utils.localTimeAgo($('.js-timeago', '.content_list'));
}; };
Activities.prototype.reloadActivities = function() { Activities.prototype.reloadActivities = function() {
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
event_filters = $.cookie("event_filter"); event_filters = $.cookie("event_filter");
filter = sender.attr("id").split("_")[0]; filter = sender.attr("id").split("_")[0];
$.cookie("event_filter", (event_filters !== filter ? filter : ""), { $.cookie("event_filter", (event_filters !== filter ? filter : ""), {
path: '/' path: gon.relative_url_root || '/'
}); });
if (event_filters !== filter) { if (event_filters !== filter) {
return sender.closest('li').toggleClass("active"); return sender.closest('li').toggleClass("active");
......
...@@ -288,7 +288,7 @@ ...@@ -288,7 +288,7 @@
new Aside(); new Aside();
if ($window.width() < 1024 && $.cookie('pin_nav') === 'true') { if ($window.width() < 1024 && $.cookie('pin_nav') === 'true') {
$.cookie('pin_nav', 'false', { $.cookie('pin_nav', 'false', {
path: '/', path: gon.relative_url_root || '/',
expires: 365 * 10 expires: 365 * 10
}); });
$('.page-with-sidebar').toggleClass('page-sidebar-collapsed page-sidebar-expanded').removeClass('page-sidebar-pinned'); $('.page-with-sidebar').toggleClass('page-sidebar-collapsed page-sidebar-expanded').removeClass('page-sidebar-pinned');
...@@ -313,7 +313,7 @@ ...@@ -313,7 +313,7 @@
$topNav.removeClass('header-pinned-nav').toggleClass('header-collapsed header-expanded'); $topNav.removeClass('header-pinned-nav').toggleClass('header-collapsed header-expanded');
} }
$.cookie('pin_nav', doPinNav, { $.cookie('pin_nav', doPinNav, {
path: '/', path: gon.relative_url_root || '/',
expires: 365 * 10 expires: 365 * 10
}); });
if ($.cookie('pin_nav') === 'true' || doPinNav) { if ($.cookie('pin_nav') === 'true' || doPinNav) {
......
...@@ -320,6 +320,7 @@ ...@@ -320,6 +320,7 @@
frequentlyUsedEmojis = this.getFrequentlyUsedEmojis(); frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();
frequentlyUsedEmojis.push(emoji); frequentlyUsedEmojis.push(emoji);
return $.cookie('frequently_used_emojis', frequentlyUsedEmojis.join(','), { return $.cookie('frequently_used_emojis', frequentlyUsedEmojis.join(','), {
path: gon.relative_url_root || '/',
expires: 365 expires: 365
}); });
}; };
......
(function() { (function(w) {
$(function() { $(function() {
return $("body").on("click", ".js-toggle-button", function(e) { $('body').on('click', '.js-toggle-button', function(e) {
$(this).find('i').toggleClass('fa fa-chevron-down').toggleClass('fa fa-chevron-up'); e.preventDefault();
$(this).closest(".js-toggle-container").find(".js-toggle-content").toggle(); $(this)
return e.preventDefault(); .find('.fa')
.toggleClass('fa-chevron-down fa-chevron-up')
.end()
.closest('.js-toggle-container')
.find('.js-toggle-content')
.toggle()
;
}); });
});
}).call(this); // If we're accessing a permalink, ensure it is not inside a
// closed js-toggle-container!
var hash = w.gl.utils.getLocationHash();
var anchor = hash && document.getElementById(hash);
var container = anchor && $(anchor).closest('.js-toggle-container');
if (container && container.find('.js-toggle-content').is(':hidden')) {
container.find('.js-toggle-button').trigger('click');
anchor.scrollIntoView();
}
});
})(window);
...@@ -54,4 +54,11 @@ $(() => { ...@@ -54,4 +54,11 @@ $(() => {
}); });
} }
}); });
gl.IssueBoardsSearch = new Vue({
el: '#js-boards-seach',
data: {
filters: Store.state.filters
}
});
}); });
...@@ -21,15 +21,10 @@ ...@@ -21,15 +21,10 @@
}, },
data () { data () {
return { return {
query: '',
filters: Store.state.filters filters: Store.state.filters
}; };
}, },
watch: { watch: {
query () {
this.list.filters = this.getFilterData();
this.list.getIssues(true);
},
filters: { filters: {
handler () { handler () {
this.list.page = 1; this.list.page = 1;
...@@ -38,16 +33,6 @@ ...@@ -38,16 +33,6 @@
deep: true deep: true
} }
}, },
methods: {
getFilterData () {
const filters = this.filters;
let queryData = { search: this.query };
Object.keys(filters).forEach((key) => { queryData[key] = filters[key]; });
return queryData;
}
},
ready () { ready () {
const options = gl.issueBoards.getBoardSortableDefaultOptions({ const options = gl.issueBoards.getBoardSortableDefaultOptions({
disabled: this.disabled, disabled: this.disabled,
......
...@@ -20,7 +20,8 @@ ...@@ -20,7 +20,8 @@
data () { data () {
return { return {
scrollOffset: 250, scrollOffset: 250,
filters: Store.state.filters filters: Store.state.filters,
showCount: false
}; };
}, },
watch: { watch: {
...@@ -30,6 +31,15 @@ ...@@ -30,6 +31,15 @@
this.$els.list.scrollTop = 0; this.$els.list.scrollTop = 0;
}, },
deep: true deep: true
},
issues () {
this.$nextTick(() => {
if (this.scrollHeight() > this.listHeight()) {
this.showCount = true;
} else {
this.showCount = false;
}
});
} }
}, },
methods: { methods: {
...@@ -58,6 +68,7 @@ ...@@ -58,6 +68,7 @@
group: 'issues', group: 'issues',
sort: false, sort: false,
disabled: this.disabled, disabled: this.disabled,
filter: '.board-list-count',
onStart: (e) => { onStart: (e) => {
const card = this.$refs.issue[e.oldIndex]; const card = this.$refs.issue[e.oldIndex];
......
...@@ -11,6 +11,7 @@ class List { ...@@ -11,6 +11,7 @@ class List {
this.loading = true; this.loading = true;
this.loadingMore = false; this.loadingMore = false;
this.issues = []; this.issues = [];
this.issuesSize = 0;
if (obj.label) { if (obj.label) {
this.label = new ListLabel(obj.label); this.label = new ListLabel(obj.label);
...@@ -51,17 +52,13 @@ class List { ...@@ -51,17 +52,13 @@ class List {
} }
nextPage () { nextPage () {
if (Math.floor(this.issues.length / 20) === this.page) { if (this.issuesSize > this.issues.length) {
this.page++; this.page++;
return this.getIssues(false); return this.getIssues(false);
} }
} }
canSearch () {
return this.type === 'backlog';
}
getIssues (emptyIssues = true) { getIssues (emptyIssues = true) {
const filters = this.filters; const filters = this.filters;
let data = { page: this.page }; let data = { page: this.page };
...@@ -80,12 +77,13 @@ class List { ...@@ -80,12 +77,13 @@ class List {
.then((resp) => { .then((resp) => {
const data = resp.json(); const data = resp.json();
this.loading = false; this.loading = false;
this.issuesSize = data.size;
if (emptyIssues) { if (emptyIssues) {
this.issues = []; this.issues = [];
} }
this.createIssues(data); this.createIssues(data.issues);
}); });
} }
...@@ -96,14 +94,20 @@ class List { ...@@ -96,14 +94,20 @@ class List {
} }
addIssue (issue, listFrom) { addIssue (issue, listFrom) {
this.issues.push(issue); if (!this.findIssue(issue.id)) {
this.issues.push(issue);
if (this.label) { if (this.label) {
issue.addLabel(this.label); issue.addLabel(this.label);
} }
if (listFrom) { if (listFrom) {
gl.boardService.moveIssue(issue.id, listFrom.id, this.id); this.issuesSize++;
gl.boardService.moveIssue(issue.id, listFrom.id, this.id)
.then(() => {
listFrom.getIssues(false);
});
}
} }
} }
...@@ -116,6 +120,7 @@ class List { ...@@ -116,6 +120,7 @@ class List {
const matchesRemove = removeIssue.id === issue.id; const matchesRemove = removeIssue.id === issue.id;
if (matchesRemove) { if (matchesRemove) {
this.issuesSize--;
issue.removeLabel(this.label); issue.removeLabel(this.label);
} }
......
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
author_id: gl.utils.getParameterValues('author_id')[0], author_id: gl.utils.getParameterValues('author_id')[0],
assignee_id: gl.utils.getParameterValues('assignee_id')[0], assignee_id: gl.utils.getParameterValues('assignee_id')[0],
milestone_title: gl.utils.getParameterValues('milestone_title')[0], milestone_title: gl.utils.getParameterValues('milestone_title')[0],
label_name: gl.utils.getParameterValues('label_name[]') label_name: gl.utils.getParameterValues('label_name[]'),
search: ''
}; };
}, },
addList (listObj) { addList (listObj) {
......
...@@ -199,6 +199,7 @@ ...@@ -199,6 +199,7 @@
break; break;
case 'labels': case 'labels':
switch (path[2]) { switch (path[2]) {
case 'new':
case 'edit': case 'edit':
new Labels(); new Labels();
} }
......
...@@ -117,7 +117,7 @@ ...@@ -117,7 +117,7 @@
} }
}); });
} else { } else {
return elements.show(); return elements.show().removeClass('option-hidden');
} }
} }
}; };
...@@ -190,9 +190,9 @@ ...@@ -190,9 +190,9 @@
currentIndex = -1; currentIndex = -1;
NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link, .option-hidden'; NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link';
SELECTABLE_CLASSES = ".dropdown-content li:not(" + NON_SELECTABLE_CLASSES + ")"; SELECTABLE_CLASSES = ".dropdown-content li:not(" + NON_SELECTABLE_CLASSES + ", .option-hidden)";
CURSOR_SELECT_SCROLL_PADDING = 5 CURSOR_SELECT_SCROLL_PADDING = 5
...@@ -556,7 +556,7 @@ ...@@ -556,7 +556,7 @@
if (isInput) { if (isInput) {
field = $(this.el); field = $(this.el);
} else { } else {
field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + value + "']"); field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + escape(value) + "']");
} }
if (el.hasClass(ACTIVE_CLASS)) { if (el.hasClass(ACTIVE_CLASS)) {
el.removeClass(ACTIVE_CLASS); el.removeClass(ACTIVE_CLASS);
...@@ -565,10 +565,6 @@ ...@@ -565,10 +565,6 @@
} else { } else {
field.remove(); field.remove();
} }
if (this.options.toggleLabel) {
this.updateLabel(selectedObject, el, this);
}
return selectedObject;
} else if (el.hasClass(INDETERMINATE_CLASS)) { } else if (el.hasClass(INDETERMINATE_CLASS)) {
el.addClass(ACTIVE_CLASS); el.addClass(ACTIVE_CLASS);
el.removeClass(INDETERMINATE_CLASS); el.removeClass(INDETERMINATE_CLASS);
...@@ -578,7 +574,6 @@ ...@@ -578,7 +574,6 @@
if (!field.length && fieldName) { if (!field.length && fieldName) {
this.addInput(fieldName, value, selectedObject); this.addInput(fieldName, value, selectedObject);
} }
return selectedObject;
} else { } else {
if (!this.options.multiSelect || el.hasClass('dropdown-clear-active')) { if (!this.options.multiSelect || el.hasClass('dropdown-clear-active')) {
this.dropdown.find("." + ACTIVE_CLASS).removeClass(ACTIVE_CLASS); this.dropdown.find("." + ACTIVE_CLASS).removeClass(ACTIVE_CLASS);
...@@ -590,9 +585,6 @@ ...@@ -590,9 +585,6 @@
field.remove(); field.remove();
} }
el.addClass(ACTIVE_CLASS); el.addClass(ACTIVE_CLASS);
if (this.options.toggleLabel) {
this.updateLabel(selectedObject, el, this);
}
if (value != null) { if (value != null) {
if (!field.length && fieldName) { if (!field.length && fieldName) {
this.addInput(fieldName, value, selectedObject); this.addInput(fieldName, value, selectedObject);
...@@ -600,8 +592,14 @@ ...@@ -600,8 +592,14 @@
field.val(value).trigger('change'); field.val(value).trigger('change');
} }
} }
return selectedObject;
} }
// Update label right after input has been added
if (this.options.toggleLabel) {
this.updateLabel(selectedObject, el, this);
}
return selectedObject;
}; };
GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject) { GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject) {
......
...@@ -127,7 +127,7 @@ ...@@ -127,7 +127,7 @@
Issue.prototype.initCanCreateBranch = function() { Issue.prototype.initCanCreateBranch = function() {
var $container; var $container;
$container = $('div#new-branch'); $container = $('#new-branch');
if ($container.length === 0) { if ($container.length === 0) {
return; return;
} }
...@@ -139,7 +139,6 @@ ...@@ -139,7 +139,6 @@
if (data.can_create_branch) { if (data.can_create_branch) {
$container.find('.checking').hide(); $container.find('.checking').hide();
$container.find('.available').show(); $container.find('.available').show();
return $container.find('a').attr('disabled', false);
} else { } else {
$container.find('.checking').hide(); $container.find('.checking').hide();
return $container.find('.unavailable').show(); return $container.find('.unavailable').show();
......
...@@ -164,7 +164,7 @@ ...@@ -164,7 +164,7 @@
instance.addInput(this.fieldName, label.id); instance.addInput(this.fieldName, label.id);
} }
} }
if ($form.find("input[type='hidden'][name='" + ($dropdown.data('fieldName')) + "'][value='" + (this.id(label)) + "']").length) { if ($form.find("input[type='hidden'][name='" + ($dropdown.data('fieldName')) + "'][value='" + escape(this.id(label)) + "']").length) {
selectedClass.push('is-active'); selectedClass.push('is-active');
} }
if ($dropdown.hasClass('js-multiselect') && removesAll) { if ($dropdown.hasClass('js-multiselect') && removesAll) {
......
...@@ -67,6 +67,14 @@ ...@@ -67,6 +67,14 @@
$.timeago.settings.strings = tmpLocale; $.timeago.settings.strings = tmpLocale;
}; };
w.gl.utils.getDayDifference = function(a, b) {
var millisecondsPerDay = 1000 * 60 * 60 * 24;
var date1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
var date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
return Math.floor((date2 - date1) / millisecondsPerDay);
}
})(window); })(window);
}).call(this); }).call(this);
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
} }
return newUrl; return newUrl;
}; };
return w.gl.utils.removeParamQueryString = function(url, param) { w.gl.utils.removeParamQueryString = function(url, param) {
var urlVariables, variables; var urlVariables, variables;
url = decodeURIComponent(url); url = decodeURIComponent(url);
urlVariables = url.split('&'); urlVariables = url.split('&');
...@@ -59,6 +59,16 @@ ...@@ -59,6 +59,16 @@
return results; return results;
})()).join('&'); })()).join('&');
}; };
w.gl.utils.getLocationHash = function(url) {
var hashIndex;
if (typeof url === 'undefined') {
// Note: We can't use window.location.hash here because it's
// not consistent across browsers - Firefox will pre-decode it
url = window.location.href;
}
hashIndex = url.indexOf('#');
return hashIndex === -1 ? null : url.substring(hashIndex + 1);
};
})(window); })(window);
}).call(this); }).call(this);
(function() { (function() {
var clearHighlights, currentTimer, defaultClass, delay, firstPiece, pieceIndex, pieces, start, stop, work;
Turbolinks.enableProgressBar(); Turbolinks.enableProgressBar();
defaultClass = 'tanuki-shape'; $(document).on('page:fetch', function() {
$('.tanuki-logo').addClass('animate');
pieces = ['path#tanuki-right-cheek', 'path#tanuki-right-eye, path#tanuki-right-ear', 'path#tanuki-nose', 'path#tanuki-left-eye, path#tanuki-left-ear', 'path#tanuki-left-cheek']; });
pieceIndex = 0;
firstPiece = pieces[0];
currentTimer = null;
delay = 150;
clearHighlights = function() {
return $("." + defaultClass + ".highlight").attr('class', defaultClass);
};
start = function() {
clearHighlights();
pieceIndex = 0;
if (pieces[0] !== firstPiece) {
pieces.reverse();
}
if (currentTimer) {
clearInterval(currentTimer);
}
return currentTimer = setInterval(work, delay);
};
stop = function() {
clearInterval(currentTimer);
return clearHighlights();
};
work = function() {
clearHighlights();
$(pieces[pieceIndex]).attr('class', defaultClass + " highlight");
if (pieceIndex === pieces.length - 1) {
pieceIndex = 0;
return pieces.reverse();
} else {
return pieceIndex++;
}
};
$(document).on('page:fetch', start);
$(document).on('page:change', stop); $(document).on('page:change', function() {
$('.tanuki-logo').removeClass('animate');
});
}).call(this); }).call(this);
...@@ -75,10 +75,8 @@ class MergeConflictResolver { ...@@ -75,10 +75,8 @@ class MergeConflictResolver {
window.location.href = data.redirect_to; window.location.href = data.redirect_to;
}) })
.error(() => { .error(() => {
new Flash('Something went wrong!');
})
.always(() => {
this.vue.isSubmitting = false; this.vue.isSubmitting = false;
new Flash('Something went wrong!');
}); });
} }
......
...@@ -17,19 +17,15 @@ ...@@ -17,19 +17,15 @@
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) {
var path;
path = '/';
$.cookie('hide_no_ssh_message', 'false', { $.cookie('hide_no_ssh_message', 'false', {
path: path 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) {
var path;
path = '/';
$.cookie('hide_no_password_message', 'false', { $.cookie('hide_no_password_message', 'false', {
path: path path: gon.relative_url_root || '/'
}); });
$(this).parents('.no-password-message').remove(); $(this).parents('.no-password-message').remove();
return e.preventDefault(); return e.preventDefault();
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
this.ProjectNew = (function() { this.ProjectNew = (function() {
function ProjectNew() { function ProjectNew() {
this.toggleSettings = bind(this.toggleSettings, this); this.toggleSettings = bind(this.toggleSettings, this);
this.$selects = $('.features select');
$('.project-edit-container').on('ajax:before', (function(_this) { $('.project-edit-container').on('ajax:before', (function(_this) {
return function() { return function() {
$('.project-edit-container').hide(); $('.project-edit-container').hide();
...@@ -15,18 +17,24 @@ ...@@ -15,18 +17,24 @@
} }
ProjectNew.prototype.toggleSettings = function() { ProjectNew.prototype.toggleSettings = function() {
this._showOrHide('#project_builds_enabled', '.builds-feature'); var self = this;
return this._showOrHide('#project_merge_requests_enabled', '.merge-requests-feature');
this.$selects.each(function () {
var $select = $(this),
className = $select.data('field').replace(/_/g, '-')
.replace('access-level', 'feature');
self._showOrHide($select, '.' + className);
});
}; };
ProjectNew.prototype.toggleSettingsOnclick = function() { ProjectNew.prototype.toggleSettingsOnclick = function() {
return $('#project_builds_enabled, #project_merge_requests_enabled').on('click', this.toggleSettings); this.$selects.on('change', this.toggleSettings);
}; };
ProjectNew.prototype._showOrHide = function(checkElement, container) { ProjectNew.prototype._showOrHide = function(checkElement, container) {
var $container; var $container = $(container);
$container = $(container);
if ($(checkElement).prop('checked')) { if ($(checkElement).val() !== '0') {
return $container.show(); return $container.show();
} else { } else {
return $container.hide(); return $container.hide();
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
} }
if (!triggered) { if (!triggered) {
return $.cookie("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed'), { return $.cookie("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed'), {
path: '/' path: gon.relative_url_root || '/'
}); });
} }
}); });
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
this.perPage = this.el.data('perPage'); this.perPage = this.el.data('perPage');
this.clearListeners(); this.clearListeners();
this.initBtnListeners(); this.initBtnListeners();
this.initFilters();
} }
Todos.prototype.clearListeners = function() { Todos.prototype.clearListeners = function() {
...@@ -27,6 +28,31 @@ ...@@ -27,6 +28,31 @@
return $('.todo').on('click', this.goToTodoUrl); return $('.todo').on('click', this.goToTodoUrl);
}; };
Todos.prototype.initFilters = function() {
new UsersSelect();
this.initFilterDropdown($('.js-project-search'), 'project_id', ['text']);
this.initFilterDropdown($('.js-type-search'), 'type');
this.initFilterDropdown($('.js-action-search'), 'action_id');
$('form.filter-form').on('submit', function (event) {
event.preventDefault();
Turbolinks.visit(this.action + '&' + $(this).serialize());
});
};
Todos.prototype.initFilterDropdown = function($dropdown, fieldName, searchFields) {
$dropdown.glDropdown({
selectable: true,
filterable: searchFields ? true : false,
fieldName: fieldName,
search: { fields: searchFields },
data: $dropdown.data('data'),
clicked: function() {
return $dropdown.closest('form.filter-form').submit();
}
})
};
Todos.prototype.doneClicked = function(e) { Todos.prototype.doneClicked = function(e) {
var $this; var $this;
e.preventDefault(); e.preventDefault();
...@@ -66,7 +92,7 @@ ...@@ -66,7 +92,7 @@
success: (function(_this) { success: (function(_this) {
return function(data) { return function(data) {
$this.remove(); $this.remove();
$('.js-todos-list').remove(); $('.prepend-top-default').html('<div class="nothing-here-block">You\'re all done!</div>');
return _this.updateBadges(data); return _this.updateBadges(data);
}; };
})(this) })(this)
......
(function() { (global => {
this.User = (function() { global.User = class {
function User(opts) { constructor(opts) {
this.opts = opts; this.opts = opts;
$('.profile-groups-avatars').tooltip({ this.placeProfileAvatarsToTop();
"placement": "top"
});
this.initTabs(); this.initTabs();
$('.hide-project-limit-message').on('click', function(e) { this.hideProjectLimitMessage();
var path; }
path = '/';
$.cookie('hide_project_limit_message', 'false', { placeProfileAvatarsToTop() {
path: path $('.profile-groups-avatars').tooltip({
}); placement: 'top'
$(this).parents('.project-limit-message').remove();
return e.preventDefault();
}); });
} }
User.prototype.initTabs = function() { initTabs() {
return new UserTabs({ return new UserTabs({
parentEl: '.user-profile', parentEl: '.user-profile',
action: this.opts.action action: this.opts.action
}); });
}; }
return User;
})();
}).call(this); hideProjectLimitMessage() {
$('.hide-project-limit-message').on('click', e => {
e.preventDefault();
const path = gon.relative_url_root || '/';
$.cookie('hide_project_limit_message', 'false', {
path: path
});
$(this).parents('.project-limit-message').remove();
});
}
}
})(window.gl || (window.gl = {}));
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
this.Calendar = (function() { this.Calendar = (function() {
function Calendar(timestamps, calendar_activities_path) { function Calendar(timestamps, calendar_activities_path) {
var group, i;
this.calendar_activities_path = calendar_activities_path; this.calendar_activities_path = calendar_activities_path;
this.clickDay = bind(this.clickDay, this); this.clickDay = bind(this.clickDay, this);
this.currentSelectedDate = ''; this.currentSelectedDate = '';
...@@ -13,26 +12,36 @@ ...@@ -13,26 +12,36 @@
this.monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; this.monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
this.months = []; this.months = [];
this.timestampsTmp = []; this.timestampsTmp = [];
i = 0; var group = 0;
group = 0;
_.each(timestamps, (function(_this) { var today = new Date()
return function(count, date) { today.setHours(0, 0, 0, 0, 0);
var day, innerArray, newDate;
newDate = new Date(parseInt(date) * 1000); var oneYearAgo = new Date(today);
day = newDate.getDay(); oneYearAgo.setFullYear(today.getFullYear() - 1);
if ((day === 0 && i !== 0) || i === 0) {
_this.timestampsTmp.push([]); var days = gl.utils.getDayDifference(oneYearAgo, today);
group++;
} for(var i = 0; i <= days; i++) {
innerArray = _this.timestampsTmp[group - 1]; var date = new Date(oneYearAgo);
innerArray.push({ date.setDate(date.getDate() + i);
count: count,
date: newDate, var day = date.getDay();
day: day var count = timestamps[date.getTime() * 0.001];
});
return i++; if ((day === 0 && i !== 0) || i === 0) {
}; this.timestampsTmp.push([]);
})(this)); group++;
}
var innerArray = this.timestampsTmp[group - 1];
innerArray.push({
count: count || 0,
date: date,
day: day
});
}
this.colorKey = this.initColorKey(); this.colorKey = this.initColorKey();
this.color = this.initColor(); this.color = this.initColor();
this.renderSvg(group); this.renderSvg(group);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
@import "framework/issue_box.scss"; @import "framework/issue_box.scss";
@import "framework/jquery.scss"; @import "framework/jquery.scss";
@import "framework/lists.scss"; @import "framework/lists.scss";
@import "framework/logo.scss";
@import "framework/markdown_area.scss"; @import "framework/markdown_area.scss";
@import "framework/mobile.scss"; @import "framework/mobile.scss";
@import "framework/modal.scss"; @import "framework/modal.scss";
......
...@@ -200,13 +200,15 @@ ...@@ -200,13 +200,15 @@
svg { svg {
height: 15px; height: 15px;
width: auto; width: 15px;
position: relative; position: relative;
top: 2px; top: 2px;
} }
svg, .fa { svg, .fa {
margin-right: 3px; &:not(:last-child) {
margin-right: 3px;
}
} }
} }
......
...@@ -53,7 +53,7 @@ pre { ...@@ -53,7 +53,7 @@ pre {
&.well-pre { &.well-pre {
border: 1px solid #eee; border: 1px solid #eee;
background: #f9f9f9; background: $gray-light;
border-radius: 0; border-radius: 0;
color: #555; color: #555;
} }
...@@ -225,7 +225,7 @@ li.note { ...@@ -225,7 +225,7 @@ li.note {
.milestone { .milestone {
&.milestone-closed { &.milestone-closed {
background: #f9f9f9; background: $gray-light;
} }
.progress { .progress {
margin-bottom: 0; margin-bottom: 0;
...@@ -248,7 +248,7 @@ li.note { ...@@ -248,7 +248,7 @@ li.note {
img.emoji { img.emoji {
height: 20px; height: 20px;
vertical-align: middle; vertical-align: top;
width: 20px; width: 20px;
} }
......
...@@ -17,6 +17,12 @@ ...@@ -17,6 +17,12 @@
.dropdown { .dropdown {
position: relative; position: relative;
.btn-link {
&:hover {
cursor: pointer;
}
}
} }
.open { .open {
...@@ -177,6 +183,13 @@ ...@@ -177,6 +183,13 @@
&.dropdown-menu-user-link { &.dropdown-menu-user-link {
line-height: 16px; line-height: 16px;
} }
.icon-play {
fill: $table-text-gray;
margin-right: 6px;
height: 12px;
width: 11px;
}
} }
.dropdown-header { .dropdown-header {
...@@ -189,6 +202,12 @@ ...@@ -189,6 +202,12 @@
.separator + .dropdown-header { .separator + .dropdown-header {
padding-top: 2px; padding-top: 2px;
} }
.unclickable {
cursor: not-allowed;
padding: 5px 8px;
color: $dropdown-header-color;
}
} }
.dropdown-menu-large { .dropdown-menu-large {
......
...@@ -115,7 +115,7 @@ ...@@ -115,7 +115,7 @@
padding: 0; padding: 0;
} }
td.blame-commit { td.blame-commit {
background: #f9f9f9; background: $gray-light;
min-width: 350px; min-width: 350px;
.commit-author-link { .commit-author-link {
......
...@@ -19,7 +19,6 @@ input[type='text'].danger { ...@@ -19,7 +19,6 @@ input[type='text'].danger {
} }
.form-actions { .form-actions {
margin: -$gl-padding;
margin-top: 0; margin-top: 0;
margin-bottom: -$gl-padding; margin-bottom: -$gl-padding;
padding: $gl-padding; padding: $gl-padding;
......
...@@ -2,16 +2,6 @@ ...@@ -2,16 +2,6 @@
* Application Header * Application Header
* *
*/ */
@mixin tanuki-logo-colors($path-color) {
fill: $path-color;
transition: all 0.8s;
&:hover,
&.highlight {
fill: lighten($path-color, 25%);
transition: all 0.1s;
}
}
header { header {
transition: padding $sidebar-transition-duration; transition: padding $sidebar-transition-duration;
...@@ -25,7 +15,7 @@ header { ...@@ -25,7 +15,7 @@ header {
margin: 8px 0; margin: 8px 0;
text-align: center; text-align: center;
#tanuki-logo, img { .tanuki-logo, img {
height: 36px; height: 36px;
} }
} }
...@@ -94,7 +84,7 @@ header { ...@@ -94,7 +84,7 @@ header {
.side-nav-toggle { .side-nav-toggle {
position: absolute; position: absolute;
left: -10px; left: -10px;
margin: 6px 0; margin: 7px 0;
font-size: 18px; font-size: 18px;
padding: 6px 10px; padding: 6px 10px;
border: none; border: none;
...@@ -146,6 +136,8 @@ header { ...@@ -146,6 +136,8 @@ header {
} }
.title { .title {
position: relative;
padding-right: 20px;
margin: 0; margin: 0;
font-size: 19px; font-size: 19px;
max-width: 400px; max-width: 400px;
...@@ -158,7 +150,11 @@ header { ...@@ -158,7 +150,11 @@ header {
vertical-align: top; vertical-align: top;
white-space: nowrap; white-space: nowrap;
@media (max-width: $screen-sm-max) { @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
max-width: 300px;
}
@media (max-width: $screen-xs-max) {
max-width: 190px; max-width: 190px;
} }
...@@ -170,11 +166,15 @@ header { ...@@ -170,11 +166,15 @@ header {
} }
.dropdown-toggle-caret { .dropdown-toggle-caret {
position: relative; color: $gl-text-color;
top: -2px; border: transparent;
background: transparent;
position: absolute;
right: 3px;
width: 12px; width: 12px;
line-height: 12px; line-height: 19px;
margin-left: 5px; margin-top: (($header-height - 19) / 2);
padding: 0;
font-size: 10px; font-size: 10px;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
...@@ -205,26 +205,6 @@ header { ...@@ -205,26 +205,6 @@ header {
} }
} }
#tanuki-logo {
#tanuki-left-ear,
#tanuki-right-ear,
#tanuki-nose {
@include tanuki-logo-colors($tanuki-red);
}
#tanuki-left-eye,
#tanuki-right-eye {
@include tanuki-logo-colors($tanuki-orange);
}
#tanuki-left-cheek,
#tanuki-right-cheek {
@include tanuki-logo-colors($tanuki-yellow);
}
}
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
header .container-fluid { header .container-fluid {
font-size: 18px; font-size: 18px;
......
@mixin unique-keyframes {
$animation-name: unique-id();
@include webkit-prefix(animation-name, $animation-name);
@-webkit-keyframes #{$animation-name} {
@content;
}
@keyframes #{$animation-name} {
@content;
}
}
@mixin tanuki-logo-colors($path-color) {
fill: $path-color;
transition: all 0.8s;
&:hover {
fill: lighten($path-color, 25%);
transition: all 0.1s;
}
}
@mixin tanuki-second-highlight-animations($tanuki-color) {
@include unique-keyframes {
10%, 80% {
fill: #{$tanuki-color}
}
20%, 90% {
fill: lighten($tanuki-color, 25%);
}
}
}
@mixin tanuki-forth-highlight-animations($tanuki-color) {
@include unique-keyframes {
30%, 60% {
fill: #{$tanuki-color};
}
40%, 70% {
fill: lighten($tanuki-color, 25%);
}
}
}
.tanuki-logo {
.tanuki-left-ear,
.tanuki-right-ear,
.tanuki-nose {
@include tanuki-logo-colors($tanuki-red);
}
.tanuki-left-eye,
.tanuki-right-eye {
@include tanuki-logo-colors($tanuki-orange);
}
.tanuki-left-cheek,
.tanuki-right-cheek {
@include tanuki-logo-colors($tanuki-yellow);
}
&.animate {
.tanuki-shape {
@include webkit-prefix(animation-duration, 1.5s);
@include webkit-prefix(animation-iteration-count, infinite);
}
.tanuki-left-cheek {
@include unique-keyframes {
0%, 10%, 100% {
fill: lighten($tanuki-yellow, 25%);
}
90% {
fill: $tanuki-yellow;
}
}
}
.tanuki-left-eye {
@include tanuki-second-highlight-animations($tanuki-orange);
}
.tanuki-left-ear {
@include tanuki-second-highlight-animations($tanuki-red);
}
.tanuki-nose {
@include unique-keyframes {
20%, 70% {
fill: $tanuki-red;
}
30%, 80% {
fill: lighten($tanuki-red, 25%);
}
}
}
.tanuki-right-eye {
@include tanuki-forth-highlight-animations($tanuki-orange);
}
.tanuki-right-ear {
@include tanuki-forth-highlight-animations($tanuki-red);
}
.tanuki-right-cheek {
@include unique-keyframes {
40% {
fill: $tanuki-yellow;
}
60% {
fill: lighten($tanuki-yellow, 25%);
}
}
}
}
}
\ No newline at end of file
...@@ -9,43 +9,11 @@ ...@@ -9,43 +9,11 @@
border-radius: $radius; border-radius: $radius;
} }
@mixin border-radius-left($radius) {
@include border-radius($radius 0 0 $radius)
}
@mixin border-radius-right($radius) {
@include border-radius(0 0 $radius $radius)
}
@mixin linear-gradient($from, $to) {
background-image: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to));
background-image: -webkit-linear-gradient($from, $to);
background-image: -moz-linear-gradient($from, $to);
background-image: -ms-linear-gradient($from, $to);
background-image: -o-linear-gradient($from, $to);
}
@mixin transition($transition) {
-webkit-transition: $transition;
-moz-transition: $transition;
-ms-transition: $transition;
-o-transition: $transition;
transition: $transition;
}
/** /**
* Prefilled mixins * Prefilled mixins
* Mixins with fixed values * Mixins with fixed values
*/ */
@mixin shade {
@include box-shadow(0 0 3px #ddd);
}
@mixin solid-shade {
@include box-shadow(0 0 0 3px #f1f1f1);
}
@mixin str-truncated($max_width: 82%) { @mixin str-truncated($max_width: 82%) {
display: inline-block; display: inline-block;
overflow: hidden; overflow: hidden;
...@@ -76,7 +44,7 @@ ...@@ -76,7 +44,7 @@
} }
&.active { &.active {
background: #f9f9f9; background: $gray-light;
a { a {
font-weight: 600; font-weight: 600;
} }
...@@ -94,23 +62,6 @@ ...@@ -94,23 +62,6 @@
} }
} }
@mixin input-big {
height: 36px;
padding: 5px 10px;
font-size: 16px;
line-height: 24px;
color: #7f8fa4;
background-color: #fff;
border-color: #e7e9ed;
}
@mixin btn-big {
height: 36px;
padding: 5px 10px;
font-size: 16px;
line-height: 24px;
}
@mixin bulleted-list { @mixin bulleted-list {
> ul { > ul {
list-style-type: disc; list-style-type: disc;
...@@ -129,3 +80,8 @@ ...@@ -129,3 +80,8 @@
color: rgba(255, 255, 255, 0.3); color: rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.1); background: rgba(255, 255, 255, 0.1);
} }
@mixin webkit-prefix($property, $value) {
#{'-webkit-' + $property}: $value;
#{$property}: $value;
}
@mixin fade($gradient-direction, $rgba, $gradient-color) { @mixin fade($gradient-direction, $gradient-color) {
visibility: hidden; visibility: hidden;
opacity: 0; opacity: 0;
z-index: 2; z-index: 2;
...@@ -8,10 +8,7 @@ ...@@ -8,10 +8,7 @@
height: 30px; height: 30px;
transition-duration: .3s; transition-duration: .3s;
-webkit-transform: translateZ(0); -webkit-transform: translateZ(0);
background: -webkit-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); background: linear-gradient(to $gradient-direction, $gradient-color 45%, rgba($gradient-color, 0.4));
background: -o-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
background: -moz-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
background: linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
&.scrolling { &.scrolling {
visibility: visible; visibility: visible;
...@@ -71,7 +68,7 @@ ...@@ -71,7 +68,7 @@
.badge { .badge {
font-weight: normal; font-weight: normal;
background-color: #eee; background-color: #eee;
color: #78a; color: $btn-transparent-color;
vertical-align: baseline; vertical-align: baseline;
} }
} }
...@@ -161,6 +158,7 @@ ...@@ -161,6 +158,7 @@
> .dropdown { > .dropdown {
margin-right: $gl-padding-top; margin-right: $gl-padding-top;
display: inline-block; display: inline-block;
vertical-align: top;
&:last-child { &:last-child {
margin-right: 0; margin-right: 0;
...@@ -210,12 +208,6 @@ ...@@ -210,12 +208,6 @@
} }
} }
.project-filter-form {
input {
background-color: $background-color;
}
}
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
padding-bottom: 0; padding-bottom: 0;
width: 100%; width: 100%;
...@@ -335,10 +327,6 @@ ...@@ -335,10 +327,6 @@
} }
} }
.badge {
color: $gl-icon-color;
}
&:hover { &:hover {
a, i { a, i {
color: $black; color: $black;
...@@ -356,7 +344,7 @@ ...@@ -356,7 +344,7 @@
} }
.fade-right { .fade-right {
@include fade(left, rgba(255, 255, 255, 0.4), $background-color); @include fade(left, $background-color);
right: -5px; right: -5px;
.fa { .fa {
...@@ -365,7 +353,7 @@ ...@@ -365,7 +353,7 @@
} }
.fade-left { .fade-left {
@include fade(right, rgba(255, 255, 255, 0.4), $background-color); @include fade(right, $background-color);
left: -5px; left: -5px;
.fa { .fa {
...@@ -376,6 +364,7 @@ ...@@ -376,6 +364,7 @@
&.sub-nav-scroll { &.sub-nav-scroll {
.fade-right { .fade-right {
@include fade(left, $dark-background-color);
right: 0; right: 0;
.fa { .fa {
...@@ -384,6 +373,7 @@ ...@@ -384,6 +373,7 @@
} }
.fade-left { .fade-left {
@include fade(right, $dark-background-color);
left: 0; left: 0;
.fa { .fa {
...@@ -400,7 +390,7 @@ ...@@ -400,7 +390,7 @@
@include scrolling-links(); @include scrolling-links();
.fade-right { .fade-right {
@include fade(left, rgba(255, 255, 255, 0.4), $white-light); @include fade(left, $white-light);
right: -5px; right: -5px;
.fa { .fa {
...@@ -409,7 +399,7 @@ ...@@ -409,7 +399,7 @@
} }
.fade-left { .fade-left {
@include fade(right, rgba(255, 255, 255, 0.4), $white-light); @include fade(right, $white-light);
left: -5px; left: -5px;
.fa { .fa {
......
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
background-position: right 0 bottom 6px; background-position: right 0 bottom 6px;
border: 1px solid $input-border; border: 1px solid $input-border;
@include border-radius($border-radius-default); @include border-radius($border-radius-default);
@include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s); transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
&:focus { &:focus {
border-color: $input-border-focus; border-color: $input-border-focus;
......
...@@ -125,7 +125,7 @@ $panel-inner-border: $border-color; ...@@ -125,7 +125,7 @@ $panel-inner-border: $border-color;
// //
//## //##
$well-bg: #f9f9f9; $well-bg: $gray-light;
$well-border: #eee; $well-border: #eee;
//== Code //== Code
......
...@@ -159,25 +159,18 @@ ...@@ -159,25 +159,18 @@
position: relative; position: relative;
a.anchor { a.anchor {
// Setting `display: none` would prevent the anchor being scrolled to, so left: -16px;
// instead we set the height to 0 and it gets updated on hover. position: absolute;
height: 0; text-decoration: none;
&:after {
content: url('icon_anchor.svg');
visibility: hidden;
}
} }
&:hover > a.anchor { &:hover > a.anchor:after {
$size: 14px; visibility: visible;
position: absolute;
right: 100%;
top: 50%;
margin-top: -11px;
margin-right: 0;
padding-right: 15px;
display: inline-block;
width: $size;
height: $size;
background-image: image-url("icon-link.png");
background-size: contain;
background-repeat: no-repeat;
} }
} }
} }
......
...@@ -9,13 +9,79 @@ $gutter_inner_width: 258px; ...@@ -9,13 +9,79 @@ $gutter_inner_width: 258px;
$sidebar-transition-duration: .15s; $sidebar-transition-duration: .15s;
$sidebar-breakpoint: 1024px; $sidebar-breakpoint: 1024px;
/*
* Color schema
*/
$white-light: #fff;
$white-normal: #ededed;
$white-dark: #ececec;
$gray-light: #fafafa;
$gray-normal: #f5f5f5;
$gray-dark: #ededed;
$gray-darkest: #c9c9c9;
$green-light: #38ae67;
$green-normal: #2faa60;
$green-dark: #2ca05b;
$blue-light: #2ea8e5;
$blue-normal: #2d9fd8;
$blue-dark: #2897ce;
$blue-medium-light: #3498cb;
$blue-medium: #2f8ebf;
$blue-medium-dark: #2d86b4;
$orange-light: #fc8a51;
$orange-normal: #e75e40;
$orange-dark: #ce5237;
$red-light: #e52c5a;
$red-normal: #d22852;
$red-dark: darken($red-normal, 5%);
$black: #000;
$black-transparent: rgba(0, 0, 0, 0.3);
$border-white-light: #f1f2f4;
$border-white-normal: #d6dae2;
$border-white-dark: #c6cacf;
$border-gray-light: #dcdcdc;
$border-gray-normal: #d7d7d7;
$border-gray-dark: #c6cacf;
$border-green-light: #2faa60;
$border-green-normal: #2ca05b;
$border-green-dark: #279654;
$border-blue-light: #2d9fd8;
$border-blue-normal: #2897ce;
$border-blue-dark: #258dc1;
$border-orange-light: #fc6d26;
$border-orange-normal: #ce5237;
$border-orange-dark: #c14e35;
$border-red-light: #d22852;
$border-red-normal: #ca264f;
$border-red-dark: darken($border-red-normal, 5%);
$help-well-bg: $gray-light;
$help-well-border: #e5e5e5;
$warning-message-bg: #fbf2d9;
$warning-message-color: #9e8e60;
$warning-message-border: #f0e2bb;
/* /*
* UI elements * UI elements
*/ */
$border-color: #e5e5e5; $border-color: #e5e5e5;
$focus-border-color: #3aabf0; $focus-border-color: #3aabf0;
$table-border-color: #f0f0f0; $table-border-color: #f0f0f0;
$background-color: #fafafa; $background-color: $gray-light;
$dark-background-color: #f5f5f5; $dark-background-color: #f5f5f5;
$table-text-gray: #8f8f8f; $table-text-gray: #8f8f8f;
...@@ -90,73 +156,6 @@ $btn-side-margin: 10px; ...@@ -90,73 +156,6 @@ $btn-side-margin: 10px;
$btn-sm-side-margin: 7px; $btn-sm-side-margin: 7px;
$btn-xs-side-margin: 5px; $btn-xs-side-margin: 5px;
/*
* Color schema
*/
$white-light: #fff;
$white-normal: #ededed;
$white-dark: #ececec;
$gray-light: #faf9f9;
$gray-normal: #f5f5f5;
$gray-dark: #ededed;
$gray-darkest: #c9c9c9;
$green-light: #38ae67;
$green-normal: #2faa60;
$green-dark: #2ca05b;
$blue-light: #2ea8e5;
$blue-normal: #2d9fd8;
$blue-dark: #2897ce;
$blue-medium-light: #3498cb;
$blue-medium: #2f8ebf;
$blue-medium-dark: #2d86b4;
$orange-light: #fc8a51;
$orange-normal: #e75e40;
$orange-dark: #ce5237;
$red-light: #e52c5a;
$red-normal: #d22852;
$red-dark: darken($red-normal, 5%);
$black: #000;
$black-transparent: rgba(0, 0, 0, 0.3);
$border-white-light: #f1f2f4;
$border-white-normal: #d6dae2;
$border-white-dark: #c6cacf;
$border-gray-light: #dcdcdc;
$border-gray-normal: #d7d7d7;
$border-gray-dark: #c6cacf;
$border-green-light: #2faa60;
$border-green-normal: #2ca05b;
$border-green-dark: #279654;
$border-blue-light: #2d9fd8;
$border-blue-normal: #2897ce;
$border-blue-dark: #258dc1;
$border-orange-light: #fc6d26;
$border-orange-normal: #ce5237;
$border-orange-dark: #c14e35;
$border-red-light: #d22852;
$border-red-normal: #ca264f;
$border-red-dark: darken($border-red-normal, 5%);
$help-well-bg: #fafafa;
$help-well-border: #e5e5e5;
$warning-message-bg: #fbf2d9;
$warning-message-color: #9e8e60;
$warning-message-border: #f0e2bb;
/* tanuki logo colors */ /* tanuki logo colors */
$tanuki-red: #e24329; $tanuki-red: #e24329;
$tanuki-orange: #fc6d26; $tanuki-orange: #fc6d26;
...@@ -186,7 +185,7 @@ $line-removed-dark: #fac5cd; ...@@ -186,7 +185,7 @@ $line-removed-dark: #fac5cd;
$line-number-old: #f9d7dc; $line-number-old: #f9d7dc;
$line-number-new: #ddfbe6; $line-number-new: #ddfbe6;
$line-number-select: #fbf2da; $line-number-select: #fbf2da;
$match-line: #fafafa; $match-line: $gray-light;
$table-border-gray: #f0f0f0; $table-border-gray: #f0f0f0;
$line-target-blue: #eaf3fc; $line-target-blue: #eaf3fc;
$line-select-yellow: #fcf8e7; $line-select-yellow: #fcf8e7;
...@@ -267,7 +266,7 @@ $zen-control-hover-color: #111; ...@@ -267,7 +266,7 @@ $zen-control-hover-color: #111;
$calendar-header-color: #b8b8b8; $calendar-header-color: #b8b8b8;
$calendar-hover-bg: #ecf3fe; $calendar-hover-bg: #ecf3fe;
$calendar-border-color: rgba(#000, .1); $calendar-border-color: rgba(#000, .1);
$calendar-unselectable-bg: #faf9f9; $calendar-unselectable-bg: $gray-light;
/* /*
* Personal Access Tokens * Personal Access Tokens
......
...@@ -96,6 +96,10 @@ ...@@ -96,6 +96,10 @@
line-height: inherit; line-height: inherit;
} }
} }
.label-default {
color: $btn-transparent-color;
}
} }
.abuse-reports { .abuse-reports {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
.is-dragging { .is-dragging {
// Important because plugin sets inline CSS // Important because plugin sets inline CSS
opacity: 1!important; opacity: 1!important;
* { * {
// !important to make sure no style can override this when dragging // !important to make sure no style can override this when dragging
cursor: -webkit-grabbing!important; cursor: -webkit-grabbing!important;
...@@ -142,11 +142,6 @@ ...@@ -142,11 +142,6 @@
} }
} }
.board-header-loading-spinner {
margin-right: 10px;
color: $gray-darkest;
}
.board-inner-container { .board-inner-container {
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
padding: $gl-padding; padding: $gl-padding;
...@@ -160,40 +155,6 @@ ...@@ -160,40 +155,6 @@
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
} }
.board-search-container {
position: relative;
background-color: #fff;
.form-control {
padding-right: 30px;
}
}
.board-search-icon,
.board-search-clear-btn {
position: absolute;
right: $gl-padding + 10px;
top: 50%;
margin-top: -7px;
font-size: 14px;
}
.board-search-icon {
color: $gl-placeholder-color;
}
.board-search-clear-btn {
padding: 0;
line-height: 1;
background: transparent;
border: 0;
outline: 0;
&:hover {
color: $gl-link-color;
}
}
.board-delete { .board-delete {
margin-right: 10px; margin-right: 10px;
padding: 0; padding: 0;
...@@ -304,3 +265,22 @@ ...@@ -304,3 +265,22 @@
margin-right: 8px; margin-right: 8px;
font-weight: 500; font-weight: 500;
} }
.issue-boards-search {
width: 335px;
.form-control {
display: inline-block;
width: 210px;
}
}
.board-list-count {
padding: 10px 0;
color: $gl-placeholder-color;
font-size: 13px;
> .fa {
margin-right: 5px;
}
}
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
&.affix { &.affix {
right: 30px; right: 30px;
bottom: 15px; bottom: 15px;
z-index: 1;
@media (min-width: $screen-md-min) { @media (min-width: $screen-md-min) {
right: 26%; right: 26%;
...@@ -107,7 +108,7 @@ ...@@ -107,7 +108,7 @@
} }
.blocks-container { .blocks-container {
padding: $gl-padding; padding: 0 $gl-padding;
} }
.block { .block {
...@@ -122,6 +123,13 @@ ...@@ -122,6 +123,13 @@
} }
} }
.retry-link {
color: $gl-link-color;
&:hover {
text-decoration: underline;
}
}
.stage-item { .stage-item {
cursor: pointer; cursor: pointer;
...@@ -131,7 +139,7 @@ ...@@ -131,7 +139,7 @@
} }
.build-dropdown { .build-dropdown {
padding: 0 $gl-padding; padding: $gl-padding 0;
.dropdown-menu-toggle { .dropdown-menu-toggle {
margin-top: 8px; margin-top: 8px;
...@@ -145,12 +153,11 @@ ...@@ -145,12 +153,11 @@
} }
.builds-container { .builds-container {
margin-top: $gl-padding;
background-color: $white-light; background-color: $white-light;
border-top: 1px solid $border-color; border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
max-height: 300px; max-height: 300px;
overflow: scroll; overflow: auto;
svg { svg {
position: relative; position: relative;
......
...@@ -113,11 +113,13 @@ ...@@ -113,11 +113,13 @@
.commit-row-description { .commit-row-description {
font-size: 14px; font-size: 14px;
border-left: 1px solid #eee; border-left: 1px solid $btn-gray-hover;
padding: 10px 15px; padding: 10px 15px;
margin: 10px 0; margin: 10px 0;
background: #f9f9f9; background: $gray-light;
display: none; display: none;
white-space: pre-line;
word-break: normal;
pre { pre {
border: none; border: none;
......
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
margin: 0; margin: 0;
} }
.fa-play { .icon-play {
font-size: 14px; height: 13px;
width: 12px;
} }
.dropdown-new { .dropdown-new {
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
pre { pre {
border: none; border: none;
background: #f9f9f9; background: $gray-light;
border-radius: 0; border-radius: 0;
color: #777; color: #777;
margin: 0 20px; margin: 0 20px;
...@@ -92,7 +92,7 @@ ...@@ -92,7 +92,7 @@
border: 1px solid #eee; border: 1px solid #eee;
padding: 5px; padding: 5px;
@include border-radius(5px); @include border-radius(5px);
background: #f9f9f9; background: $gray-light;
margin-left: 10px; margin-left: 10px;
top: -6px; top: -6px;
img { img {
...@@ -115,11 +115,8 @@ ...@@ -115,11 +115,8 @@
} }
&.commits-stat { &.commits-stat {
margin-top: 3px;
display: block; display: block;
padding: 3px; padding: 0 3px 0 0;
padding-left: 0;
&:hover { &:hover {
background: none; background: none;
} }
......
i.icon-gitorious {
display: inline-block;
background-position: 0 0;
background-size: contain;
background-repeat: no-repeat;
}
i.icon-gitorious-small {
background-image: image-url('gitorious-logo-blue.png');
width: 13px;
height: 13px;
}
i.icon-gitorious-big {
background-image: image-url('gitorious-logo-black.png');
width: 18px;
height: 18px;
}
.import-jobs-from-col, .import-jobs-from-col,
.import-jobs-to-col { .import-jobs-to-col {
width: 40%; width: 40%;
......
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
padding-right: 8px; padding-right: 8px;
margin-bottom: 10px; margin-bottom: 10px;
min-width: 15px; min-width: 15px;
.selected_issue {
vertical-align: text-top;
}
} }
.issue-labels { .issue-labels {
...@@ -68,12 +72,12 @@ form.edit-issue { ...@@ -68,12 +72,12 @@ form.edit-issue {
} }
&.closed { &.closed {
background: #f9f9f9; background: $gray-light;
border-color: #e5e5e5; border-color: #e5e5e5;
} }
&.merged { &.merged {
background: #f9f9f9; background: $gray-light;
border-color: #e5e5e5; border-color: #e5e5e5;
} }
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
display: inline-block; display: inline-block;
margin-right: 10px; margin-right: 10px;
margin-bottom: 10px; margin-bottom: 10px;
text-decoration: none;
} }
&.suggest-colors-dropdown { &.suggest-colors-dropdown {
......
...@@ -16,7 +16,7 @@ $colors: ( ...@@ -16,7 +16,7 @@ $colors: (
white_button_origin_chosen : #268ced, white_button_origin_chosen : #268ced,
white_header_not_chosen : #f0f0f0, white_header_not_chosen : #f0f0f0,
white_line_not_chosen : #f9f9f9, white_line_not_chosen : $gray-light,
dark_header_head_neutral : rgba(#3f3, .2), dark_header_head_neutral : rgba(#3f3, .2),
......
...@@ -269,7 +269,7 @@ ...@@ -269,7 +269,7 @@
.builds { .builds {
.table-holder { .table-holder {
overflow-x: scroll; overflow-x: auto;
} }
} }
...@@ -375,6 +375,16 @@ ...@@ -375,6 +375,16 @@
} }
} }
.mr-version-switch {
background: $background-color;
padding: $gl-btn-padding;
color: $gl-placeholder-color;
a.btn-link {
color: $gl-dark-link-color;
}
}
.merge-request-details { .merge-request-details {
.title { .title {
......
...@@ -281,19 +281,13 @@ ul.notes { ...@@ -281,19 +281,13 @@ ul.notes {
font-size: 17px; font-size: 17px;
} }
&.js-note-delete { &:hover {
i { .danger-highlight {
&:hover { color: $gl-text-red;
color: $gl-text-red;
}
} }
}
&.js-note-edit { .link-highlight {
i { color: $gl-link-color;
&:hover {
color: $gl-link-color;
}
} }
} }
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
.stage { .stage {
max-width: 90px; max-width: 90px;
width: 90px; width: 90px;
text-align: center;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
...@@ -146,6 +147,7 @@ ...@@ -146,6 +147,7 @@
} }
.stage-cell { .stage-cell {
text-align: center;
svg { svg {
height: 18px; height: 18px;
...@@ -153,10 +155,6 @@ ...@@ -153,10 +155,6 @@
vertical-align: middle; vertical-align: middle;
overflow: visible; overflow: visible;
} }
.light {
width: 3px;
}
} }
.duration, .duration,
...@@ -215,6 +213,13 @@ ...@@ -215,6 +213,13 @@
border-color: $border-white-normal; border-color: $border-white-normal;
} }
} }
.btn {
.icon-play {
height: 13px;
width: 12px;
}
}
} }
} }
...@@ -254,7 +259,6 @@ ...@@ -254,7 +259,6 @@
width: 100%; width: 100%;
overflow: auto; overflow: auto;
white-space: nowrap; white-space: nowrap;
max-height: 500px;
transition: max-height 0.3s, padding 0.3s; transition: max-height 0.3s, padding 0.3s;
&.graph-collapsed { &.graph-collapsed {
...@@ -265,7 +269,6 @@ ...@@ -265,7 +269,6 @@
.pipeline-visualization { .pipeline-visualization {
position: relative; position: relative;
min-width: 1220px;
ul { ul {
padding: 0; padding: 0;
...@@ -275,7 +278,7 @@ ...@@ -275,7 +278,7 @@
.stage-column { .stage-column {
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
margin-right: 50px; margin-right: 65px;
li { li {
list-style: none; list-style: none;
...@@ -321,6 +324,14 @@ ...@@ -321,6 +324,14 @@
a { a {
color: $layout-link-gray; color: $layout-link-gray;
text-decoration: none;
&:hover {
.ci-status-text {
text-decoration: underline;
}
}
} }
} }
...@@ -336,9 +347,9 @@ ...@@ -336,9 +347,9 @@
content: ''; content: '';
position: absolute; position: absolute;
top: 50%; top: 50%;
right: -54px; right: -69px;
border-top: 2px solid $border-color; border-top: 2px solid $border-color;
width: 54px; width: 69px;
height: 1px; height: 1px;
} }
} }
...@@ -358,22 +369,25 @@ ...@@ -358,22 +369,25 @@
&::after { &::after {
right: -20px; right: -20px;
border-right: 2px solid $border-color; border-right: 2px solid $border-color;
border-radius: 0 0 50px; border-radius: 0 0 15px;
} }
// Left connecting curves // Left connecting curves
&::before { &::before {
left: -20px; left: -20px;
border-left: 2px solid $border-color; border-left: 2px solid $border-color;
border-radius: 0 0 0 50px; border-radius: 0 0 0 15px;
} }
} }
// 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: 45px; height: 29px;
top: -26px; top: -10px;
}
.curve {
display: block;
} }
} }
} }
...@@ -392,6 +406,12 @@ ...@@ -392,6 +406,12 @@
border: none; border: none;
} }
} }
// Remove opposite curve
.curve {
&::before {
display: none;
}
}
} }
} }
...@@ -403,6 +423,39 @@ ...@@ -403,6 +423,39 @@
border: none; border: none;
} }
} }
// Remove opposite curve
.curve {
&::after {
display: none;
}
}
}
}
// Curve first child connecting lines in opposite direction
.curve {
display: none;
&::before,
&::after {
content: '';
width: 21px;
height: 25px;
position: absolute;
top: -28.5px;
border-top: 2px solid $border-color;
}
&::after {
left: -39px;
border-right: 2px solid $border-color;
border-radius: 0 15px;
}
&::before {
right: -39px;
border-left: 2px solid $border-color;
border-radius: 15px 0 0;
} }
} }
} }
...@@ -421,11 +474,22 @@ ...@@ -421,11 +474,22 @@
.pipelines.tab-pane { .pipelines.tab-pane {
.content-list.pipelines { .content-list.pipelines {
overflow: scroll; overflow: auto;
} }
.stage { .stage {
max-width: 60px; max-width: 100px;
width: 60px; width: 100px;
}
.pipeline-actions {
min-width: initial;
}
}
.ci-status-icon-created {
svg {
fill: $table-text-gray;
} }
} }
...@@ -311,6 +311,14 @@ a.deploy-project-label { ...@@ -311,6 +311,14 @@ a.deploy-project-label {
color: $gl-success; color: $gl-success;
} }
.lfs-enabled {
color: $gl-success;
}
.lfs-disabled {
color: $gl-warning;
}
.breadcrumb.repo-breadcrumb { .breadcrumb.repo-breadcrumb {
padding: 0; padding: 0;
background: transparent; background: transparent;
...@@ -600,18 +608,25 @@ pre.light-well { ...@@ -600,18 +608,25 @@ pre.light-well {
} }
} }
.project-show-readme .readme-holder { .project-show-readme {
padding: $gl-padding 0; .row-content-block {
border-top: 0; background-color: inherit;
border: none;
.edit-project-readme {
z-index: 2;
position: relative;
} }
.wiki h1 { .readme-holder {
border-bottom: none; padding: $gl-padding 0;
padding: 0; border-top: 0;
.edit-project-readme {
z-index: 2;
position: relative;
}
.wiki h1 {
border-bottom: none;
padding: 0;
}
} }
} }
......
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
.search-icon { .search-icon {
@extend .fa-search; @extend .fa-search;
@include transition(color .15s); transition: color 0.15s;
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;
-ms-user-select: none; -ms-user-select: none;
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
} }
.location-badge { .location-badge {
@include transition(all .15s); transition: all 0.15s;
background-color: $location-badge-active-bg; background-color: $location-badge-active-bg;
color: $white-light; color: $white-light;
} }
......
...@@ -43,6 +43,15 @@ ...@@ -43,6 +43,15 @@
border-color: $blue-normal; border-color: $blue-normal;
} }
&.ci-created {
color: $table-text-gray;
border-color: $table-text-gray;
svg {
fill: $table-text-gray;
}
}
svg { svg {
height: 13px; height: 13px;
width: 13px; width: 13px;
......
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
pre { pre {
border: none; border: none;
background: #f9f9f9; background: $gray-light;
border-radius: 0; border-radius: 0;
color: #777; color: #777;
margin: 0 20px; margin: 0 20px;
......
...@@ -11,6 +11,20 @@ ...@@ -11,6 +11,20 @@
} }
} }
.add-to-tree {
vertical-align: top;
}
.last-commit {
max-width: 506px;
.last-commit-content {
@include str-truncated;
width: calc(100% - 140px);
margin-left: 3px;
}
}
.tree-table { .tree-table {
margin-bottom: 0; margin-bottom: 0;
......
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
$l-cyan: #8abeb7; $l-cyan: #8abeb7;
$l-white: $ci-text-color; $l-white: $ci-text-color;
.term-bold {
font-weight: bold;
}
.term-italic { .term-italic {
font-style: italic; font-style: italic;
} }
......
...@@ -29,7 +29,8 @@ class Admin::SystemInfoController < Admin::ApplicationController ...@@ -29,7 +29,8 @@ class Admin::SystemInfoController < Admin::ApplicationController
] ]
def show def show
system_info = Vmstat.snapshot @cpus = Vmstat.cpu rescue nil
@memory = Vmstat.memory rescue nil
mounts = Sys::Filesystem.mounts mounts = Sys::Filesystem.mounts
@disks = [] @disks = []
...@@ -50,10 +51,5 @@ class Admin::SystemInfoController < Admin::ApplicationController ...@@ -50,10 +51,5 @@ class Admin::SystemInfoController < Admin::ApplicationController
rescue Sys::Filesystem::Error rescue Sys::Filesystem::Error
end end
end end
@cpus = system_info.cpus.length
@mem_used = system_info.memory.active_bytes
@mem_total = system_info.memory.total_bytes
end end
end end
...@@ -24,8 +24,8 @@ class ApplicationController < ActionController::Base ...@@ -24,8 +24,8 @@ class ApplicationController < ActionController::Base
protect_from_forgery with: :exception protect_from_forgery with: :exception
helper_method :abilities, :can?, :current_application_settings helper_method :can?, :current_application_settings
helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?, :gitlab_project_import_enabled? helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?, :gitlab_project_import_enabled?
rescue_from Encoding::CompatibilityError do |exception| rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception) log_exception(exception)
...@@ -97,12 +97,8 @@ class ApplicationController < ActionController::Base ...@@ -97,12 +97,8 @@ class ApplicationController < ActionController::Base
current_application_settings.after_sign_out_path.presence || new_user_session_path current_application_settings.after_sign_out_path.presence || new_user_session_path
end end
def abilities
Ability.abilities
end
def can?(object, action, subject) def can?(object, action, subject)
abilities.allowed?(object, action, subject) Ability.allowed?(object, action, subject)
end end
def access_denied! def access_denied!
...@@ -250,10 +246,6 @@ class ApplicationController < ActionController::Base ...@@ -250,10 +246,6 @@ class ApplicationController < ActionController::Base
Gitlab::OAuth::Provider.enabled?(:bitbucket) && Gitlab::BitbucketImport.public_key.present? Gitlab::OAuth::Provider.enabled?(:bitbucket) && Gitlab::BitbucketImport.public_key.present?
end end
def gitorious_import_enabled?
current_application_settings.import_sources.include?('gitorious')
end
def google_code_import_enabled? def google_code_import_enabled?
current_application_settings.import_sources.include?('google_code') current_application_settings.import_sources.include?('google_code')
end end
......
...@@ -8,10 +8,14 @@ module ToggleAwardEmoji ...@@ -8,10 +8,14 @@ module ToggleAwardEmoji
def toggle_award_emoji def toggle_award_emoji
name = params.require(:name) name = params.require(:name)
awardable.toggle_award_emoji(name, current_user) if awardable.user_can_award?(current_user, name)
TodoService.new.new_award_emoji(to_todoable(awardable), current_user) awardable.toggle_award_emoji(name, current_user)
TodoService.new.new_award_emoji(to_todoable(awardable), current_user)
render json: { ok: true } render json: { ok: true }
else
render json: { ok: false }
end
end end
private private
......
class Import::GitoriousController < Import::BaseController
before_action :verify_gitorious_import_enabled
def new
redirect_to client.authorize_url(callback_import_gitorious_url)
end
def callback
session[:gitorious_repos] = params[:repos]
redirect_to status_import_gitorious_path
end
def status
@repos = client.repos
@already_added_projects = current_user.created_projects.where(import_type: "gitorious")
already_added_projects_names = @already_added_projects.pluck(:import_source)
@repos.reject! { |repo| already_added_projects_names.include? repo.full_name }
end
def jobs
jobs = current_user.created_projects.where(import_type: "gitorious").to_json(only: [:id, :import_status])
render json: jobs
end
def create
@repo_id = params[:repo_id]
repo = client.repo(@repo_id)
@target_namespace = params[:new_namespace].presence || repo.namespace
@project_name = repo.name
namespace = get_or_create_namespace || (render and return)
@project = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, current_user).execute
end
private
def client
@client ||= Gitlab::GitoriousImport::Client.new(session[:gitorious_repos])
end
def verify_gitorious_import_enabled
render_404 unless gitorious_import_enabled?
end
end
...@@ -37,7 +37,7 @@ class JwtController < ApplicationController ...@@ -37,7 +37,7 @@ class JwtController < ApplicationController
def authenticate_project(login, password) def authenticate_project(login, password)
if login == 'gitlab-ci-token' if login == 'gitlab-ci-token'
Project.find_by(builds_enabled: true, runners_token: password) Project.with_builds_enabled.find_by(runners_token: password)
end end
end end
......
...@@ -14,7 +14,7 @@ class NamespacesController < ApplicationController ...@@ -14,7 +14,7 @@ class NamespacesController < ApplicationController
if user if user
redirect_to user_path(user) redirect_to user_path(user)
elsif group && can?(current_user, :read_group, namespace) elsif group && can?(current_user, :read_group, group)
redirect_to group_path(group) redirect_to group_path(group)
elsif current_user.nil? elsif current_user.nil?
authenticate_user! authenticate_user!
......
...@@ -88,6 +88,6 @@ class Projects::ApplicationController < ApplicationController ...@@ -88,6 +88,6 @@ class Projects::ApplicationController < ApplicationController
end end
def builds_enabled def builds_enabled
return render_404 unless @project.builds_enabled? return render_404 unless @project.feature_available?(:builds, current_user)
end end
end end
class Projects::ArtifactsController < Projects::ApplicationController class Projects::ArtifactsController < Projects::ApplicationController
include ExtractsPath
layout 'project' layout 'project'
before_action :authorize_read_build! before_action :authorize_read_build!
before_action :authorize_update_build!, only: [:keep] before_action :authorize_update_build!, only: [:keep]
before_action :extract_ref_name_and_path
before_action :validate_artifacts! before_action :validate_artifacts!
def download def download
unless artifacts_file.file_storage? if artifacts_file.file_storage?
return redirect_to artifacts_file.url send_file artifacts_file.path, disposition: 'attachment'
else
redirect_to artifacts_file.url
end end
send_file artifacts_file.path, disposition: 'attachment'
end end
def browse def browse
directory = params[:path] ? "#{params[:path]}/" : '' directory = params[:path] ? "#{params[:path]}/" : ''
@entry = build.artifacts_metadata_entry(directory) @entry = build.artifacts_metadata_entry(directory)
return render_404 unless @entry.exists? render_404 unless @entry.exists?
end end
def file def file
...@@ -34,14 +37,41 @@ class Projects::ArtifactsController < Projects::ApplicationController ...@@ -34,14 +37,41 @@ class Projects::ArtifactsController < Projects::ApplicationController
redirect_to namespace_project_build_path(project.namespace, project, build) redirect_to namespace_project_build_path(project.namespace, project, build)
end end
def latest_succeeded
target_path = artifacts_action_path(@path, project, build)
if target_path
redirect_to(target_path)
else
render_404
end
end
private private
def extract_ref_name_and_path
return unless params[:ref_name_and_path]
@ref_name, @path = extract_ref(params[:ref_name_and_path])
end
def validate_artifacts! def validate_artifacts!
render_404 unless build.artifacts? render_404 unless build && build.artifacts?
end end
def build def build
@build ||= project.builds.find_by!(id: params[:build_id]) @build ||= build_from_id || build_from_ref
end
def build_from_id
project.builds.find_by(id: params[:build_id]) if params[:build_id]
end
def build_from_ref
return unless @ref_name
builds = project.latest_successful_builds_for(@ref_name)
builds.find_by(name: params[:job])
end end
def artifacts_file def artifacts_file
......
...@@ -4,7 +4,7 @@ class Projects::AvatarsController < Projects::ApplicationController ...@@ -4,7 +4,7 @@ class Projects::AvatarsController < Projects::ApplicationController
before_action :authorize_admin_project!, only: [:destroy] before_action :authorize_admin_project!, only: [:destroy]
def show def show
@blob = @repository.blob_at_branch('master', @project.avatar_in_git) @blob = @repository.blob_at_branch(@repository.root_ref, @project.avatar_in_git)
if @blob if @blob
headers['X-Content-Type-Options'] = 'nosniff' headers['X-Content-Type-Options'] = 'nosniff'
......
...@@ -8,12 +8,15 @@ module Projects ...@@ -8,12 +8,15 @@ module Projects
issues = ::Boards::Issues::ListService.new(project, current_user, filter_params).execute issues = ::Boards::Issues::ListService.new(project, current_user, filter_params).execute
issues = issues.page(params[:page]) issues = issues.page(params[:page])
render json: issues.as_json( render json: {
only: [:iid, :title, :confidential], issues: issues.as_json(
include: { only: [:iid, :title, :confidential],
assignee: { only: [:id, :name, :username], methods: [:avatar_url] }, include: {
labels: { only: [:id, :title, :description, :color, :priority], methods: [:text_color] } assignee: { only: [:id, :name, :username], methods: [:avatar_url] },
}) labels: { only: [:id, :title, :description, :color, :priority], methods: [:text_color] }
}),
size: issues.total_count
}
end end
def update def update
......
...@@ -78,8 +78,8 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -78,8 +78,8 @@ class Projects::BuildsController < Projects::ApplicationController
end end
def raw def raw
if @build.has_trace? if @build.has_trace_file?
send_file @build.path_to_trace, type: 'text/plain; charset=utf-8', disposition: 'inline' send_file @build.trace_file_path, type: 'text/plain; charset=utf-8', disposition: 'inline'
else else
render_404 render_404
end end
......
...@@ -38,6 +38,6 @@ class Projects::DiscussionsController < Projects::ApplicationController ...@@ -38,6 +38,6 @@ class Projects::DiscussionsController < Projects::ApplicationController
end end
def module_enabled def module_enabled
render_404 unless @project.merge_requests_enabled render_404 unless @project.feature_available?(:merge_requests, current_user)
end end
end end
...@@ -201,7 +201,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -201,7 +201,7 @@ class Projects::IssuesController < Projects::ApplicationController
end end
def module_enabled def module_enabled
return render_404 unless @project.issues_enabled && @project.default_issues_tracker? return render_404 unless @project.feature_available?(:issues, current_user) && @project.default_issues_tracker?
end end
def redirect_to_external_issue_tracker def redirect_to_external_issue_tracker
...@@ -212,7 +212,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -212,7 +212,7 @@ class Projects::IssuesController < Projects::ApplicationController
if action_name == 'new' if action_name == 'new'
redirect_to external.new_issue_path redirect_to external.new_issue_path
else else
redirect_to external.issues_url redirect_to external.project_path
end end
end end
......
...@@ -99,7 +99,7 @@ class Projects::LabelsController < Projects::ApplicationController ...@@ -99,7 +99,7 @@ class Projects::LabelsController < Projects::ApplicationController
protected protected
def module_enabled def module_enabled
unless @project.issues_enabled || @project.merge_requests_enabled unless @project.feature_available?(:issues, current_user) || @project.feature_available?(:merge_requests, current_user)
return render_404 return render_404
end end
end end
......
...@@ -83,12 +83,22 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -83,12 +83,22 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def diffs def diffs
apply_diff_view_cookie! apply_diff_view_cookie!
@merge_request_diff = @merge_request.merge_request_diff @merge_request_diff =
if params[:diff_id]
@merge_request.merge_request_diffs.find(params[:diff_id])
else
@merge_request.merge_request_diff
end
respond_to do |format| respond_to do |format|
format.html { define_discussion_vars } format.html { define_discussion_vars }
format.json do format.json do
@diffs = @merge_request.diffs(diff_options) unless @merge_request_diff.latest?
# Disable comments if browsing older version of the diff
@diff_notes_disabled = true
end
@diffs = @merge_request_diff.diffs(diff_options)
render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") }
end end
...@@ -403,7 +413,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -403,7 +413,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def module_enabled def module_enabled
return render_404 unless @project.merge_requests_enabled return render_404 unless @project.feature_available?(:merge_requests, current_user)
end end
def validates_merge_request def validates_merge_request
......
...@@ -106,7 +106,7 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -106,7 +106,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end end
def module_enabled def module_enabled
unless @project.issues_enabled || @project.merge_requests_enabled unless @project.feature_available?(:issues, current_user) || @project.feature_available?(:merge_requests, current_user)
return render_404 return render_404
end end
end end
......
...@@ -94,7 +94,7 @@ class Projects::SnippetsController < Projects::ApplicationController ...@@ -94,7 +94,7 @@ class Projects::SnippetsController < Projects::ApplicationController
end end
def module_enabled def module_enabled
return render_404 unless @project.snippets_enabled return render_404 unless @project.feature_available?(:snippets, current_user)
end end
def snippet_params def snippet_params
......
class Projects::TagsController < Projects::ApplicationController class Projects::TagsController < Projects::ApplicationController
include SortingHelper
# Authorize # Authorize
before_action :require_non_empty_project before_action :require_non_empty_project
before_action :authorize_download_code! before_action :authorize_download_code!
...@@ -6,8 +8,10 @@ class Projects::TagsController < Projects::ApplicationController ...@@ -6,8 +8,10 @@ class Projects::TagsController < Projects::ApplicationController
before_action :authorize_admin_project!, only: [:destroy] before_action :authorize_admin_project!, only: [:destroy]
def index def index
@sort = params[:sort] || 'name' params[:sort] = params[:sort].presence || 'name'
@tags = @repository.tags_sorted_by(@sort)
@sort = params[:sort]
@tags = TagsFinder.new(@repository, params).execute
@tags = Kaminari.paginate_array(@tags).page(params[:page]) @tags = Kaminari.paginate_array(@tags).page(params[:page])
@releases = project.releases.where(tag: @tags.map(&:name)) @releases = project.releases.where(tag: @tags.map(&:name))
......
...@@ -303,13 +303,23 @@ class ProjectsController < Projects::ApplicationController ...@@ -303,13 +303,23 @@ class ProjectsController < Projects::ApplicationController
end end
def project_params def project_params
project_feature_attributes =
{
project_feature_attributes:
[
:issues_access_level, :builds_access_level,
:wiki_access_level, :merge_requests_access_level, :snippets_access_level
]
}
params.require(:project).permit( params.require(:project).permit(
:name, :path, :description, :issues_tracker, :tag_list, :runners_token, :name, :path, :description, :issues_tracker, :tag_list, :runners_token,
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :container_registry_enabled, :container_registry_enabled,
:issues_tracker_id, :default_branch, :issues_tracker_id, :default_branch,
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar,
:builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex,
:public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled :public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled,
:lfs_enabled, project_feature_attributes
) )
end end
......
...@@ -64,7 +64,7 @@ class IssuableFinder ...@@ -64,7 +64,7 @@ class IssuableFinder
if project? if project?
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
unless Ability.abilities.allowed?(current_user, :read_project, @project) unless Ability.allowed?(current_user, :read_project, @project)
@project = nil @project = nil
end end
else else
......
class TagsFinder
def initialize(repository, params)
@repository = repository
@params = params
end
def execute
tags = @repository.tags_sorted_by(sort)
filter_by_name(tags)
end
private
def sort
@params[:sort].presence
end
def search
@params[:search].presence
end
def filter_by_name(tags)
if search
tags.select { |tag| tag.name.include?(search) }
else
tags
end
end
end
...@@ -83,7 +83,7 @@ class TodosFinder ...@@ -83,7 +83,7 @@ class TodosFinder
if project? if project?
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
unless Ability.abilities.allowed?(current_user, :read_project, @project) unless Ability.allowed?(current_user, :read_project, @project)
@project = nil @project = nil
end end
else else
......
...@@ -110,7 +110,7 @@ module ApplicationHelper ...@@ -110,7 +110,7 @@ module ApplicationHelper
project = event.project project = event.project
# Skip if project repo is empty or MR disabled # Skip if project repo is empty or MR disabled
return false unless project && !project.empty_repo? && project.merge_requests_enabled return false unless project && !project.empty_repo? && project.feature_available?(:merge_requests, current_user)
# Skip if user already created appropriate MR # Skip if user already created appropriate MR
return false if project.merge_requests.where(source_branch: event.branch_name).opened.any? return false if project.merge_requests.where(source_branch: event.branch_name).opened.any?
......
...@@ -25,6 +25,11 @@ module CiStatusHelper ...@@ -25,6 +25,11 @@ module CiStatusHelper
end end
end end
def ci_status_for_statuseable(subject)
status = subject.try(:status) || 'not found'
status.humanize
end
def ci_icon_for_status(status) def ci_icon_for_status(status)
icon_name = icon_name =
case status case status
...@@ -41,7 +46,7 @@ module CiStatusHelper ...@@ -41,7 +46,7 @@ module CiStatusHelper
when 'play' when 'play'
'icon_play' 'icon_play'
when 'created' when 'created'
'icon_status_pending' 'icon_status_created'
else else
'icon_status_cancel' 'icon_status_cancel'
end end
...@@ -66,10 +71,10 @@ module CiStatusHelper ...@@ -66,10 +71,10 @@ module CiStatusHelper
Ci::Runner.shared.blank? Ci::Runner.shared.blank?
end end
def render_status_with_link(type, status, path = nil, tooltip_placement: 'auto left', cssclass: '') def render_status_with_link(type, status, path = nil, tooltip_placement: 'auto left', cssclass: '', container: 'body')
klass = "ci-status-link ci-status-icon-#{status.dasherize} #{cssclass}" klass = "ci-status-link ci-status-icon-#{status.dasherize} #{cssclass}"
title = "#{type.titleize}: #{ci_label_for_status(status)}" title = "#{type.titleize}: #{ci_label_for_status(status)}"
data = { toggle: 'tooltip', placement: tooltip_placement } data = { toggle: 'tooltip', placement: tooltip_placement, container: container }
if path if path
link_to ci_icon_for_status(status), path, link_to ci_icon_for_status(status), path,
......
...@@ -3,7 +3,7 @@ module CompareHelper ...@@ -3,7 +3,7 @@ module CompareHelper
from.present? && from.present? &&
to.present? && to.present? &&
from != to && from != to &&
project.merge_requests_enabled && project.feature_available?(:merge_requests, current_user) &&
project.repository.branch_names.include?(from) && project.repository.branch_names.include?(from) &&
project.repository.branch_names.include?(to) project.repository.branch_names.include?(to)
end end
......
...@@ -149,4 +149,20 @@ module GitlabRoutingHelper ...@@ -149,4 +149,20 @@ module GitlabRoutingHelper
def resend_invite_group_member_path(group_member, *args) def resend_invite_group_member_path(group_member, *args)
resend_invite_group_group_member_path(group_member.source, group_member) resend_invite_group_group_member_path(group_member.source, group_member)
end end
# Artifacts
def artifacts_action_path(path, project, build)
action, path_params = path.split('/', 2)
args = [project.namespace, project, build, path_params]
case action
when 'download'
download_namespace_project_build_artifacts_path(*args)
when 'browse'
browse_namespace_project_build_artifacts_path(*args)
when 'file'
file_namespace_project_build_artifacts_path(*args)
end
end
end end
...@@ -49,6 +49,19 @@ module IssuablesHelper ...@@ -49,6 +49,19 @@ module IssuablesHelper
end end
end end
def project_dropdown_label(project_id, default_label)
return default_label if project_id.nil?
return "Any project" if project_id == "0"
project = Project.find_by(id: project_id)
if project
project.name_with_namespace
else
default_label
end
end
def milestone_dropdown_label(milestone_title, default_label = "Milestone") def milestone_dropdown_label(milestone_title, default_label = "Milestone")
if milestone_title == Milestone::Upcoming.name if milestone_title == Milestone::Upcoming.name
milestone_title = Milestone::Upcoming.title milestone_title = Milestone::Upcoming.title
......
...@@ -23,10 +23,14 @@ module LfsHelper ...@@ -23,10 +23,14 @@ module LfsHelper
end end
def lfs_download_access? def lfs_download_access?
return false unless project.lfs_enabled?
project.public? || ci? || (user && user.can?(:download_code, project)) project.public? || ci? || (user && user.can?(:download_code, project))
end end
def lfs_upload_access? def lfs_upload_access?
return false unless project.lfs_enabled?
user && user.can?(:push_code, project) user && user.can?(:push_code, project)
end end
......
...@@ -98,6 +98,6 @@ module MergeRequestsHelper ...@@ -98,6 +98,6 @@ module MergeRequestsHelper
end end
def merge_request_button_visibility(merge_request, closed) def merge_request_button_visibility(merge_request, closed)
return 'hidden' if merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?) return 'hidden' if merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?) || merge_request.closed_without_fork?
end end
end end
...@@ -25,6 +25,8 @@ module NavHelper ...@@ -25,6 +25,8 @@ module NavHelper
current_path?('merge_requests#commits') || current_path?('merge_requests#commits') ||
current_path?('merge_requests#builds') || current_path?('merge_requests#builds') ||
current_path?('merge_requests#conflicts') || current_path?('merge_requests#conflicts') ||
current_path?('merge_requests#pipelines') ||
current_path?('issues#show') current_path?('issues#show')
if cookies[:collapsed_gutter] == 'true' if cookies[:collapsed_gutter] == 'true'
"page-gutter right-sidebar-collapsed" "page-gutter right-sidebar-collapsed"
......
...@@ -61,7 +61,9 @@ module ProjectsHelper ...@@ -61,7 +61,9 @@ module ProjectsHelper
project_link = link_to simple_sanitize(project.name), project_path(project), { class: "project-item-select-holder" } project_link = link_to simple_sanitize(project.name), project_path(project), { class: "project-item-select-holder" }
if current_user if current_user
project_link << icon("chevron-down", class: "dropdown-toggle-caret js-projects-dropdown-toggle", aria: { label: "Toggle switch project dropdown" }, data: { target: ".js-dropdown-menu-projects", toggle: "dropdown" }) project_link << button_tag(type: 'button', class: "dropdown-toggle-caret js-projects-dropdown-toggle", aria: { label: "Toggle switch project dropdown" }, data: { target: ".js-dropdown-menu-projects", toggle: "dropdown" }) do
icon("chevron-down")
end
end end
full_title = "#{namespace_link} / #{project_link}".html_safe full_title = "#{namespace_link} / #{project_link}".html_safe
...@@ -187,6 +189,18 @@ module ProjectsHelper ...@@ -187,6 +189,18 @@ module ProjectsHelper
nav_tabs.flatten nav_tabs.flatten
end end
def project_lfs_status(project)
if project.lfs_enabled?
content_tag(:span, class: 'lfs-enabled') do
'Enabled'
end
else
content_tag(:span, class: 'lfs-disabled') do
'Disabled'
end
end
end
def git_user_name def git_user_name
if current_user if current_user
current_user.name current_user.name
...@@ -400,4 +414,23 @@ module ProjectsHelper ...@@ -400,4 +414,23 @@ module ProjectsHelper
message.strip.gsub(project.repository_storage_path.chomp('/'), "[REPOS PATH]") message.strip.gsub(project.repository_storage_path.chomp('/'), "[REPOS PATH]")
end end
def project_feature_options
{
'Disabled' => ProjectFeature::DISABLED,
'Only team members' => ProjectFeature::PRIVATE,
'Everyone with access' => ProjectFeature::ENABLED
}
end
def project_feature_access_select(field)
# Don't show option "everyone with access" if project is private
options = project_feature_options
level = @project.project_feature.public_send(field)
options.delete('Everyone with access') if @project.private? && level != ProjectFeature::ENABLED
options = options_for_select(options, selected: @project.project_feature.public_send(field) || ProjectFeature::ENABLED)
content_tag(:select, options, name: "project[project_feature_attributes][#{field.to_s}]", id: "project_project_feature_attributes_#{field.to_s}", class: "pull-right form-control", data: { field: field }).html_safe
end
end end
...@@ -44,7 +44,7 @@ module SearchHelper ...@@ -44,7 +44,7 @@ module SearchHelper
def help_autocomplete def help_autocomplete
[ [
{ category: "Help", label: "API Help", url: help_page_path("api/README") }, { category: "Help", label: "API Help", url: help_page_path("api/README") },
{ category: "Help", label: "Markdown Help", url: help_page_path("markdown/markdown") }, { category: "Help", label: "Markdown Help", url: help_page_path("user/markdown") },
{ category: "Help", label: "Permissions Help", url: help_page_path("user/permissions") }, { category: "Help", label: "Permissions Help", url: help_page_path("user/permissions") },
{ category: "Help", label: "Public Access Help", url: help_page_path("public_access/public_access") }, { category: "Help", label: "Public Access Help", url: help_page_path("public_access/public_access") },
{ category: "Help", label: "Rake Tasks Help", url: help_page_path("raketasks/README") }, { category: "Help", label: "Rake Tasks Help", url: help_page_path("raketasks/README") },
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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