Commit f5b9837c authored by Timothy Andrew's avatar Timothy Andrew

Merge remote-tracking branch 'origin/master' into 21170-cycle-analytics

parents 72b9b87c 1d548869
...@@ -248,6 +248,21 @@ bundler:audit: ...@@ -248,6 +248,21 @@ bundler:audit:
script: script:
- "bundle exec bundle-audit check --update --ignore OSVDB-115941" - "bundle exec bundle-audit check --update --ignore OSVDB-115941"
migration paths:
stage: test
<<: *use-db
only:
- master@gitlab-org/gitlab-ce
script:
- git checkout HEAD .
- git fetch --tags
- git checkout v8.5.9
- 'echo test: unix:/var/opt/gitlab/redis/redis.socket > config/resque.yml'
- bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}" --retry=3
- rake db:drop db:create db:schema:load db:seed_fu
- git checkout $CI_BUILD_REF
- rake db:migrate
coverage: coverage:
stage: post-test stage: post-test
services: [] services: []
...@@ -263,7 +278,6 @@ coverage: ...@@ -263,7 +278,6 @@ coverage:
- coverage/index.html - coverage/index.html
- coverage/assets/ - coverage/assets/
# Notify slack in the end # Notify slack in the end
notify:slack: notify:slack:
......
### 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
......
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.12.0 (unreleased) v 8.12.0 (unreleased)
- Add ability to fork to a specific namespace using API. (ritave)
- Cleanup misalignments in Issue list view !6206
- Prepend blank line to `Closes` message on merge request linked to issue (lukehowell)
- Filter tags by name !6121
- Make push events have equal vertical spacing.
- Add two-factor recovery endpoint to internal API !5510 - Add two-factor recovery endpoint to internal API !5510
- Remove vendor prefixes for linear-gradient CSS (ClemMakesApps)
- Add font color contrast to external label in admin area (ClemMakesApps)
- Change logo animation to CSS (ClemMakesApps)
- Instructions for enabling Git packfile bitmaps !6104
- Fix pagination on user snippets page
- Change merge_error column from string to text type - Change merge_error column from string to text type
- Reduce contributions calendar data payload (ClemMakesApps) - Reduce contributions calendar data payload (ClemMakesApps)
- Add `web_url` field to issue, merge request, and snippet API objects (Ben Boeckel) - Add `web_url` field to issue, merge request, and snippet API objects (Ben Boeckel)
- Expose `sha` and `merge_commit_sha` in merge request API (Ben Boeckel)
- Set path for all JavaScript cookies to honor GitLab's subdirectory setting !5627 (Mike Greiling) - Set path for all JavaScript cookies to honor GitLab's subdirectory setting !5627 (Mike Greiling)
- Fix bug where pagination is still displayed despite all todos marked as done (ClemMakesApps)
- Center build stage columns in pipeline overview (ClemMakesApps)
- Rename behaviour to behavior in bug issue template for consistency (ClemMakesApps)
- Remove suggested colors hover underline (ClemMakesApps)
- Shorten task status phrase (ClemMakesApps)
- Add hover color to emoji icon (ClemMakesApps) - Add hover color to emoji icon (ClemMakesApps)
- Fix branches page dropdown sort alignment (ClemMakesApps)
- Add white background for no readme container (ClemMakesApps)
- API: Expose issue confidentiality flag. (Robert Schilling)
- Fix markdown anchor icon interaction (ClemMakesApps)
- Test migration paths from 8.5 until current release !4874
- Optimistic locking for Issues and Merge Requests (title and description overriding prevention) - Optimistic locking for Issues and Merge Requests (title and description overriding prevention)
- Add `wiki_page_events` to project hook APIs (Ben Boeckel) - Add `wiki_page_events` to project hook APIs (Ben Boeckel)
- Remove Gitorious import - Remove Gitorious import
- Fix inconsistent background color for filter input field (ClemMakesApps)
- Remove prefixes from transition CSS property (ClemMakesApps)
- Add Sentry logging to API calls - Add Sentry logging to API calls
- Add BroadcastMessage API
- Use 'git update-ref' for safer web commits !6130
- Automatically expand hidden discussions when accessed by a permalink !5585 (Mike Greiling) - Automatically expand hidden discussions when accessed by a permalink !5585 (Mike Greiling)
- Remove unused mixins (ClemMakesApps)
- Add search to all issue board lists
- Fix groups sort dropdown alignment (ClemMakesApps) - Fix groups sort dropdown alignment (ClemMakesApps)
- Add horizontal scrolling to all sub-navs on mobile viewports (ClemMakesApps)
- Use JavaScript tooltips for mentions !5301 (winniehell)
- Add hover state to todos !5361 (winniehell)
- Fix icon alignment of star and fork buttons !5451 (winniehell)
- Fix alignment of icon buttons !5887 (winniehell)
- Fix markdown help references (ClemMakesApps)
- Add last commit time to repo view (ClemMakesApps)
- Fix accessibility and visibility of project list dropdown button !6140
- Fix missing flash messages on service edit page (airatshigapov)
- Added project specific enable/disable setting for LFS !5997
- Don't expose a user's token in the `/api/v3/user` API (!6047)
- Remove redundant js-timeago-pending from user activity log (ClemMakesApps)
- Ability to manage project issues, snippets, wiki, merge requests and builds access level
- Remove inconsistent font weight for sidebar's labels (ClemMakesApps)
- Align add button on repository view (ClemMakesApps)
- Added tests for diff notes - Added tests for diff notes
- Add a button to download latest successful artifacts for branches and tags !5142
- Remove redundant pipeline tooltips (ClemMakesApps)
- Expire commit info views after one day, instead of two weeks, to allow for user email updates
- Add delimiter to project stars and forks count (ClemMakesApps) - Add delimiter to project stars and forks count (ClemMakesApps)
- Fix badge count alignment (ClemMakesApps) - Fix badge count alignment (ClemMakesApps)
- Remove green outline from `New branch unavailable` button on issue page !5858 (winniehell)
- Fix repo title alignment (ClemMakesApps)
- Fix branch title trailing space on hover (ClemMakesApps) - Fix branch title trailing space on hover (ClemMakesApps)
- Award emoji tooltips containing more than 10 usernames are now truncated !4780 (jlogandavison) - Award emoji tooltips containing more than 10 usernames are now truncated !4780 (jlogandavison)
- Fix duplicate "me" in award emoji tooltip !5218 (jlogandavison) - Fix duplicate "me" in award emoji tooltip !5218 (jlogandavison)
- Order award emoji tooltips in order they were added (EspadaV8)
- Fix spacing and vertical alignment on build status icon on commits page (ClemMakesApps) - Fix spacing and vertical alignment on build status icon on commits page (ClemMakesApps)
- Update merge_requests.md with a simpler way to check out a merge request. !5944 - Update merge_requests.md with a simpler way to check out a merge request. !5944
- Fix button missing type (ClemMakesApps) - Fix button missing type (ClemMakesApps)
- Move to project dropdown with infinite scroll for better performance - Move to project dropdown with infinite scroll for better performance
- Fix leaking of submit buttons outside the width of a main container !18731 (originally by @pavelloz)
- Load branches asynchronously in Cherry Pick and Revert dialogs. - Load branches asynchronously in Cherry Pick and Revert dialogs.
- Convert datetime coffeescript spec to ES6 (ClemMakesApps)
- Add merge request versions !5467 - Add merge request versions !5467
- Change using size to use count and caching it for number of group members. !5935 - Change using size to use count and caching it for number of group members. !5935
- Replace play icon font with svg (ClemMakesApps)
- Added 'only_allow_merge_if_build_succeeds' project setting in the API. !5930 (Duck) - Added 'only_allow_merge_if_build_succeeds' project setting in the API. !5930 (Duck)
- Reduce number of database queries on builds tab - Reduce number of database queries on builds tab
- Wrap text in commit message containers
- Capitalize mentioned issue timeline notes (ClemMakesApps) - Capitalize mentioned issue timeline notes (ClemMakesApps)
- Fix inconsistent checkbox alignment (ClemMakesApps)
- Use the default branch for displaying the project icon instead of master !5792 (Hannes Rosenögger) - Use the default branch for displaying the project icon instead of master !5792 (Hannes Rosenögger)
- Adds response mime type to transaction metric action when it's not HTML - Adds response mime type to transaction metric action when it's not HTML
- Fix hover leading space bug in pipeline graph !5980
v 8.11.3 (unreleased) - User can edit closed MR with deleted fork (Katarzyna Kobierska Ula Budziszewska) !5496
- Fix repository page ui issues
- Fixed invisible scroll controls on build page on iPhone
- Fix error on raw build trace download for old builds stored in database !4822
- Refactor the triggers page and documentation !6217
- Show values of CI trigger variables only when clicked (Katarzyna Kobierska Ula Budziszewska)
- Use default clone protocol on "check out, review, and merge locally" help page URL
v 8.11.5 (unreleased)
- Optimize branch lookups and force a repository reload for Repository#find_branch
- Fix member expiration date picker after update
- Fix suggested colors options for new labels in the admin area. !6138
- Fix GitLab import button
- Remove gitorious from import_sources
v 8.11.4
- Fix resolving conflicts on forks. !6082
- Fix diff commenting on merge requests created prior to 8.10. !6029
- Fix pipelines tab layout regression. !5952
- Fix "Wiki" link not appearing in navigation for projects with external wiki. !6057
- Do not enforce using hash with hidden key in CI configuration. !6079
- Fix hover leading space bug in pipeline graph !5980
- Fix sorting issues by "last updated" doesn't work after import from GitHub
- GitHub importer use default project visibility for non-private projects
- Creating an issue through our API now emails label subscribers !5720
- Block concurrent updates for Pipeline
- Don't create groups for unallowed users when importing projects
- Fix resolving conflicts on forks
- Fix diff commenting on merge requests created prior to 8.10
- Don't create groups for unallowed users when importing projects
- Scope webhooks/services that will run for confidential issues
- Fix issue boards leak private label names and descriptions
- Fix broken gitlab:backup:restore because of bad permissions on repo storage !6098 (Dirk Hörner)
- Remove gitorious. !5866
v 8.11.3
- Allow system info page to handle case where info is unavailable - Allow system info page to handle case where info is unavailable
- Label list shows all issues (opened or closed) with that label - Label list shows all issues (opened or closed) with that label
- Don't show resolve conflicts link before MR status is updated - Don't show resolve conflicts link before MR status is updated
- Fix IE11 fork button bug !5982
- Don't prevent viewing the MR when git refs for conflicts can't be found on disk - Don't prevent viewing the MR when git refs for conflicts can't be found on disk
- Fix external issue tracker "Issues" link leading to 404s - Fix external issue tracker "Issues" link leading to 404s
- Don't try to show merge conflict resolution info if a merge conflict contains non-UTF-8 characters
- Automatically expand hidden discussions when accessed by a permalink !5585 (Mike Greiling)
v 8.11.2 v 8.11.2
- Show "Create Merge Request" widget for push events to fork projects on the source project. !5978 - Show "Create Merge Request" widget for push events to fork projects on the source project. !5978
...@@ -106,8 +197,6 @@ v 8.11.0 ...@@ -106,8 +197,6 @@ v 8.11.0
- Update `timeago` plugin to use multiple string/locale settings - Update `timeago` plugin to use multiple string/locale settings
- Remove unused images (ClemMakesApps) - Remove unused images (ClemMakesApps)
- Get issue and merge request description templates from repositories - Get issue and merge request description templates from repositories
- Add hover state to todos !5361 (winniehell)
- Fix icon alignment of star and fork buttons !5451 (winniehell)
- Enforce 2FA restrictions on API authentication endpoints !5820 - Enforce 2FA restrictions on API authentication endpoints !5820
- Limit git rev-list output count to one in forced push check - Limit git rev-list output count to one in forced push check
- Show deployment status on merge requests with external URLs - Show deployment status on merge requests with external URLs
......
...@@ -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.6.3'
# 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'
......
...@@ -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.6.3)
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)
...@@ -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.6.3)
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)
......
...@@ -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
...@@ -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() {
......
(function(w) { (function(w) {
$(function() { $(function() {
$('.js-toggle-button').on('click', function(e) { $('body').on('click', '.js-toggle-button', function(e) {
e.preventDefault(); e.preventDefault();
$(this) $(this)
.find('.fa') .find('.fa')
......
...@@ -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) {
......
Vue.http.interceptors.push((request, next) => { Vue.http.interceptors.push((request, next) => {
Vue.activeResources = Vue.activeResources ? Vue.activeResources + 1 : 1; Vue.activeResources = Vue.activeResources ? Vue.activeResources + 1 : 1;
Vue.nextTick(() => { next(function (response) {
setTimeout(() => { Vue.activeResources--;
Vue.activeResources--;
}, 500);
}); });
next();
}); });
...@@ -54,12 +54,14 @@ ...@@ -54,12 +54,14 @@
} }
Build.prototype.getInitialBuildTrace = function() { Build.prototype.getInitialBuildTrace = function() {
var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped']
return $.ajax({ return $.ajax({
url: this.build_url, url: this.build_url,
dataType: 'json', dataType: 'json',
success: function(build_data) { success: function(build_data) {
$('.js-build-output').html(build_data.trace_html); $('.js-build-output').html(build_data.trace_html);
if (build_data.status === 'success' || build_data.status === 'failed') { if (removeRefreshStatuses.indexOf(build_data.status) >= 0) {
return $('.js-build-refresh').remove(); return $('.js-build-refresh').remove();
} }
} }
......
$(function(){
$('.reveal-variables').off('click').on('click',function(){
$('.js-build').toggle().niceScroll();
$(this).hide();
});
});
...@@ -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) {
......
...@@ -10,21 +10,24 @@ ...@@ -10,21 +10,24 @@
ImporterStatus.prototype.initStatusPage = function() { ImporterStatus.prototype.initStatusPage = function() {
$('.js-add-to-import').off('click').on('click', (function(_this) { $('.js-add-to-import').off('click').on('click', (function(_this) {
return function(e) { return function(e) {
var $btn, $namespace_input, $target_field, $tr, id, new_namespace; var $btn, $namespace_input, $target_field, $tr, id, target_namespace;
$btn = $(e.currentTarget); $btn = $(e.currentTarget);
$tr = $btn.closest('tr'); $tr = $btn.closest('tr');
$target_field = $tr.find('.import-target'); $target_field = $tr.find('.import-target');
$namespace_input = $target_field.find('input'); $namespace_input = $target_field.find('input');
id = $tr.attr('id').replace('repo_', ''); id = $tr.attr('id').replace('repo_', '');
new_namespace = null; target_namespace = null;
if ($namespace_input.length > 0) { if ($namespace_input.length > 0) {
new_namespace = $namespace_input.prop('value'); target_namespace = $namespace_input.prop('value');
$target_field.empty().append(new_namespace + "/" + ($target_field.data('project_name'))); $target_field.empty().append(target_namespace + "/" + ($target_field.data('project_name')));
} }
$btn.disable().addClass('is-loading'); $btn.disable().addClass('is-loading');
return $.post(_this.import_url, { return $.post(_this.import_url, {
repo_id: id, repo_id: id,
new_namespace: new_namespace target_namespace: target_namespace
}, { }, {
dataType: 'script' dataType: 'script'
}); });
...@@ -70,7 +73,7 @@ ...@@ -70,7 +73,7 @@
if ($('.js-importer-status').length) { if ($('.js-importer-status').length) {
var jobsImportPath = $('.js-importer-status').data('jobs-import-path'); var jobsImportPath = $('.js-importer-status').data('jobs-import-path');
var importPath = $('.js-importer-status').data('import-path'); var importPath = $('.js-importer-status').data('import-path');
new ImporterStatus(jobsImportPath, importPath); new ImporterStatus(jobsImportPath, importPath);
} }
}); });
......
...@@ -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) {
......
(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!');
}); });
} }
......
...@@ -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();
......
(global => {
global.gl = global.gl || {};
gl.SnippetsList = function() {
var $holder = $('.snippets-list-holder');
$holder.find('.pagination').on('ajax:success', (e, data) => {
$holder.replaceWith(data.html);
});
}
})(window);
...@@ -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();
$.cookie('hide_project_limit_message', 'false', { }
path: gon.relative_url_root || '/'
}); placeProfileAvatarsToTop() {
$(this).parents('.project-limit-message').remove(); $('.profile-groups-avatars').tooltip({
return e.preventDefault(); placement: 'top'
}); });
} }
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 = {}));
...@@ -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;
......
...@@ -183,6 +183,13 @@ ...@@ -183,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 {
...@@ -195,6 +202,12 @@ ...@@ -195,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;
} }
} }
...@@ -141,7 +138,7 @@ ...@@ -141,7 +138,7 @@
} }
li a { li a {
padding: 16px 10px 11px; padding: 16px 15px 11px;
} }
/* Small devices (phones, tablets, 768px and lower) */ /* Small devices (phones, tablets, 768px and lower) */
...@@ -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;
...@@ -35,6 +101,7 @@ $gl-icon-color: $gl-placeholder-color; ...@@ -35,6 +101,7 @@ $gl-icon-color: $gl-placeholder-color;
$gl-grayish-blue: #7f8fa4; $gl-grayish-blue: #7f8fa4;
$gl-gray: $gl-text-color; $gl-gray: $gl-text-color;
$gl-gray-dark: #313236; $gl-gray-dark: #313236;
$gl-gray-light: $gl-placeholder-color;
$gl-header-color: $gl-title-color; $gl-header-color: $gl-title-color;
/* /*
...@@ -90,73 +157,6 @@ $btn-side-margin: 10px; ...@@ -90,73 +157,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 +186,7 @@ $line-removed-dark: #fac5cd; ...@@ -186,7 +186,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 +267,7 @@ $zen-control-hover-color: #111; ...@@ -267,7 +267,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,13 +108,23 @@ ...@@ -107,13 +108,23 @@
} }
.blocks-container { .blocks-container {
padding: $gl-padding; padding: 0 $gl-padding;
} }
.block { .block {
width: 100%; width: 100%;
} }
.js-build-variable {
color: $code-color;
}
.js-build-value {
padding: 2px 4px;
color: $black;
background-color: $white-light;
}
.build-sidebar-header { .build-sidebar-header {
padding: 0 $gl-padding $gl-padding; padding: 0 $gl-padding $gl-padding;
...@@ -122,6 +133,13 @@ ...@@ -122,6 +133,13 @@
} }
} }
.retry-link {
color: $gl-link-color;
&:hover {
text-decoration: underline;
}
}
.stage-item { .stage-item {
cursor: pointer; cursor: pointer;
...@@ -131,7 +149,7 @@ ...@@ -131,7 +149,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,7 +163,6 @@ ...@@ -145,7 +163,6 @@
} }
.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;
......
...@@ -18,8 +18,7 @@ ...@@ -18,8 +18,7 @@
} }
.commit-row-title { .commit-row-title {
line-height: 1; line-height: 1.35;
margin-bottom: 7px;
.notes_count { .notes_count {
float: right; float: right;
...@@ -43,6 +42,7 @@ ...@@ -43,6 +42,7 @@
border: 1px solid $border-gray-dark; border: 1px solid $border-gray-dark;
border-radius: $border-radius-default; border-radius: $border-radius-default;
margin-left: 5px; margin-left: 5px;
line-height: 1;
&:hover { &:hover {
background-color: darken($gray-light, 10%); background-color: darken($gray-light, 10%);
...@@ -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;
...@@ -134,7 +136,7 @@ ...@@ -134,7 +136,7 @@
.commit-row-info { .commit-row-info {
color: $gl-gray; color: $gl-gray;
line-height: 1; line-height: 1.35;
a { a {
color: $gl-gray; color: $gl-gray;
......
...@@ -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;
} }
......
...@@ -9,9 +9,13 @@ ...@@ -9,9 +9,13 @@
.issue-check { .issue-check {
float: left; float: left;
padding-right: 8px; padding-right: 16px;
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),
......
...@@ -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;
}
}
} }
} }
...@@ -273,7 +278,7 @@ ...@@ -273,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;
...@@ -319,6 +324,14 @@ ...@@ -319,6 +324,14 @@
a { a {
color: $layout-link-gray; color: $layout-link-gray;
text-decoration: none;
&:hover {
.ci-status-text {
text-decoration: underline;
}
}
} }
} }
...@@ -334,9 +347,9 @@ ...@@ -334,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;
} }
} }
...@@ -356,22 +369,25 @@ ...@@ -356,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;
} }
} }
} }
...@@ -390,6 +406,12 @@ ...@@ -390,6 +406,12 @@
border: none; border: none;
} }
} }
// Remove opposite curve
.curve {
&::before {
display: none;
}
}
} }
} }
...@@ -401,6 +423,39 @@ ...@@ -401,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;
} }
} }
} }
...@@ -419,11 +474,22 @@ ...@@ -419,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: $gray-darkest;
} }
} }
...@@ -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,10 @@ ...@@ -11,6 +11,10 @@
} }
} }
.add-to-tree {
vertical-align: top;
}
.tree-table { .tree-table {
margin-bottom: 0; margin-bottom: 0;
...@@ -22,6 +26,15 @@ ...@@ -22,6 +26,15 @@
line-height: 21px; line-height: 21px;
} }
.last-commit {
@include str-truncated(60%);
}
.commit-history-link-spacer {
margin: 0 10px;
color: $table-border-color;
}
&:hover { &:hover {
td { td {
background-color: $row-hover; background-color: $row-hover;
...@@ -77,11 +90,17 @@ ...@@ -77,11 +90,17 @@
} }
} }
.tree_commit { .tree-time-ago {
color: $gl-gray; min-width: 135px;
color: $gl-gray-light;
}
.tree-commit {
max-width: 320px;
color: $gl-gray-light;
.tree-commit-link { .tree-commit-link {
color: $gl-gray; color: $gl-gray-light;
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
......
...@@ -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;
} }
......
...@@ -24,7 +24,7 @@ class ApplicationController < ActionController::Base ...@@ -24,7 +24,7 @@ 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?, :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|
...@@ -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!
......
...@@ -13,7 +13,7 @@ module ServiceParams ...@@ -13,7 +13,7 @@ module ServiceParams
# `issue_events` and `merge_request_events` (singular!) # `issue_events` and `merge_request_events` (singular!)
# See app/helpers/services_helper.rb for how we # See app/helpers/services_helper.rb for how we
# make those event names plural as special case. # make those event names plural as special case.
:issues_events, :merge_requests_events, :issues_events, :confidential_issues_events, :merge_requests_events,
:notify_only_broken_builds, :notify_only_broken_pipelines, :notify_only_broken_builds, :notify_only_broken_pipelines,
:add_pusher, :send_from_committer_email, :disable_diffs, :add_pusher, :send_from_committer_email, :disable_diffs,
:external_wiki_url, :notify, :color, :external_wiki_url, :notify, :color,
......
...@@ -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::BaseController < ApplicationController class Import::BaseController < ApplicationController
private private
def get_or_create_namespace def find_or_create_namespace(name, owner)
return current_user.namespace if name == owner
return current_user.namespace unless current_user.can_create_group?
begin begin
namespace = Group.create!(name: @target_namespace, path: @target_namespace, owner: current_user) name = params[:target_namespace].presence || name
namespace = Group.create!(name: name, path: name, owner: current_user)
namespace.add_owner(current_user) namespace.add_owner(current_user)
namespace
rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid
namespace = Namespace.find_by_path_or_name(@target_namespace) Namespace.find_by_path_or_name(name)
unless current_user.can?(:create_projects, namespace)
@already_been_taken = true
return false
end
end end
namespace
end end
end end
...@@ -35,23 +35,20 @@ class Import::BitbucketController < Import::BaseController ...@@ -35,23 +35,20 @@ class Import::BitbucketController < Import::BaseController
end end
def create def create
@repo_id = params[:repo_id] || "" @repo_id = params[:repo_id].to_s
repo = client.project(@repo_id.gsub("___", "/")) repo = client.project(@repo_id.gsub('___', '/'))
@project_name = repo["slug"] @project_name = repo['slug']
@target_namespace = find_or_create_namespace(repo['owner'], client.user['user']['username'])
repo_owner = repo["owner"]
repo_owner = current_user.username if repo_owner == client.user["user"]["username"]
@target_namespace = params[:new_namespace].presence || repo_owner
namespace = get_or_create_namespace || (render and return)
unless Gitlab::BitbucketImport::KeyAdder.new(repo, current_user, access_params).execute unless Gitlab::BitbucketImport::KeyAdder.new(repo, current_user, access_params).execute
@access_denied = true render 'deploy_key' and return
render
return
end end
@project = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute if current_user.can?(:create_projects, @target_namespace)
@project = Gitlab::BitbucketImport::ProjectCreator.new(repo, @target_namespace, current_user, access_params).execute
else
render 'unauthorized'
end
end end
private private
......
...@@ -41,14 +41,13 @@ class Import::GithubController < Import::BaseController ...@@ -41,14 +41,13 @@ class Import::GithubController < Import::BaseController
@repo_id = params[:repo_id].to_i @repo_id = params[:repo_id].to_i
repo = client.repo(@repo_id) repo = client.repo(@repo_id)
@project_name = repo.name @project_name = repo.name
@target_namespace = find_or_create_namespace(repo.owner.login, client.user.login)
repo_owner = repo.owner.login if current_user.can?(:create_projects, @target_namespace)
repo_owner = current_user.username if repo_owner == client.user.login @project = Gitlab::GithubImport::ProjectCreator.new(repo, @target_namespace, current_user, access_params).execute
@target_namespace = params[:new_namespace].presence || repo_owner else
render 'unauthorized'
namespace = get_or_create_namespace || (render and return) end
@project = Gitlab::GithubImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute
end end
private private
......
...@@ -26,15 +26,14 @@ class Import::GitlabController < Import::BaseController ...@@ -26,15 +26,14 @@ class Import::GitlabController < Import::BaseController
def create def create
@repo_id = params[:repo_id].to_i @repo_id = params[:repo_id].to_i
repo = client.project(@repo_id) repo = client.project(@repo_id)
@project_name = repo["name"] @project_name = repo['name']
@target_namespace = find_or_create_namespace(repo['namespace']['path'], client.user['username'])
repo_owner = repo["namespace"]["path"] if current_user.can?(:create_projects, @target_namespace)
repo_owner = current_user.username if repo_owner == client.user["username"] @project = Gitlab::GitlabImport::ProjectCreator.new(repo, @target_namespace, current_user, access_params).execute
@target_namespace = params[:new_namespace].presence || repo_owner else
render 'unauthorized'
namespace = get_or_create_namespace || (render and return) end
@project = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute
end end
private private
......
...@@ -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
......
...@@ -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
...@@ -59,6 +59,7 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -59,6 +59,7 @@ class Projects::HooksController < Projects::ApplicationController
:pipeline_events, :pipeline_events,
:enable_ssl_verification, :enable_ssl_verification,
:issues_events, :issues_events,
:confidential_issues_events,
:merge_requests_events, :merge_requests_events,
:note_events, :note_events,
:push_events, :push_events,
......
...@@ -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
......
...@@ -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
......
...@@ -413,7 +413,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -413,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
......
...@@ -20,9 +20,8 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -20,9 +20,8 @@ class Projects::ServicesController < Projects::ApplicationController
def update def update
if @service.update_attributes(service_params[:service]) if @service.update_attributes(service_params[:service])
redirect_to( redirect_to(
edit_namespace_project_service_path(@project.namespace, @project, edit_namespace_project_service_path(@project.namespace, @project, @service.to_param),
@service.to_param, notice: notice: 'Successfully updated.'
'Successfully updated.')
) )
else else
render 'edit' render 'edit'
......
...@@ -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
module ImportHelper module ImportHelper
def import_project_target(owner, name)
namespace = current_user.can_create_group? ? owner : current_user.namespace_path
"#{namespace}/#{name}"
end
def github_project_link(path_with_namespace) def github_project_link(path_with_namespace)
link_to path_with_namespace, github_project_url(path_with_namespace), target: '_blank' link_to path_with_namespace, github_project_url(path_with_namespace), target: '_blank'
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.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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