Commit 7e6dcf9c authored by Zeger-Jan van de Weg's avatar Zeger-Jan van de Weg

Merge branch 'master' into awardables

parents dccf8a9f 98d8e3fe
......@@ -115,6 +115,11 @@ bundler:audit:
script:
- "bundle exec bundle-audit check --update --ignore OSVDB-115941"
db-migrate-reset:
stage: test
script:
- RAILS_ENV=test bundle exec rake db:migrate:reset
# Ruby 2.2 jobs
spec:feature:ruby22:
......
......@@ -728,7 +728,7 @@ Metrics/ParameterLists:
# A complexity metric geared towards measuring complexity for a human reader.
Metrics/PerceivedComplexity:
Enabled: true
Max: 17
Max: 18
#################### Lint ################################
......@@ -953,10 +953,9 @@ Performance/DoubleStartEndWith:
Performance/EndWith:
Enabled: false
# TODO: Enable LstripRstrip Cop.
# Use `strip` instead of `lstrip.rstrip`.
Performance/LstripRstrip:
Enabled: false
Enabled: true
# TODO: Enable RangeInclude Cop.
# Use `Range#cover?` instead of `Range#include?`.
......
......@@ -65,7 +65,7 @@ linters:
# Reports when you have an empty rule set.
EmptyRule:
enabled: false
enabled: true
# Reports when you have an @extend directive.
ExtendDirective:
......@@ -244,11 +244,11 @@ linters:
# URLs should be valid and not contain protocols or domain names.
UrlFormat:
enabled: false
enabled: true
# URLs should always be enclosed within quotes.
UrlQuotes:
enabled: false
enabled: true
# Properties, like color and font, are easier to read and maintain
# when defined using variables rather than literals.
......
This diff is collapsed.
......@@ -38,7 +38,7 @@ source edition, and GitLab Enterprise Edition (EE) which is our commercial
edition. Throughout this guide you will see references to CE and EE for
abbreviation.
If you have read this guide and want to know how the GitLab [core team][core-team]
If you have read this guide and want to know how the GitLab [core team]
operates please see [the GitLab contributing process](PROCESS.md).
## Contributor license agreement
......@@ -135,12 +135,23 @@ For feature proposals for EE, open an issue on the
In order to help track the feature proposals, we have created a
[`feature proposal`][fpl] label. For the time being, users that are not members
of the project cannot add labels. You can instead ask one of the [core team][core-team]
members to add the label `feature proposal` to the issue.
of the project cannot add labels. You can instead ask one of the [core team]
members to add the label `feature proposal` to the issue or add the following
code snippet right after your description in a new line: `~"feature proposal"`.
Please keep feature proposals as small and simple as possible, complex ones
might be edited to make them small and simple.
You are encouraged to use the template below for feature proposals.
```
## Description including problem, use cases, benefits, and/or goals
## Proposal
## Links / references
```
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
discuss whether it is interesting to include this in GitLab.
......@@ -323,6 +334,7 @@ request is as follows:
[shell command guidelines](doc/development/shell_commands.md)
1. If your code creates new files on disk please read the
[shared files guidelines](doc/development/shared_files.md).
1. When writing commit messages please follow [these](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) [guidelines](http://chris.beams.io/posts/git-commit/).
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
......@@ -343,12 +355,11 @@ is it will be merged (quickly). After that you can send more MRs to enhance it.
For examples of feedback on merge requests please look at already
[closed merge requests][closed-merge-requests]. If you would like quick feedback
on your merge request feel free to mention one of the Merge Marshalls in the
[core team][core-team] or one of the
[Merge request coaches](https://about.gitlab.com/team/).
[core team] or one of the [Merge request coaches](https://about.gitlab.com/team/).
Please ensure that your merge request meets the contribution acceptance criteria.
When having your code reviewed and when reviewing merge requests please take the
[Thoughtbot code review guide] into account.
[code review guidelines](doc/development/code_review.md) into account.
### Merge request description format
......@@ -496,7 +507,7 @@ reported by emailing `contact@gitlab.com`.
This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
[core-team]: https://about.gitlab.com/core-team/
[core team]: https://about.gitlab.com/core-team/
[getting-help]: https://about.gitlab.com/getting-help/
[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up-for-grabs
......@@ -522,4 +533,3 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[gitlab-design]: https://gitlab.com/gitlab-org/gitlab-design
[free Antetype viewer (Mac OSX only)]: https://itunes.apple.com/us/app/antetype-viewer/id824152298?mt=12
[`gitlab1.atype` file]: https://gitlab.com/gitlab-org/gitlab-design/tree/master/gitlab1.atype/
[Thoughtbot code review guide]: https://github.com/thoughtbot/guides/tree/master/code-review
......@@ -19,8 +19,8 @@ gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries
gem 'devise', '~> 3.5.4'
gem 'doorkeeper', '~> 3.1'
gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.2.0'
gem 'omniauth', '~> 1.3.1'
gem 'omniauth-auth0', '~> 1.4.1'
gem 'omniauth-azure-oauth2', '~> 0.0.6'
......@@ -178,7 +178,7 @@ gem 'ruby-fogbugz', '~> 0.2.1'
gem 'd3_rails', '~> 3.5.0'
#cal-heatmap
gem 'cal-heatmap-rails', '~> 3.5.0'
gem 'cal-heatmap-rails', '~> 3.6.0'
# underscore-rails
gem "underscore-rails", "~> 1.8.0"
......@@ -190,6 +190,9 @@ gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input
gem "loofah", "~> 2.0.3"
# Working with license
gem 'licensee', '~> 8.0.0'
# Protect against bruteforcing
gem "rack-attack", '~> 4.3.1'
......@@ -214,7 +217,7 @@ gem 'font-awesome-rails', '~> 4.2'
gem 'gitlab_emoji', '~> 0.3.0'
gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 4.0.0'
gem 'jquery-rails', '~> 4.1.0'
gem 'jquery-scrollto-rails', '~> 1.4.3'
gem 'jquery-ui-rails', '~> 5.0.0'
gem 'raphael-rails', '~> 2.1.2'
......@@ -239,8 +242,7 @@ group :development do
gem "foreman"
gem 'brakeman', '~> 3.2.0', require: false
gem "annotate", "~> 2.7.0"
gem "letter_opener", '~> 1.1.2'
gem 'letter_opener_web', '~> 1.3.0'
gem 'quiet_assets', '~> 1.0.2'
gem 'rerun', '~> 0.11.0'
gem 'bullet', require: false
......@@ -267,7 +269,7 @@ group :development, :test do
gem 'database_cleaner', '~> 1.4.0'
gem 'factory_girl_rails', '~> 4.6.0'
gem 'rspec-rails', '~> 3.3.0'
gem 'rspec-rails', '~> 3.4.0'
gem 'rspec-retry'
gem 'spinach-rails', '~> 0.2.1'
gem 'spinach-rerun-reporter', '~> 0.0.2'
......@@ -315,9 +317,9 @@ end
gem "newrelic_rpm", '~> 3.14'
gem 'octokit', '~> 3.8.0'
gem 'octokit', '~> 4.3.0'
gem "mail_room", "~> 0.6.1"
gem "mail_room", "~> 0.7"
gem 'email_reply_parser', '~> 0.5.8'
......
......@@ -51,9 +51,6 @@ GEM
activerecord (>= 3.0)
akismet (2.0.0)
allocations (1.0.4)
annotate (2.7.0)
activerecord (>= 3.2, < 6.0)
rake (~> 10.4)
arel (6.0.3)
asana (0.4.0)
faraday (~> 0.9)
......@@ -103,7 +100,7 @@ GEM
bundler (~> 1.2)
thor (~> 0.18)
byebug (8.2.1)
cal-heatmap-rails (3.5.1)
cal-heatmap-rails (3.6.0)
capybara (2.6.2)
addressable
mime-types (>= 1.16)
......@@ -134,7 +131,7 @@ GEM
execjs
coffee-script-source (1.10.0)
colorize (0.7.7)
concurrent-ruby (1.0.0)
concurrent-ruby (1.0.2)
connection_pool (2.2.0)
coveralls (0.8.13)
json (~> 1.8)
......@@ -175,7 +172,7 @@ GEM
diff-lcs (1.2.5)
diffy (3.0.7)
docile (1.1.5)
doorkeeper (2.2.2)
doorkeeper (3.1.0)
railties (>= 3.2)
dropzonejs-rails (0.7.2)
rails (> 3.1)
......@@ -186,7 +183,7 @@ GEM
encryptor (1.3.0)
equalizer (0.0.11)
erubis (2.7.0)
escape_utils (1.1.0)
escape_utils (1.1.1)
eventmachine (1.0.8)
excon (0.45.4)
execjs (2.6.0)
......@@ -336,7 +333,7 @@ GEM
json
get_process_mem (0.2.0)
gherkin-ruby (0.3.2)
github-linguist (4.7.5)
github-linguist (4.7.6)
charlock_holmes (~> 0.7.3)
escape_utils (~> 1.1.0)
mime-types (>= 1.19)
......@@ -346,14 +343,14 @@ GEM
flowdock (~> 0.7)
gitlab-grit (>= 2.4.1)
multi_json
gitlab-grit (2.7.3)
gitlab-grit (2.8.1)
charlock_holmes (~> 0.6)
diff-lcs (~> 1.1)
mime-types (~> 1.15)
mime-types (>= 1.16, < 3)
posix-spawn (~> 0.3)
gitlab_emoji (0.3.1)
gemojione (~> 2.2, >= 2.2.1)
gitlab_git (10.0.0)
gitlab_git (10.1.0)
activesupport (~> 4.0)
charlock_holmes (~> 0.7.3)
github-linguist (~> 4.7.0)
......@@ -431,8 +428,8 @@ GEM
json
ipaddress (0.8.2)
jquery-atwho-rails (1.3.2)
jquery-rails (4.0.5)
rails-dom-testing (~> 1.0)
jquery-rails (4.1.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jquery-scrollto-rails (1.4.3)
......@@ -450,8 +447,14 @@ GEM
kgio (2.10.0)
launchy (2.4.3)
addressable (~> 2.3)
letter_opener (1.1.2)
letter_opener (1.4.1)
launchy (~> 2.2)
letter_opener_web (1.3.0)
actionmailer (>= 3.2)
letter_opener (~> 1.0)
railties (>= 3.2)
licensee (8.0.0)
rugged (>= 0.24b)
listen (3.0.5)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
......@@ -461,9 +464,9 @@ GEM
systemu (~> 2.6.2)
mail (2.6.4)
mime-types (>= 1.16, < 4)
mail_room (0.6.1)
mail_room (0.7.0)
method_source (0.8.2)
mime-types (1.25.1)
mime-types (2.99.1)
mimemagic (0.3.0)
mini_portile2 (2.0.0)
minitest (5.7.0)
......@@ -485,8 +488,8 @@ GEM
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (~> 1.2)
octokit (3.8.0)
sawyer (~> 0.6.0, >= 0.5.3)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
omniauth (1.3.1)
hashie (>= 1.2, < 4)
rack (>= 1.0, < 3)
......@@ -627,7 +630,7 @@ GEM
recaptcha (1.0.2)
json
redcarpet (3.3.3)
redis (3.2.2)
redis (3.3.0)
redis-actionpack (4.0.1)
actionpack (~> 4)
redis-rack (~> 1.5.0)
......@@ -658,29 +661,29 @@ GEM
chunky_png
rqrcode-rails3 (0.1.7)
rqrcode (>= 0.4.2)
rspec (3.3.0)
rspec-core (~> 3.3.0)
rspec-expectations (~> 3.3.0)
rspec-mocks (~> 3.3.0)
rspec-core (3.3.2)
rspec-support (~> 3.3.0)
rspec-expectations (3.3.1)
rspec (3.4.0)
rspec-core (~> 3.4.0)
rspec-expectations (~> 3.4.0)
rspec-mocks (~> 3.4.0)
rspec-core (3.4.4)
rspec-support (~> 3.4.0)
rspec-expectations (3.4.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.3.0)
rspec-mocks (3.3.2)
rspec-support (~> 3.4.0)
rspec-mocks (3.4.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.3.0)
rspec-rails (3.3.3)
rspec-support (~> 3.4.0)
rspec-rails (3.4.2)
actionpack (>= 3.0, < 4.3)
activesupport (>= 3.0, < 4.3)
railties (>= 3.0, < 4.3)
rspec-core (~> 3.3.0)
rspec-expectations (~> 3.3.0)
rspec-mocks (~> 3.3.0)
rspec-support (~> 3.3.0)
rspec-core (~> 3.4.0)
rspec-expectations (~> 3.4.0)
rspec-mocks (~> 3.4.0)
rspec-support (~> 3.4.0)
rspec-retry (0.4.5)
rspec-core
rspec-support (3.3.0)
rspec-support (3.4.1)
rubocop (0.38.0)
parser (>= 2.3.0.6, < 3.0)
powerpack (~> 0.1)
......@@ -712,8 +715,8 @@ GEM
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
sawyer (0.6.0)
addressable (~> 2.3.5)
sawyer (0.7.0)
addressable (>= 2.3.5, < 2.5)
faraday (~> 0.8, < 0.10)
scss_lint (0.47.1)
rake (>= 0.9, < 11)
......@@ -734,10 +737,9 @@ GEM
rack
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
sidekiq (4.0.1)
sidekiq (4.1.2)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
json (~> 1.0)
redis (~> 3.2, >= 3.2.1)
sidekiq-cron (0.4.0)
redis-namespace (>= 1.5.2)
......@@ -888,7 +890,6 @@ DEPENDENCIES
after_commit_queue
akismet (~> 2.0)
allocations (~> 1.0)
annotate (~> 2.7.0)
asana (~> 0.4.0)
asciidoctor (~> 1.5.2)
attr_encrypted (~> 1.3.4)
......@@ -903,7 +904,7 @@ DEPENDENCIES
bullet
bundler-audit
byebug
cal-heatmap-rails (~> 3.5.0)
cal-heatmap-rails (~> 3.6.0)
capybara (~> 2.6.2)
capybara-screenshot (~> 1.0.0)
carrierwave (~> 0.10.0)
......@@ -920,7 +921,7 @@ DEPENDENCIES
devise-async (~> 0.9.0)
devise-two-factor (~> 2.0.0)
diffy (~> 3.0.3)
doorkeeper (~> 2.2.0)
doorkeeper (~> 3.1)
dropzonejs-rails (~> 0.7.1)
email_reply_parser (~> 0.5.8)
email_spec (~> 1.6.0)
......@@ -951,14 +952,15 @@ DEPENDENCIES
httparty (~> 0.13.3)
influxdb (~> 0.2)
jquery-atwho-rails (~> 1.3.2)
jquery-rails (~> 4.0.0)
jquery-rails (~> 4.1.0)
jquery-scrollto-rails (~> 1.4.3)
jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 5.0.0)
kaminari (~> 0.16.3)
letter_opener (~> 1.1.2)
letter_opener_web (~> 1.3.0)
licensee (~> 8.0.0)
loofah (~> 2.0.3)
mail_room (~> 0.6.1)
mail_room (~> 0.7)
method_source (~> 0.8)
minitest (~> 5.7.0)
mousetrap-rails (~> 1.4.6)
......@@ -968,7 +970,7 @@ DEPENDENCIES
newrelic_rpm (~> 3.14)
nokogiri (~> 1.6.7, >= 1.6.7.2)
oauth2 (~> 1.0.0)
octokit (~> 3.8.0)
octokit (~> 4.3.0)
omniauth (~> 1.3.1)
omniauth-auth0 (~> 1.4.1)
omniauth-azure-oauth2 (~> 0.0.6)
......@@ -1008,7 +1010,7 @@ DEPENDENCIES
responders (~> 2.0)
rouge (~> 1.10.1)
rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.3.0)
rspec-rails (~> 3.4.0)
rspec-retry
rubocop (~> 0.38.0)
ruby-fogbugz (~> 0.2.1)
......@@ -1055,4 +1057,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
1.11.2
1.12.3
......@@ -59,7 +59,7 @@ core team members will mention this person.
Workflow labels are purposely not very detailed since that would be hard to keep
updated as you would need to re-evaluate them after every comment. We optionally
use functional labels on demand when want to group related issues to get an
use functional labels on demand when we want to group related issues to get an
overview (for example all issues related to RVM, to tackle them in one go) and
to add details to the issue.
......@@ -73,6 +73,7 @@ in support or comment for further detail. Do not use `feature request`.
- ~bug is an issue reporting undesirable or incorrect behavior.
- ~customer is an issue reported by enterprise subscribers. This label should
be accompanied by *bug* or *feature proposal* labels.
Example workflow: when a UX designer provided a design but it needs frontend work they remove the UX label and add the frontend label.
## Functional labels
......@@ -105,6 +106,25 @@ sensitive as to how you word things. Use Emoji to express your feelings (heart,
star, smile, etc.). Some good tips about giving feedback to merge requests is in
the [Thoughtbot code review guide].
## Feature Freeze
5 working days before the 22nd the stable branches for the upcoming release will
be frozen for major changes. Merge requests may still be merged into master
during this period. By freezing the stable branches prior to a release there's
no need to worry about last minute merge requests potentially breaking a lot of
things.
What is considered to be a major change is determined on a case by case basis as
this definition depends very much on the context of changes. For example, a 5
line change might have a big impact on the entire application. Ultimately the
decision will be made by those reviewing a merge request and the release
manager.
During the feature freeze all merge requests that are meant to go into the next
release should have the correct milestone assigned _and_ have the label
~"Pick into Stable" set. Merge requests without a milestone and this label will
not be merged into any stable branches.
## Copy & paste responses
### Improperly formatted issue
......
# GitLab
[![build status](https://ci.gitlab.com/projects/1/status.svg?ref=master)](https://ci.gitlab.com/projects/1?ref=master)
[![build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
[![Build Status](https://semaphoreci.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/400484/shields_badge.svg)](https://semaphoreci.com/gitlabhq/gitlabhq)
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
[![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.svg?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master)
......@@ -20,6 +20,10 @@ To see how GitLab looks please see the [features page on our website](https://ab
- Completely free and open source (MIT Expat license)
- Powered by [Ruby on Rails](https://github.com/rails/rails)
## Hiring
We're hiring developers, support people, and production engineers all the time, please see our [jobs page](https://about.gitlab.com/jobs/).
## Editions
There are two editions of GitLab:
......@@ -31,11 +35,11 @@ There are two editions of GitLab:
On [about.gitlab.com](https://about.gitlab.com/) you can find more information about:
- [Subscriptions](https://about.gitlab.com/subscription/)
- [Subscriptions](https://about.gitlab.com/pricing/)
- [Consultancy](https://about.gitlab.com/consultancy/)
- [Community](https://about.gitlab.com/community/)
- [Hosted GitLab.com](https://about.gitlab.com/gitlab-com/) use GitLab as a free service
- [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/) with additional features aimed at larger organizations.
- [GitLab Enterprise Edition](https://about.gitlab.com/features/#enterprise) with additional features aimed at larger organizations.
- [GitLab CI](https://about.gitlab.com/gitlab-ci/) a continuous integration (CI) server that is easy to integrate with GitLab.
## Requirements
......@@ -80,7 +84,7 @@ There are a lot of [third-party applications integrating with GitLab](https://ab
## GitLab release cycle
For more information about the release process see the [release documentation](http://doc.gitlab.com/ce/release/).
For more information about the release process see the [release documentation](https://gitlab.com/gitlab-org/release-tools/blob/master/README.md).
## Upgrading
......
8.7.0-pre
8.8.0-pre
......@@ -5,6 +5,7 @@
group_projects_path: "/api/:version/groups/:id/projects.json"
projects_path: "/api/:version/projects.json"
labels_path: "/api/:version/projects/:id/labels"
license_path: "/api/:version/licenses/:key"
group: (group_id, callback) ->
url = Api.buildUrl(Api.group_path)
......@@ -92,6 +93,16 @@
).done (projects) ->
callback(projects)
# Return text for a specific license
licenseText: (key, data, callback) ->
url = Api.buildUrl(Api.license_path).replace(':key', key)
$.ajax(
url: url
data: data
).done (license) ->
callback(license)
buildUrl: (url) ->
url = gon.relative_url_root + url if gon.relative_url_root?
return url.replace(':version', gon.api_version)
......@@ -174,7 +174,7 @@ $ ->
$('.trigger-submit').on 'change', ->
$(@).parents('form').submit()
gl.utils.localTimeAgo($('abbr.timeago, .js-timeago'), false)
gl.utils.localTimeAgo($('abbr.timeago, .js-timeago'), true)
# Flash
if (flash = $(".flash-container")).length > 0
......@@ -204,6 +204,7 @@ $ ->
$('.header-content .title').toggle()
$('.header-content .navbar-collapse').toggle()
$('.navbar-toggle').toggleClass('active')
$('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left")
# Show/hide comments on diff
$("body").on "click", ".js-toggle-diff-comments", (e) ->
......
......@@ -105,7 +105,7 @@ class @AwardsHandler
@postEmoji awardUrl, emoji, =>
@addAwardToEmojiBar(emoji)
$(".emoji-menu").removeClass "is-visible"
$('.emoji-menu').removeClass 'is-visible'
addAwardToEmojiBar: (emoji) ->
@addEmojiToFrequentlyUsedList(emoji)
......@@ -168,7 +168,7 @@ class @AwardsHandler
@resetTooltip(award_block)
resetTooltip: (award) ->
award.tooltip("destroy")
award.tooltip('destroy')
# "destroy" call is asynchronous and there is no appropriate callback on it, this is why we need to set timeout.
setTimeout (->
......@@ -194,13 +194,13 @@ class @AwardsHandler
$currentBlock.removeClass 'hidden'
resolveNameToCssClass: (emoji) ->
emoji_icon = $(".emoji-menu-content [data-emoji='#{emoji}']")
emojiIcon = $(".emoji-menu-content [data-emoji='#{emoji}']")
if emoji_icon.length > 0
unicodeName = emoji_icon.data("unicode-name")
if emojiIcon.length > 0
unicodeName = emojiIcon.data('unicode-name')
else
# Find by alias
unicodeName = $(".emoji-menu-content [data-aliases*=':#{emoji}:']").data("unicode-name")
unicodeName = $(".emoji-menu-content [data-aliases*=':#{emoji}:']").data('unicode-name')
"emoji-#{unicodeName}"
......@@ -217,45 +217,42 @@ class @AwardsHandler
scrollTop: $('.awards').offset().top - 80
}, 200)
normilizeEmojiName: (emoji) ->
@aliases[emoji] || emoji
addEmojiToFrequentlyUsedList: (emoji) ->
frequently_used_emojis = @getFrequentlyUsedEmojis()
frequently_used_emojis.push(emoji)
$.cookie('frequently_used_emojis', frequently_used_emojis.join(","), { expires: 365 })
frequentlyUsedEmojis = @getFrequentlyUsedEmojis()
frequentlyUsedEmojis.push(emoji)
$.cookie('frequently_used_emojis', frequentlyUsedEmojis.join(','), { expires: 365 })
getFrequentlyUsedEmojis: ->
frequently_used_emojis = ($.cookie('frequently_used_emojis') || "").split(",")
_.compact(_.uniq(frequently_used_emojis))
frequentlyUsedEmojis = ($.cookie('frequently_used_emojis') || '').split(',')
_.compact(_.uniq(frequentlyUsedEmojis))
renderFrequentlyUsedBlock: ->
if $.cookie('frequently_used_emojis')
frequently_used_emojis = @getFrequentlyUsedEmojis()
frequentlyUsedEmojis = @getFrequentlyUsedEmojis()
ul = $("<ul class='clearfix emoji-menu-list'>")
for emoji in frequently_used_emojis
$(".emoji-menu-content [data-emoji='#{emoji}']").closest("li").clone().appendTo(ul)
$("input.emoji-search").after(ul).after($("<h5>").text("Frequently used"))
$('input.emoji-search').after(ul).after($('<h5>').text('Frequently used'))
setupSearch: ->
$("input.emoji-search").on 'keyup', (ev) =>
$('input.emoji-search').keyup (ev) =>
term = $(ev.target).val()
# Clean previous search results
$("ul.emoji-menu-search, h5.emoji-search").remove()
$('ul.emoji-menu-search, h5.emoji-search').remove()
if term
# Generate a search result block
h5 = $("<h5>").text("Search results").addClass("emoji-search")
found_emojis = @searchEmojis(term).show()
ul = $("<ul>").addClass("emoji-menu-list emoji-menu-search").append(found_emojis)
$(".emoji-menu-content ul, .emoji-menu-content h5").hide()
$(".emoji-menu-content").append(h5).append(ul)
h5 = $('<h5>').text('Search results').addClass('emoji-search')
foundEmojis = @searchEmojis(term).show()
ul = $('<ul>').addClass('emoji-menu-list emoji-menu-search').append(foundEmojis)
$('.emoji-menu-content ul, .emoji-menu-content h5').hide()
$('.emoji-menu-content').append(h5).append(ul)
else
$(".emoji-menu-content").children().show()
$('.emoji-menu-content').children().show()
searchEmojis: (term)->
$(".emoji-menu-content [data-emoji*='#{term}']").closest("li").clone()
class @BlobLicenseSelector
licenseRegex: /^(.+\/)?(licen[sc]e|copying)($|\.)/i
constructor: (editor) ->
@$licenseSelector = $('.js-license-selector')
$fileNameInput = $('#file_name')
initialFileNameValue = if $fileNameInput.length
$fileNameInput.val()
else if $('.editor-file-name').length
$('.editor-file-name').text().trim()
@toggleLicenseSelector(initialFileNameValue)
if $fileNameInput
$fileNameInput.on 'keyup blur', (e) =>
@toggleLicenseSelector($(e.target).val())
$('select.license-select').on 'change', (e) ->
data =
project: $(this).data('project')
fullname: $(this).data('fullname')
Api.licenseText $(this).val(), data, (license) ->
editor.setValue(license.content, -1)
toggleLicenseSelector: (fileName) =>
if @licenseRegex.test(fileName)
@$licenseSelector.show()
else
@$licenseSelector.hide()
class @EditBlob
constructor: (assets_path, mode)->
ace.config.set "modePath", assets_path + '/ace'
constructor: (assets_path, ace_mode = null) ->
ace.config.set "modePath", "#{assets_path}/ace"
ace.config.loadModule "ace/ext/searchbox"
if mode
ace_mode = mode
editor = ace.edit("editor")
editor.focus()
@editor = editor
if ace_mode
editor.getSession().setMode "ace/mode/" + ace_mode
@editor = ace.edit("editor")
@editor.focus()
@editor.getSession().setMode "ace/mode/#{ace_mode}" if ace_mode
# Before a form submission, move the content from the Ace editor into the
# submitted textarea
$('form').submit ->
$("#file-content").val(editor.getValue())
$('form').submit =>
$("#file-content").val(@editor.getValue())
@initModePanesAndLinks()
new BlobLicenseSelector(@editor)
editModePanes = $(".js-edit-mode-pane")
editModeLinks = $(".js-edit-mode a")
editModeLinks.click (event) ->
event.preventDefault()
currentLink = $(this)
paneId = currentLink.attr("href")
currentPane = editModePanes.filter(paneId)
editModeLinks.parent().removeClass "active hover"
currentLink.parent().addClass "active hover"
editModePanes.hide()
if paneId is "#preview"
currentPane.fadeIn 200
$.post currentLink.data("preview-url"),
content: editor.getValue()
, (response) ->
currentPane.empty().append response
currentPane.syntaxHighlight()
return
initModePanesAndLinks: ->
@$editModePanes = $(".js-edit-mode-pane")
@$editModeLinks = $(".js-edit-mode a")
@$editModeLinks.click @editModeLinkClickHandler
else
currentPane.fadeIn 200
editor.focus()
return
editModeLinkClickHandler: (event) =>
event.preventDefault()
currentLink = $(event.target)
paneId = currentLink.attr("href")
currentPane = @$editModePanes.filter(paneId)
@$editModeLinks.parent().removeClass "active hover"
currentLink.parent().addClass "active hover"
@$editModePanes.hide()
currentPane.fadeIn 200
if paneId is "#preview"
$.post currentLink.data("preview-url"),
content: @editor.getValue()
, (response) ->
currentPane.empty().append response
currentPane.syntaxHighlight()
editor: ->
return @editor
else
@editor.focus()
class @NewBlob
constructor: (assets_path, mode)->
ace.config.set "modePath", assets_path + '/ace'
ace.config.loadModule "ace/ext/searchbox"
if mode
ace_mode = mode
editor = ace.edit("editor")
editor.focus()
@editor = editor
if ace_mode
editor.getSession().setMode "ace/mode/" + ace_mode
# Before a form submission, move the content from the Ace editor into the
# submitted textarea
$('form').submit ->
$("#file-content").val(editor.getValue())
editor: ->
return @editor
class @CommitsList
@timer = null
@init: (ref, limit) ->
@init: (limit) ->
$("body").on "click", ".day-commits-table li.commit", (event) ->
if event.target.nodeName != "A"
location.href = $(this).attr("url")
......
......@@ -17,6 +17,7 @@ class Dispatcher
switch page
when 'projects:issues:index'
Issues.init()
Issuable.init()
shortcut_handler = new ShortcutsNavigation()
when 'projects:issues:show'
new Issue()
......@@ -59,7 +60,7 @@ class Dispatcher
new ZenMode()
when 'projects:merge_requests:index'
shortcut_handler = new ShortcutsNavigation()
MergeRequests.init()
Issuable.init()
when 'dashboard:activity'
new Activities()
when 'dashboard:projects:starred'
......@@ -109,6 +110,8 @@ class Dispatcher
new BuildArtifacts()
when 'projects:group_links:index'
new GroupsSelect()
when 'search:show'
new Search()
switch path.first()
when 'admin'
......
......@@ -61,6 +61,7 @@ class @DropzoneInput
return
drop: ->
$mdArea.removeClass 'is-dropzone-hover'
form.find(".div-dropzone-hover").css "opacity", 0
form_textarea.focus()
return
......
class @DueDateSelect
constructor: ->
$loading = $('.js-issuable-update .due_date')
.find('.block-loading')
.hide()
$('.js-due-date-select').each (i, dropdown) ->
$dropdown = $(dropdown)
$dropdownParent = $dropdown.closest('.dropdown')
$datePicker = $dropdownParent.find('.js-due-date-calendar')
$block = $dropdown.closest('.block')
$selectbox = $dropdown.closest('.selectbox')
$value = $block.find('.value')
$sidebarValue = $('.js-due-date-sidebar-value', $block)
fieldName = $dropdown.data('field-name')
abilityName = $dropdown.data('ability-name')
issueUpdateURL = $dropdown.data('issue-update')
$dropdown.glDropdown(
hidden: ->
$selectbox.hide()
$value.removeAttr('style')
)
addDueDate = ->
# Create the post date
value = $("input[name='#{fieldName}']").val()
date = new Date value.replace(new RegExp('-', 'g'), ',')
mediumDate = $.datepicker.formatDate 'M d, yy', date
data = {}
data[abilityName] = {}
data[abilityName].due_date = value
$.ajax(
type: 'PUT'
url: issueUpdateURL
data: data
beforeSend: ->
$loading.fadeIn()
$dropdown.trigger('loading.gl.dropdown')
$selectbox.hide()
$value.removeAttr('style')
$value.html(mediumDate)
$sidebarValue.html(mediumDate)
).done (data) ->
$dropdown.trigger('loaded.gl.dropdown')
$dropdown.dropdown('toggle')
$loading.fadeOut()
$datePicker.datepicker(
dateFormat: 'yy-mm-dd',
defaultDate: $("input[name='#{fieldName}']").val()
altField: "input[name='#{fieldName}']"
onSelect: ->
addDueDate()
)
$(document)
.off 'click', '.ui-datepicker-header a'
.on 'click', '.ui-datepicker-header a', (e) ->
e.stopImmediatePropagation()
......@@ -32,10 +32,8 @@ class GitLabDropdownFilter
else if @input.val() is "" and $inputContainer.hasClass HAS_VALUE_CLASS
$inputContainer.removeClass HAS_VALUE_CLASS
if keyCode is 13 and @input.val() isnt ""
if @options.enterCallback
@options.enterCallback()
return
if keyCode is 13
return false
clearTimeout timeout
timeout = setTimeout =>
......@@ -132,7 +130,6 @@ class GitLabDropdown
@filterInput = @getElement(FILTER_INPUT)
@highlight = false
@filterInputBlur = true
@enterCallback = true
} = @options
self = @
......@@ -157,6 +154,9 @@ class GitLabDropdown
@fullData = data
@parseData @fullData
if @options.filterable
@filterInput.trigger 'keyup'
}
# Init filterable
......@@ -178,15 +178,15 @@ class GitLabDropdown
callback: (data) =>
currentIndex = -1
@parseData data
enterCallback: =>
if @enterCallback
@selectRowAtIndex 0
# Event listeners
@dropdown.on "shown.bs.dropdown", @opened
@dropdown.on "hidden.bs.dropdown", @hidden
@dropdown.on "click", ".dropdown-menu, .dropdown-menu-close", @shouldPropagate
@dropdown.on 'keyup', (e) =>
if e.which is 27 # Escape key
$('.dropdown-menu-close', @dropdown).trigger 'click'
if @dropdown.find(".dropdown-toggle-page").length
@dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on "click", (e) =>
......@@ -224,6 +224,9 @@ class GitLabDropdown
menu.toggleClass PAGE_TWO_CLASS
# Focus first visible input on active page
@dropdown.find('[class^="dropdown-page-"]:visible :text:visible:first').focus()
parseData: (data) ->
@renderedData = data
......@@ -243,7 +246,8 @@ class GitLabDropdown
shouldPropagate: (e) =>
if @options.multiSelect
$target = $(e.target)
if not $target.hasClass('dropdown-menu-close') and not $target.hasClass('dropdown-menu-close-icon')
if not $target.hasClass('dropdown-menu-close') and not $target.hasClass('dropdown-menu-close-icon') and not $target.data('is-link')
e.stopPropagation()
return false
else
......@@ -378,7 +382,6 @@ class GitLabDropdown
selectedObject = @renderedData[selectedIndex]
value = if @options.id then @options.id(selectedObject, el) else selectedObject.id
field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']")
if el.hasClass(ACTIVE_CLASS)
el.removeClass(ACTIVE_CLASS)
field.remove()
......@@ -389,13 +392,13 @@ class GitLabDropdown
else
selectedObject
else
if !value?
field.remove()
if not @options.multiSelect
if not @options.multiSelect or el.hasClass('dropdown-clear-active')
@dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS
@dropdown.parent().find("input[name='#{fieldName}']").remove()
if !value?
field.remove()
# Toggle active class for the tick mark
el.addClass ACTIVE_CLASS
......
......@@ -4,18 +4,33 @@ class @ImporterStatus
this.setAutoUpdate()
initStatusPage: ->
$(".js-add-to-import").click (event) =>
new_namespace = null
tr = $(event.currentTarget).closest("tr")
id = tr.attr("id").replace("repo_", "")
if tr.find(".import-target input").length > 0
new_namespace = tr.find(".import-target input").prop("value")
tr.find(".import-target").empty().append(new_namespace + "/" + tr.find(".import-target").data("project_name"))
$.post @import_url, {repo_id: id, new_namespace: new_namespace}, dataType: 'script'
$(".js-import-all").click (event) =>
$(".js-add-to-import").each ->
$(this).click()
$('.js-add-to-import')
.off 'click'
.on 'click', (e) =>
new_namespace = null
$btn = $(e.currentTarget)
$tr = $btn.closest('tr')
id = $tr.attr('id').replace('repo_', '')
if $tr.find('.import-target input').length > 0
new_namespace = $tr.find('.import-target input').prop('value')
$tr.find('.import-target').empty().append("#{new_namespace} / #{$tr.find('.import-target').data('project_name')}")
$btn
.disable()
.addClass 'is-loading'
$.post @import_url, {repo_id: id, new_namespace: new_namespace}, dataType: 'script'
$('.js-import-all')
.off 'click'
.on 'click', (e) ->
$btn = $(@)
$btn
.disable()
.addClass 'is-loading'
$('.js-add-to-import').each ->
$(this).trigger('click')
setAutoUpdate: ->
setInterval (=>
......
@Issuable =
init: ->
Issuable.initTemplates()
Issuable.initSearch()
initTemplates: ->
Issuable.labelRow = _.template(
'<% _.each(labels, function(label){ %>
<span class="label-row">
<a href="#"><span class="label color-label has-tooltip" style="background-color: <%= label.color %>; color: <%= label.text_color %>" title="<%= _.escape(label.description) %>" data-container="body"><%= _.escape(label.title) %></span></a>
</span>
<% }); %>'
)
initSearch: ->
@timer = null
$('#issue_search')
.off 'keyup'
.on 'keyup', ->
clearTimeout(@timer)
@timer = setTimeout( ->
Issuable.filterResults $('#issue_search_form')
, 500)
toggleLabelFilters: ->
$filteredLabels = $('.filtered-labels')
if $filteredLabels.find('.label-row').length > 0
$filteredLabels.removeClass('hidden')
else
$filteredLabels.addClass('hidden')
filterResults: (form) =>
formData = form.serialize()
$('.issues-holder, .merge-requests-holder').css('opacity', '0.5')
formAction = form.attr('action')
issuesUrl = formAction
issuesUrl += ("#{if formAction.indexOf('?') < 0 then '?' else '&'}")
issuesUrl += formData
$.ajax
type: 'GET'
url: formAction
data: formData
complete: ->
$('.issues-holder, .merge-requests-holder').css('opacity', '1.0')
success: (data) ->
$('.issues-holder, .merge-requests-holder').html(data.html)
# Change url so if user reload a page - search results are saved
history.replaceState {page: issuesUrl}, document.title, issuesUrl
Issuable.reload()
Issuable.updateStateFilters()
$filteredLabels = $('.filtered-labels')
if typeof Issuable.labelRow is 'function'
$filteredLabels.html(Issuable.labelRow(data))
Issuable.toggleLabelFilters()
dataType: "json"
reload: ->
if Issues.created
Issues.initChecks()
$('#filter_issue_search').val($('#issue_search').val())
updateStateFilters: ->
stateFilters = $('.issues-state-filters')
newParams = {}
paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search']
for paramKey in paramKeys
newParams[paramKey] = gl.utils.getParameterValues(paramKey)[0] or ''
if stateFilters.length
stateFilters.find('a').each ->
initialUrl = gl.utils.removeParamQueryString($(this).attr('href'), 'label_name[]')
labelNameValues = gl.utils.getParameterValues('label_name[]')
if labelNameValues
labelNameQueryString = ("label_name[]=#{value}" for value in labelNameValues).join('&')
newUrl = "#{gl.utils.mergeUrlParams(newParams, initialUrl)}&#{labelNameQueryString}"
else
newUrl = gl.utils.mergeUrlParams(newParams, initialUrl)
$(this).attr 'href', newUrl
......@@ -9,21 +9,29 @@ class @IssuableContext
$(".issuable-sidebar .inline-update").on "change", ".js-assignee", ->
$(this).submit()
$(document).off("click", ".edit-link").on "click",".edit-link", (e) ->
$block = $(@).parents('.block')
$selectbox = $block.find('.selectbox')
if $selectbox.is(':visible')
$selectbox.hide()
$block.find('.value').show()
else
$selectbox.show()
$block.find('.value').hide()
if $selectbox.is(':visible')
setTimeout (->
$block.find('.dropdown-menu-toggle').trigger 'click'
), 0
$(document)
.off 'click', '.issuable-sidebar .dropdown-content a'
.on 'click', '.issuable-sidebar .dropdown-content a', (e) ->
e.preventDefault()
$(document)
.off 'click', '.edit-link'
.on 'click', '.edit-link', (e) ->
e.preventDefault()
$block = $(@).parents('.block')
$selectbox = $block.find('.selectbox')
if $selectbox.is(':visible')
$selectbox.hide()
$block.find('.value').show()
else
$selectbox.show()
$block.find('.value').hide()
if $selectbox.is(':visible')
setTimeout ->
$block.find('.dropdown-menu-toggle').trigger 'click'
, 0
$(".right-sidebar").niceScroll()
......
......@@ -12,6 +12,7 @@ class @Issue
@initMergeRequests()
@initRelatedBranches()
@initCanCreateBranch()
initTaskList: ->
$('.detail-page-description .js-task-list-container').taskList('enable')
......@@ -92,3 +93,25 @@ class @Issue
.success (data) ->
if 'html' of data
$container.html(data.html)
initCanCreateBranch: ->
$container = $('div#new-branch')
# If the user doesn't have the required permissions the container isn't
# rendered at all.
return unless $container
$.getJSON($container.data('path'))
.error ->
$container.find('.checking').hide()
$container.find('.unavailable').show()
new Flash('Failed to check if a new branch can be created.', 'alert')
.success (data) ->
if data.can_create_branch
$container.find('.checking').hide()
$container.find('.available').show()
$container.find('a').attr('disabled', false)
else
$container.find('.checking').hide()
$container.find('.unavailable').show()
@Issues =
init: ->
Issues.initSearch()
Issues.created = true
Issues.initChecks()
$("body").on "ajax:success", ".close_issue, .reopen_issue", ->
......@@ -15,10 +15,6 @@
else
$(this).html totalIssues - 1
reload: ->
Issues.initChecks()
$('#filter_issue_search').val($('#issue_search').val())
initChecks: ->
$(".check_all_issues").click ->
$(".selected_issue").prop("checked", @checked)
......@@ -26,51 +22,6 @@
$(".selected_issue").bind "change", Issues.checkChanged
# Update state filters if present in page
updateStateFilters: ->
stateFilters = $('.issues-state-filters')
newParams = {}
paramKeys = ['author_id', 'label_name', 'milestone_title', 'assignee_id', 'issue_search']
for paramKey in paramKeys
newParams[paramKey] = gl.utils.getUrlParameter(paramKey) or ''
if stateFilters.length
stateFilters.find('a').each ->
initialUrl = $(this).attr 'href'
$(this).attr 'href', gl.utils.mergeUrlParams(newParams, initialUrl)
# Make sure we trigger ajax request only after user stop typing
initSearch: ->
@timer = null
$("#issue_search").keyup ->
clearTimeout(@timer)
@timer = setTimeout( ->
Issues.filterResults $("#issue_search_form")
, 500)
filterResults: (form) =>
$('.issues-holder, .merge-requests-holder').css("opacity", '0.5')
formAction = form.attr('action')
formData = form.serialize()
issuesUrl = formAction
issuesUrl += ("#{if formAction.indexOf("?") < 0 then '?' else '&'}")
issuesUrl += formData
$.ajax
type: "GET"
url: formAction
data: formData
complete: ->
$('.issues-holder, .merge-requests-holder').css("opacity", '1.0')
success: (data) ->
$('.issues-holder, .merge-requests-holder').html(data.html)
# Change url so if user reload a page - search results are saved
history.replaceState {page: issuesUrl}, document.title, issuesUrl
Issues.reload()
Issues.updateStateFilters()
dataType: "json"
checkChanged: ->
checked_issues = $(".selected_issue:checked")
if checked_issues.length > 0
......
((w) ->
if not w.gl? then w.gl = {}
if not gl.animate? then gl.animate = {}
w.glAnimate = ($el, animation, done) ->
gl.animate.animate = ($el, animation, options, done) ->
if options?.cssStart?
$el.css(options.cssStart)
$el
.removeClass()
.removeClass(animation + ' animated')
.addClass(animation + ' animated')
.one 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', ->
$(this).removeClass()
$(this).removeClass(animation + ' animated')
if done?
done()
if options?.cssEnd?
$el.css(options.cssEnd)
return
return
return
gl.animate.animateEach = ($els, animation, time, options, done) ->
dfd = $.Deferred()
if not $els.length
dfd.resolve()
$els.each((i) ->
setTimeout(=>
$this = $(@)
gl.animate.animate($this, animation, options, =>
if i is $els.length - 1
dfd.resolve()
if done?
done()
)
,time * i
)
return
)
return dfd.promise()
return
) window
\ No newline at end of file
......@@ -3,16 +3,20 @@
w.gl ?= {}
w.gl.utils ?= {}
w.gl.utils.getUrlParameter = (sParam) ->
# Returns an array containing the value(s) of the
# of the key passed as an argument
w.gl.utils.getParameterValues = (sParam) ->
sPageURL = decodeURIComponent(window.location.search.substring(1))
sURLVariables = sPageURL.split('&')
sParameterName = undefined
values = []
i = 0
while i < sURLVariables.length
sParameterName = sURLVariables[i].split('=')
if sParameterName[0] is sParam
return if sParameterName[1] is undefined then true else sParameterName[1]
values.push(sParameterName[1])
i++
values
# #
# @param {Object} params - url keys and value to merge
......@@ -28,4 +32,12 @@
newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}"
newUrl
# removes parameter query string from url. returns the modified url
w.gl.utils.removeParamQueryString = (url, param) ->
url = decodeURIComponent(url)
urlVariables = url.split('&')
(
variables for variables in urlVariables when variables.indexOf(param) is -1
).join('&')
) window
......@@ -87,8 +87,8 @@ class @MergeRequestTabs
if window.location.hash
navBarHeight = $('.navbar-gitlab').outerHeight()
$el = $("#{container} #{window.location.hash}")
$.scrollTo("#{container} #{window.location.hash}", offset: -navBarHeight) if $el.length
$el = $("#{container} #{window.location.hash}:not(.match)")
$.scrollTo("#{container} #{window.location.hash}:not(.match)", offset: -navBarHeight) if $el.length
# Activate a tab based on the current action
activateTab: (action) ->
......@@ -176,16 +176,17 @@ class @MergeRequestTabs
if locationHash isnt ''
hashClassString = ".#{locationHash.replace('#', '')}"
$diffLine = $(locationHash)
$diffLine = $("#{locationHash}:not(.match)", $('#diffs'))
if $diffLine.is ':not(tr)'
$diffLine = $("td#{locationHash}, td#{hashClassString}")
if not $diffLine.is 'tr'
$diffLine = $('#diffs').find("td#{locationHash}, td#{hashClassString}")
else
$diffLine = $('td', $diffLine)
$diffLine = $diffLine.find('td')
$diffLine.addClass 'hll'
diffLineTop = $diffLine.offset().top
navBarHeight = $('.navbar-gitlab').outerHeight()
if $diffLine.length
$diffLine.addClass 'hll'
diffLineTop = $diffLine.offset().top
navBarHeight = $('.navbar-gitlab').outerHeight()
loadBuilds: (source) ->
return if @buildsLoaded
......
......@@ -9,11 +9,12 @@ class @MergeRequestWidget
constructor: (@opts) ->
$('#modal_merge_info').modal(show: false)
@firstCICheck = true
@readyForCICheck = true
@readyForCICheck = false
clearInterval @fetchBuildStatusInterval
@clearEventListeners()
@addEventListeners()
@getCIStatus(false)
@pollCIStatus()
notifyPermissions()
......@@ -68,20 +69,18 @@ class @MergeRequestWidget
$.getJSON @opts.ci_status_url, (data) =>
@readyForCICheck = true
if @firstCICheck
@firstCICheck = false
@opts.ci_status = data.status
if @opts.ci_status is ''
@opts.ci_status = data.status
if data.status is ''
return
if data.status isnt @opts.ci_status and data.status?
if @firstCICheck || data.status isnt @opts.ci_status and data.status?
@opts.ci_status = data.status
@showCIStatus data.status
if data.coverage
@showCICoverage data.coverage
if showNotification
# The first check should only update the UI, a notification
# should only be displayed on status changes
if showNotification and not @firstCICheck
status = @ciLabelForStatus(data.status)
if status is "preparing"
......@@ -104,8 +103,7 @@ class @MergeRequestWidget
@close()
Turbolinks.visit _this.opts.builds_path
)
@opts.ci_status = data.status
@firstCICheck = false
showCIStatus: (state) ->
$('.ci_widget').hide()
......
#
# * Filter merge requests
#
@MergeRequests =
init: ->
MergeRequests.initSearch()
# Make sure we trigger ajax request only after user stop typing
initSearch: ->
@timer = null
$("#issue_search").keyup ->
clearTimeout(@timer)
@timer = setTimeout(MergeRequests.filterResults, 500)
filterResults: =>
form = $("#issue_search_form")
search = $("#issue_search").val()
$('.merge-requests-holder').css("opacity", '0.5')
issues_url = form.attr('action') + '?' + form.serialize()
$.ajax
type: "GET"
url: form.attr('action')
data: form.serialize()
complete: ->
$('.merge-requests-holder').css("opacity", '1.0')
success: (data) ->
$('.merge-requests-holder').html(data.html)
# Change url so if user reload a page - search results are saved
history.replaceState {page: issues_url}, document.title, issues_url
MergeRequests.reload()
dataType: "json"
reload: ->
$('#filter_issue_search').val($('#issue_search').val())
......@@ -24,7 +24,7 @@ class @MilestoneSelect
if issueUpdateURL
milestoneLinkTemplate = _.template(
'<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>"><%= title %></a>'
'<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>"><%= _.escape(title) %></a>'
)
milestoneLinkNoneTemplate = '<div class="light">None</div>'
......@@ -71,7 +71,7 @@ class @MilestoneSelect
defaultLabel
fieldName: $dropdown.data('field-name')
text: (milestone) ->
milestone.title
_.escape(milestone.title)
id: (milestone) ->
if !useId
milestone.name
......@@ -97,7 +97,7 @@ class @MilestoneSelect
selectedMilestone = selected.name
else
selectedMilestone = ''
Issues.filterResults $dropdown.closest('form')
Issuable.filterResults $dropdown.closest('form')
else if $dropdown.hasClass('js-filter-submit')
$dropdown.closest('form').submit()
else
......
......@@ -75,6 +75,9 @@ class @Notes
# when issue status changes, we need to refresh data
$(document).on "issuable:change", @refresh
# when a key is clicked on the notes
$(document).on "keydown", ".js-note-text", @keydownNoteText
cleanBinding: ->
$(document).off "ajax:success", ".js-main-target-form"
$(document).off "ajax:success", ".js-discussion-note-form"
......@@ -92,10 +95,19 @@ class @Notes
$(document).off "click", ".js-note-target-reopen"
$(document).off "click", ".js-note-target-close"
$(document).off "click", ".js-note-discard"
$(document).off "keydown", ".js-note-text"
$('.note .js-task-list-container').taskList('disable')
$(document).off 'tasklist:changed', '.note .js-task-list-container'
keydownNoteText: (e) ->
$this = $(this)
if $this.val() is '' and e.which is 38 #aka the up key
myLastNote = $("li.note[data-author-id='#{gon.current_user_id}'][data-editable]:last")
if myLastNote.length
myLastNoteEditBtn = myLastNote.find('.js-note-edit')
myLastNoteEditBtn.trigger('click', [true, myLastNote])
initRefresh: ->
clearInterval(Notes.interval)
Notes.interval = setInterval =>
......@@ -343,7 +355,7 @@ class @Notes
Adds a hidden div with the original content of the note to fill the edit note form with
if the user cancels
###
showEditForm: (e) ->
showEditForm: (e, scrollTo, myLastNote) ->
e.preventDefault()
note = $(this).closest(".note")
note.addClass "is-editting"
......@@ -354,9 +366,27 @@ class @Notes
# Show the attachment delete link
note.find(".js-note-attachment-delete").show()
new GLForm form
done = ($noteText) ->
# Neat little trick to put the cursor at the end
noteTextVal = $noteText.val()
$noteText.val('').val(noteTextVal);
form.find(".js-note-text").focus()
new GLForm form
if scrollTo? and myLastNote?
# scroll to the bottom
# so the open of the last element doesn't make a jump
$('html, body').scrollTop($(document).height());
$('html, body').animate({
scrollTop: myLastNote.offset().top - 150
}, 500, ->
$noteText = form.find(".js-note-text")
$noteText.focus()
done($noteText)
);
else
$noteText = form.find('.js-note-text')
$noteText.focus()
done($noteText)
###
Called in response to clicking the edit note link
......
......@@ -45,9 +45,10 @@ class @Profile
saveForm: ->
self = @
formData = new FormData(@form[0])
formData.append('user[avatar]', @avatarGlCrop.getBlob(), 'avatar.png')
avatarBlob = @avatarGlCrop.getBlob()
formData.append('user[avatar]', avatarBlob, 'avatar.png') if avatarBlob?
$.ajax
url: @form.attr('action')
......
class @Sidebar
constructor: (currentUser) ->
@sidebar = $('aside')
@addEventListeners()
addEventListeners: ->
$('aside').on('click', '.sidebar-collapsed-icon', @sidebarCollapseClicked)
$('.dropdown').on('hidden.gl.dropdown', @sidebarDropdownHidden)
@sidebar.on('click', '.sidebar-collapsed-icon', @, @sidebarCollapseClicked)
$('.dropdown').on('hidden.gl.dropdown', @, @onSidebarDropdownHidden)
$('.dropdown').on('loading.gl.dropdown', @sidebarDropdownLoading)
$('.dropdown').on('loaded.gl.dropdown', @sidebarDropdownLoaded)
......@@ -30,26 +32,56 @@ class @Sidebar
else
i.show()
sidebarCollapseClicked: (e) ->
sidebar = e.data
e.preventDefault()
$block = $(@).closest('.block')
sidebar.openDropdown($block);
$('aside')
.find('.gutter-toggle')
.trigger('click')
$editLink = $block.find('.edit-link')
openDropdown: (blockOrName) ->
$block = if _.isString(blockOrName) then @getBlock(blockOrName) else blockOrName
$block.find('.edit-link').trigger('click')
if $editLink.length
$editLink.trigger('click')
$block.addClass('collapse-after-update')
$('.page-with-sidebar').addClass('with-overlay')
if not @isOpen()
@setCollapseAfterUpdate($block)
@toggleSidebar('open')
sidebarDropdownHidden: (e) ->
setCollapseAfterUpdate: ($block) ->
$block.addClass('collapse-after-update')
$('.page-with-sidebar').addClass('with-overlay')
onSidebarDropdownHidden: (e) ->
sidebar = e.data
e.preventDefault()
$block = $(@).closest('.block')
sidebar.sidebarDropdownHidden($block)
sidebarDropdownHidden: ($block) ->
if $block.hasClass('collapse-after-update')
$block.removeClass('collapse-after-update')
$('.page-with-sidebar').removeClass('with-overlay')
$('aside')
.find('.gutter-toggle')
.trigger('click')
\ No newline at end of file
@toggleSidebar('hide')
triggerOpenSidebar: ->
@sidebar
.find('.js-sidebar-toggle')
.trigger('click')
toggleSidebar: (action = 'toggle') ->
if action is 'toggle'
@triggerOpenSidebar()
if action is 'open'
@triggerOpenSidebar() if not @isOpen()
if action is 'hide'
@triggerOpenSidebar() is @isOpen()
isOpen: ->
@sidebar.is('.right-sidebar-expanded')
getBlock: (name) ->
@sidebar.find(".block.#{name}")
class @Search
constructor: ->
$groupDropdown = $('.js-search-group-dropdown')
$projectDropdown = $('.js-search-project-dropdown')
@eventListeners()
$groupDropdown.glDropdown(
selectable: true
filterable: true
fieldName: 'group_id'
data: (term, callback) ->
Api.groups term, null, (data) ->
data.unshift(
name: 'Any'
)
data.splice 1, 0, 'divider'
callback(data)
id: (obj) ->
obj.id
text: (obj) ->
obj.name
toggleLabel: (obj) ->
"#{$groupDropdown.data('default-label')} #{obj.name}"
clicked: =>
@submitSearch()
)
$projectDropdown.glDropdown(
selectable: true
filterable: true
fieldName: 'project_id'
data: (term, callback) ->
Api.projects term, 'id', (data) ->
data.unshift(
name_with_namespace: 'Any'
)
data.splice 1, 0, 'divider'
callback(data)
id: (obj) ->
obj.id
text: (obj) ->
obj.name_with_namespace
toggleLabel: (obj) ->
"#{$projectDropdown.data('default-label')} #{obj.name_with_namespace}"
clicked: =>
@submitSearch()
)
eventListeners: ->
$(document)
.off 'keyup', '.js-search-input'
.on 'keyup', '.js-search-input', @searchKeyUp
$(document)
.off 'click', '.js-search-clear'
.on 'click', '.js-search-clear', @clearSearchField
submitSearch: ->
$('.js-search-form').submit()
searchKeyUp: ->
$input = $(@)
if $input.val() is ''
$('.js-search-clear').addClass 'hidden'
else
$('.js-search-clear').removeClass 'hidden'
clearSearchField: ->
$('.js-search-input')
.val ''
.trigger 'keyup'
.focus()
......@@ -2,34 +2,35 @@ class @Shortcuts
constructor: ->
@enabledHelp = []
Mousetrap.reset()
Mousetrap.bind('?', @selectiveHelp)
Mousetrap.bind('?', @onToggleHelp)
Mousetrap.bind('s', Shortcuts.focusSearch)
Mousetrap.bind(['ctrl+shift+p', 'command+shift+p'], @toggleMarkdownPreview)
Mousetrap.bind('t', -> Turbolinks.visit(findFileURL)) if findFileURL?
selectiveHelp: (e) =>
Shortcuts.showHelp(e, @enabledHelp)
onToggleHelp: (e) =>
e.preventDefault()
@toggleHelp(@enabledHelp)
toggleMarkdownPreview: (e) =>
$(document).triggerHandler('markdown-preview:toggle', [e])
@showHelp: (e, location) ->
if $('#modal-shortcuts').length > 0
$('#modal-shortcuts').modal('show')
else
url = '/help/shortcuts'
url = gon.relative_url_root + url if gon.relative_url_root?
$.ajax(
url: url,
dataType: 'script',
success: (e) ->
if location and location.length > 0
$(l).show() for l in location
else
$('.hidden-shortcut').show()
$('.js-more-help-button').remove()
)
e.preventDefault()
toggleHelp: (location) ->
$modal = $('#modal-shortcuts')
if $modal.length
$modal.modal('toggle')
return
$.ajax(
url: gon.shortcuts_path,
dataType: 'script',
success: (e) ->
if location and location.length > 0
$(l).show() for l in location
else
$('.hidden-shortcut').show()
$('.js-more-help-button').remove()
)
@focusSearch: (e) ->
$('#search').focus()
......
......@@ -4,18 +4,8 @@
class @ShortcutsIssuable extends ShortcutsNavigation
constructor: (isMergeRequest) ->
super()
Mousetrap.bind('a', ->
$('.block.assignee .edit-link').trigger('click')
return false
)
Mousetrap.bind('m', ->
$('.block.milestone .edit-link').trigger('click')
return false
)
Mousetrap.bind('r', =>
@replyWithSelectedText()
return false
)
Mousetrap.bind('a', @openSidebarDropdown.bind(@, 'assignee'))
Mousetrap.bind('m', @openSidebarDropdown.bind(@, 'milestone'))
Mousetrap.bind('j', =>
@prevIssue()
return false
......@@ -28,7 +18,7 @@ class @ShortcutsIssuable extends ShortcutsNavigation
@editIssue()
return false
)
Mousetrap.bind('l', @openSidebarDropdown.bind(@, 'labels'))
if isMergeRequest
@enabledHelp.push('.hidden-shortcut.merge_requests')
......@@ -71,3 +61,7 @@ class @ShortcutsIssuable extends ShortcutsNavigation
editIssue: ->
$editBtn = $('.issuable-edit')
Turbolinks.visit($editBtn.attr('href'))
openSidebarDropdown: (name) ->
sidebar.openDropdown(name)
return false
......@@ -14,6 +14,7 @@ class @ShortcutsNavigation extends Shortcuts
Mousetrap.bind('g m', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-merge_requests'))
Mousetrap.bind('g w', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-wiki'))
Mousetrap.bind('g s', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-snippets'))
Mousetrap.bind('i', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-new-issue'))
@enabledHelp.push('.hidden-shortcut.project')
@findAndFollowLink: (selector) ->
......
......@@ -12,7 +12,7 @@ toggleSidebar = ->
niceScrollBars.updateScrollBar();
), 300
$(document).on("click", '.toggle-nav-collapse', (e) ->
$(document).on("click", '.toggle-nav-collapse, .side-nav-toggle', (e) ->
e.preventDefault()
toggleSidebar()
......
class @Todos
constructor: (@name) ->
constructor: (opts = {}) ->
{
@el = $('.js-todos-options')
} = opts
@perPage = @el.data('perPage')
@clearListeners()
@initBtnListeners()
......@@ -26,6 +32,7 @@ class @Todos
dataType: 'json'
data: '_method': 'delete'
success: (data) =>
@redirectIfNeeded data.count
@clearDone $this.closest('li')
@updateBadges data
......@@ -57,11 +64,46 @@ class @Todos
$('.todos-pending .badge, .todos-pending-count').text data.count
$('.todos-done .badge').text data.done_count
getTotalPages: ->
@el.data('totalPages')
getCurrentPage: ->
@el.data('currentPage')
getTodosPerPage: ->
@el.data('perPage')
redirectIfNeeded: (total) ->
currPages = @getTotalPages()
currPage = @getCurrentPage()
# Refresh if no remaining Todos
if not total
location.reload()
return
# Do nothing if no pagination
return if not currPages
newPages = Math.ceil(total / @getTodosPerPage())
url = location.href # Includes query strings
# If new total of pages is different than we have now
if newPages isnt currPages
# Redirect to previous page if there's one available
if currPages > 1 and currPage is currPages
pageParams =
page: currPages - 1
url = gl.utils.mergeUrlParams(pageParams, url)
Turbolinks.visit(url)
goToTodoUrl: (e)->
todoLink = $(this).data('url')
return unless todoLink
if e.metaKey
# Allow Meta-Click or Mouse3-click to open in a new tab
if e.metaKey or e.which is 2
e.preventDefault()
window.open(todoLink,'_blank')
else
......
......@@ -92,7 +92,7 @@ class @UserTabs
@setCurrentAction(action)
activateTab: (action) ->
@parentEl.find(".nav-links .#{action}-tab a").tab('show')
@parentEl.find(".nav-links .js-#{action}-tab a").tab('show')
setTab: (source, action) ->
return if @loaded[action] is true
......
......@@ -158,7 +158,7 @@ class @UsersSelect
if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
selectedId = user.id
Issues.filterResults $dropdown.closest('form')
Issuable.filterResults $dropdown.closest('form')
else if $dropdown.hasClass 'js-filter-submit'
$dropdown.closest('form').submit()
else
......
......@@ -25,6 +25,7 @@
@import "framework/lists.scss";
@import "framework/markdown_area.scss";
@import "framework/mobile.scss";
@import "framework/modal.scss";
@import "framework/nav.scss";
@import "framework/pagination.scss";
@import "framework/progress.scss";
......
......@@ -28,6 +28,7 @@
&.s46 { width: 46px; height: 46px; margin-right: 15px; }
&.s48 { width: 48px; height: 48px; margin-right: 10px; }
&.s60 { width: 60px; height: 60px; margin-right: 12px; }
&.s70 { width: 70px; height: 70px; margin-right: 14px; }
&.s90 { width: 90px; height: 90px; margin-right: 15px; }
&.s110 { width: 110px; height: 110px; margin-right: 15px; }
&.s140 { width: 140px; height: 140px; margin-right: 20px; }
......
.light-well {
background-color: #f8fafc;
background-color: $background-color;
padding: 15px;
}
......@@ -18,7 +18,7 @@
line-height: 36px;
}
.gray-content-block {
.row-content-block {
margin-top: 0;
margin-bottom: -$gl-padding;
background-color: $background-color;
......@@ -81,6 +81,11 @@
margin-left: 10px;
}
}
&.build-content {
background-color: $white-light;
border-top: none;
}
}
.cover-block {
......@@ -113,7 +118,7 @@
line-height: 1.1;
h1 {
color: #313236;
color: $gl-gray-dark;
margin-bottom: 6px;
font-size: 23px;
}
......@@ -150,6 +155,41 @@
right: auto;
}
}
&.groups-cover-block {
background: $white-light;
border-bottom: 1px solid $border-color;
text-align: left;
padding: 24px 0;
.group-info {
.cover-title {
margin-top: 9px;
}
p {
margin-bottom: 0;
}
}
@media (max-width: $screen-xs-max) {
text-align: center;
.avatar {
float: none;
}
}
}
.group-info {
h1 {
display: inline;
font-weight: normal;
font-size: 24px;
color: $gl-title-color;
}
}
}
.block-connector {
......
......@@ -59,7 +59,7 @@
}
@mixin btn-gray {
@include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-light, $gray-dark, $border-gray-dark, #313236);
@include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-light, $gray-dark, $border-gray-dark, $gl-gray-dark);
}
@mixin btn-white {
......@@ -139,11 +139,19 @@
pointer-events: auto !important;
}
&[disabled] {
pointer-events: none !important;
}
.caret {
margin-left: 5px;
}
}
.btn-lg {
padding: 12px 20px;
}
.btn-transparent {
color: $btn-transparent-color;
background-color: transparent;
......@@ -243,3 +251,10 @@
.btn-file-option {
background: linear-gradient(180deg, $white-light 25%, $gray-light 100%);
}
.btn-build {
margin-left: 10px;
i {
color: $gl-icon-color;
}
}
......@@ -54,6 +54,10 @@
fill: #254e77 !important;
}
.future {
visibility: hidden;
}
.domain-background {
fill: none;
shape-rendering: crispedges;
......
......@@ -11,6 +11,7 @@
.prepend-top-10 { margin-top: 10px }
.prepend-top-default { margin-top: $gl-padding !important; }
.prepend-top-20 { margin-top: 20px }
.prepend-left-5 { margin-left: 5px }
.prepend-left-10 { margin-left: 10px }
.prepend-left-default { margin-left: $gl-padding; }
.prepend-left-20 { margin-left: 20px }
......
......@@ -42,7 +42,7 @@
font-size: 15px;
text-align: left;
border: 1px solid $dropdown-toggle-border-color;
border-radius: $dropdown-border-radius;
border-radius: $border-radius-base;
outline: 0;
text-overflow: ellipsis;
white-space: nowrap;
......@@ -80,7 +80,7 @@
padding: 10px 0;
background-color: $dropdown-bg;
border: 1px solid $dropdown-border-color;
border-radius: $dropdown-border-radius;
border-radius: $border-radius-base;
box-shadow: 0 2px 4px $dropdown-shadow-color;
&.is-loading {
......@@ -248,7 +248,7 @@
.dropdown-title {
position: relative;
padding: 0 25px 15px;
padding: 0 25px 10px;
margin: 0 10px 10px;
font-weight: 600;
line-height: 1;
......@@ -278,7 +278,7 @@
right: 5px;
width: 20px;
height: 20px;
top: -1px;
top: -3px;
}
.dropdown-menu-back {
......@@ -320,7 +320,7 @@
}
}
.dropdown-input-field {
.dropdown-input-field, .default-dropdown-input {
width: 100%;
padding: 0 7px;
color: $dropdown-input-color;
......@@ -358,6 +358,13 @@
border-top: 1px solid $dropdown-divider-color;
}
.dropdown-due-date-footer {
padding-top: 0;
margin-left: 10px;
margin-right: 10px;
border-top: 0;
}
.dropdown-footer-list {
font-size: 14px;
......@@ -395,3 +402,122 @@
height: 15px;
border-radius: $border-radius-base;
}
.dropdown-menu-due-date {
.dropdown-content {
max-height: 230px;
}
.ui-widget {
table {
margin: 0;
}
&.ui-datepicker-inline {
padding: 0 10px;
border: 0;
width: 100%;
}
.ui-datepicker-header {
padding: 0 8px 10px;
border: 0;
.ui-icon {
background: none;
font-size: 20px;
text-indent: 0;
&:before {
display: block;
position: relative;
top: -2px;
color: $dropdown-title-btn-color;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
}
.ui-state-active,
.ui-state-hover {
color: $md-link-color;
background-color: $calendar-hover-bg;
}
.ui-datepicker-prev,
.ui-datepicker-next {
top: 0;
height: 15px;
cursor: pointer;
&:hover {
background-color: transparent;
border: 0;
.ui-icon:before {
color: $md-link-color;
}
}
}
.ui-datepicker-prev {
left: 0;
.ui-icon:before {
content: '\f104';
text-align: left;
}
}
.ui-datepicker-next {
right: 0;
.ui-icon:before {
content: '\f105';
text-align: right;
}
}
td {
padding: 0;
border: 1px solid $calendar-border-color;
&:first-child {
border-left: 0;
}
&:last-child {
border-right: 0;
}
a {
line-height: 17px;
border: 0;
border-radius: 0;
}
}
.ui-datepicker-title {
color: $gl-gray;
font-size: 15px;
line-height: 1;
font-weight: normal;
}
}
th {
padding: 2px 0;
color: $calendar-header-color;
font-weight: normal;
text-transform: lowercase;
border-top: 1px solid $calendar-border-color;
}
.ui-datepicker-unselectable {
background-color: $calendar-unselectable-bg;
}
}
......@@ -38,12 +38,14 @@
.filename {
&.old {
display: inline-block;
span.idiff {
background-color: #f8cbcb;
}
}
&.new {
display: inline-block;
span.idiff {
background-color: #a6f3a6;
}
......@@ -82,10 +84,6 @@
}
}
&.blob_file {
}
&.blob-no-preview {
background: #eee;
text-shadow: 0 1px 2px #fff;
......@@ -129,6 +127,11 @@
td.line-numbers {
float: none;
border-left: 1px solid #ddd;
i {
float: none;
margin-right: 0;
}
}
td.lines {
padding: 0;
......
......@@ -78,6 +78,24 @@ label {
border-radius: 3px;
}
.select-wrapper {
position: relative;
.caret {
position: absolute;
right: 10px;
top: $gl-padding;
color: $gray-darkest;
pointer-events: none;
}
}
.select-control {
padding-left: 10px;
padding-right: 10px;
-webkit-appearance: none;
}
.form-control-inline {
display: inline;
}
......
......@@ -24,6 +24,10 @@
background-color: $color-darker;
a {
color: #fff;
h3 {
color: #fff;
}
}
}
}
......
......@@ -8,7 +8,7 @@ header {
&.navbar-empty {
height: 58px;
background: #fff;
border-bottom: 1px solid #eee;
border-bottom: 1px solid $btn-gray-hover;
.center-logo {
margin: 11px 0;
......@@ -22,13 +22,21 @@ header {
}
&.navbar-gitlab {
padding: 0 20px;
padding: 0 16px;
z-index: 100;
margin-bottom: 0;
min-height: $header-height;
background-color: #fff;
height: $header-height;
background-color: $background-color;
border: none;
border-bottom: 1px solid #eee;
border-bottom: 1px solid $border-color;
@media (max-width: $screen-xs-min) {
padding: 0 16px;
}
&.with-horizontal-nav {
border-bottom: none;
}
.container-fluid {
width: 100% !important;
......@@ -47,7 +55,7 @@ header {
text-align: center;
&:hover, &:focus, &:active {
background-color: #fff;
background-color: $background-color;
}
}
......@@ -56,22 +64,54 @@ header {
margin: 6px 0;
border-radius: 0;
position: absolute;
right: 2px;
right: -10px;
padding: 6px 10px;
&:hover {
background-color: #eee;
background-color: $btn-gray-hover;
}
&.active {
color: $gl-icon-color;
}
}
}
&.header-collapsed {
padding: 0 16px;
}
.side-nav-toggle {
display: none;
position: absolute;
left: -10px;
margin: 6px 0;
padding: 6px 10px;
border: none;
background-color: $background-color;
&:hover {
background-color: $btn-gray-hover;
}
&:focus {
outline: none;
}
@media (max-width: $screen-xs-min) {
display: block;
}
}
}
.header-content {
position: relative;
height: $header-height;
padding-right: 20px;
padding-right: 40px;
@media (max-width: $screen-xs-min) {
padding-left: 40px;
}
@media (min-width: $screen-sm-min) {
padding-right: 0;
......@@ -122,6 +162,10 @@ header {
}
}
.project-item-select-holder {
display: inline;
}
.impersonation i {
color: $red-normal;
}
......@@ -137,6 +181,10 @@ header {
@media (min-width: $screen-md-min) {
@include collapsed-header;
}
@media (max-width: $screen-xs-min) {
margin-left: 0;
}
}
.header-expanded {
......@@ -145,6 +193,10 @@ header {
@media (min-width: $screen-md-min) {
margin-left: $sidebar_width;
}
@media (max-width: $screen-xs-min) {
margin-left: 0;
}
}
@media (max-width: $screen-xs-max) {
......
......@@ -5,7 +5,7 @@
*/
.status-box {
/* Extra small devices (phones, less than 768px) */
/* No media query since this is the default in Bootstrap */
padding: 5px 11px;
......
......@@ -90,3 +90,12 @@
box-shadow: none;
width: 100%;
}
.md {
&.md-preview-holder {
code {
white-space: pre-wrap;
word-break: keep-all;
}
}
}
......@@ -30,7 +30,7 @@
}
.rss-btn {
display: none !important;
display: none;
}
.project-home-links {
......@@ -70,13 +70,6 @@
display: none;
}
.issue-details {
.creator,
.page-title .btn-close {
display: none;
}
}
%ul.notes .note-role, .note-actions {
display: none;
}
......
.modal-body {
position: relative;
overflow-y: auto;
padding: 15px;
.form-actions {
margin: -$gl-padding+1;
margin-top: 15px;
}
.text-danger {
font-weight: bold;
}
}
body.modal-open {
overflow: hidden;
}
.modal .modal-dialog {
width: 860px;
}
......@@ -26,8 +26,8 @@
}
&.active a {
color: #000;
border-bottom: 2px solid #4688f1;
border-bottom: 2px solid $link-underline-blue;
color: $black;
}
.badge {
......@@ -140,6 +140,12 @@
}
}
.project-filter-form {
input {
background-color: $background-color;
}
}
@media (max-width: $screen-xs-max) {
padding-bottom: 0;
......@@ -185,3 +191,73 @@
}
}
}
.layout-nav {
position: fixed;
top: $header-height;
width: 100%;
z-index: 1;
background: $background-color;
border-bottom: 1px solid $border-color;
transition-duration: .3s;
.container-fluid {
position: relative;
}
.controls {
float: right;
padding: 7px 0 0;
i {
color: $layout-link-gray;
}
.fa-rss,
.fa-cog {
font-size: 16px;
}
.fa-caret-down {
margin-left: 5px;
color: $gl-icon-color;
}
.dropdown {
margin-left: 7px;
}
}
.nav-links {
border-bottom: none;
height: 51px;
white-space: nowrap;
overflow-x: auto;
li {
a {
padding-top: 10px;
}
a, i {
color: $layout-link-gray;
}
&.active {
a, i {
color: $black;
}
}
.badge {
color: $gl-icon-color;
}
}
}
}
.page-with-layout-nav {
margin-top: 50px;
}
......@@ -7,13 +7,11 @@
.select2-choice {
background: #fff;
border-color: $input-border;
border-color: $border-white-light;
height: 35px;
padding: $gl-vert-padding $gl-btn-padding;
font-size: $gl-font-size;
line-height: 1.42857143;
@include border-radius($border-radius-default);
border-radius: $border-radius-base;
.select2-arrow {
background-image: none;
......@@ -121,9 +119,6 @@
}
}
.select2-container-multi .select2-choices .select2-search-choice {
}
.select2-drop-active {
margin-top: 6px;
font-size: 14px;
......@@ -202,6 +197,14 @@
}
}
.select2-highlighted {
.group-result {
.group-path {
color: #fff;
}
}
}
.group-result {
.group-image {
float: left;
......
......@@ -3,6 +3,7 @@
position: absolute;
width: 58px;
cursor: pointer;
margin-top: 8px;
}
.page-with-sidebar {
......@@ -62,7 +63,7 @@
float: left;
height: $header-height;
width: 100%;
padding: 11px 0 11px 22px;
padding-left: 22px;
overflow: hidden;
outline: none;
transition-duration: .3s;
......@@ -85,7 +86,7 @@
margin: 0;
margin-left: 50px;
font-size: 19px;
line-height: 41px;
line-height: 50px;
font-weight: normal;
}
}
......@@ -97,7 +98,7 @@
}
.sidebar-user {
padding: 9px 22px;
padding: 7px 22px;
position: fixed;
bottom: 40px;
width: $sidebar_width;
......@@ -209,15 +210,33 @@
}
}
.sidebar-wrapper {
&.hidden-nav {
width: 0;
}
}
.page-sidebar-collapsed {
padding-left: $sidebar_collapsed_width;
@media (max-width: $screen-xs-min) {
padding-left: 0;
}
.sidebar-wrapper {
width: $sidebar_collapsed_width;
@media (max-width: $screen-xs-min) {
width: 0;
}
.header-logo {
width: $sidebar_collapsed_width;
@media (max-width: $screen-xs-min) {
width: 0;
}
a {
padding-left: ($sidebar_collapsed_width - 36) / 2;
......@@ -243,17 +262,35 @@
.collapse-nav a {
width: $sidebar_collapsed_width;
@media (max-width: $screen-xs-min) {
width: 0;
}
}
.sidebar-user {
padding-left: ($sidebar_collapsed_width - 36) / 2;
width: $sidebar_collapsed_width;
@media (max-width: $screen-xs-min) {
width: 0;
padding-left: 0;
padding-right: 0;
}
.username {
display: none;
}
}
}
.layout-nav {
padding-right: $sidebar_collapsed_width;
@media (max-width: $screen-xs-min) {
padding-right: 0;;
}
}
}
.page-sidebar-expanded {
......@@ -263,6 +300,10 @@
padding-left: $sidebar_width;
}
@media (max-width: $screen-xs-min) {
padding-left: 0;
}
.sidebar-wrapper {
width: $sidebar_width;
......@@ -280,6 +321,20 @@
}
}
}
.layout-nav {
@media (max-width: $screen-xs-min) {
padding-right: 0;;
}
@media (min-width: $screen-xs-min) and (max-width: $screen-md-min) {
padding-right: 62px;
}
@media (min-width: $screen-md-min) {
padding-right: $sidebar_width;
}
}
}
.right-sidebar-collapsed {
......
......@@ -32,13 +32,11 @@ table {
th {
background-color: $background-color;
font-weight: normal;
font-size: 15px;
border-bottom: 1px solid $border-color;
border-bottom: none;
}
td {
border-color: $table-border-color;
border-bottom: 1px solid $border-color;
}
}
}
......
......@@ -11,7 +11,7 @@
border-bottom: 1px solid $border-white-light;
&:target {
background: $row-hover;
background: $line-target-blue;
}
.avatar {
......@@ -39,8 +39,7 @@
.diff-file {
border: 1px solid $border-color;
border-bottom: none;
margin-left: 0;
margin-right: 0;
margin: 0;
}
}
......
......@@ -81,7 +81,7 @@
// Labels
.label {
padding: 2px 4px;
padding: 4px 5px;
font-size: 13px;
font-style: normal;
font-weight: normal;
......
......@@ -153,8 +153,8 @@ $nav-link-padding: 13px $gl-padding;
//== Code
//
//##
$pre-bg: #f8fafc !default;
$pre-bg: $background-color !default;
$pre-color: $gl-gray !default;
$pre-border-color: #e7e9ed;
$pre-border-color: $border-color;
$table-bg-accent: $background-color;
......@@ -42,14 +42,14 @@
margin: 24px 0 12px;
padding: 0 0 10px;
border-bottom: 1px solid #e7e9ed;
color: #313236;
color: $gl-gray-dark;
}
h2 {
font-size: 1.2em;
font-weight: 600;
margin: 24px 0 12px;
color: #313236;
color: $gl-gray-dark;
}
h3 {
......@@ -205,6 +205,10 @@ h1, h2, h3, h4, h5, h6 {
font-weight: 600;
}
.light-header {
font-weight: 600;
}
/** CODE **/
pre {
font-family: $monospace_font;
......@@ -259,3 +263,9 @@ h1, h2, h3, h4 {
color: $gl-gray;
}
}
.text-right-lg {
@media (min-width: $screen-lg-min) {
text-align: right;
}
}
......@@ -12,7 +12,7 @@ $gutter_inner_width: 258px;
*/
$border-color: #e5e5e5;
$focus-border-color: #3aabf0;
$table-border-color: #eef0f2;
$table-border-color: #ececec;
$background-color: #fafafa;
/*
......@@ -20,7 +20,7 @@ $background-color: #fafafa;
*/
$gl-font-size: 15px;
$gl-title-color: #333;
$gl-text-color: #555;
$gl-text-color: #5c5c5c;
$gl-text-green: #4a2;
$gl-text-red: #d12f19;
$gl-text-orange: #d90;
......@@ -30,6 +30,7 @@ $gl-placeholder-color: #8f8f8f;
$gl-icon-color: $gl-placeholder-color;
$gl-grayish-blue: #7f8fa4;
$gl-gray: $gl-text-color;
$gl-gray-dark: #313236;
$gl-header-color: $gl-title-color;
/*
......@@ -65,16 +66,18 @@ $gl-padding-top: 10px;
$row-hover: #f4f8fe;
$progress-color: #c0392b;
$avatar_radius: 50%;
$header-height: 58px;
$header-height: 50px;
$fixed-layout-width: 1280px;
$gl-avatar-size: 40px;
$error-exclamation-point: #e62958;
$border-radius-default: 2px;
$btn-transparent-color: #8f8f8f;
$ssh-key-icon-color: #8f8f8f;
$ssh-key-icon-size: 18px;
$settings-icon-size: 18px;
$provider-btn-group-border: #e5e5e5;
$provider-btn-not-active-color: #4688f1;
$link-underline-blue: #4a8bee;
$layout-link-gray: #7e7c7c;
$todo-alert-blue: #428bca;
/*
* Color schema
......@@ -109,6 +112,7 @@ $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;
......@@ -168,8 +172,12 @@ $line-removed: #fbe9eb;
$line-removed-dark: #fac5cd;
$line-number-old: #f9d7dc;
$line-number-new: #ddfbe6;
$line-number-select: #fbf2da;
$match-line: #fafafa;
$table-border-gray: #f0f0f0;
$line-target-blue: #eaf3fc;
$line-select-yellow: #fcf8e7;
$line-select-yellow-dark: #f0e2bd;
/*
* Fonts
*/
......@@ -179,7 +187,6 @@ $regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif
/*
* Dropdowns
*/
$dropdown-border-radius: 2px;
$dropdown-width: 300px;
$dropdown-bg: #fff;
$dropdown-link-color: #555;
......@@ -208,6 +215,7 @@ $dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color;
$btn-active-gray: #ececec;
$btn-placeholder-gray: #c7c7c7;
$btn-white-active: #848484;
$btn-gray-hover: #eee;
/*
* Award emoji
......@@ -241,3 +249,8 @@ $note-form-border-color: #e5e5e5;
$note-toolbar-color: #959494;
$zen-control-hover-color: #111;
$calendar-header-color: #b8b8b8;
$calendar-hover-bg: #ecf3fe;
$calendar-border-color: rgba(#000, .1);
$calendar-unselectable-bg: #faf9f9;
......@@ -111,8 +111,6 @@
.vg { color: #f8f8f2 } /* Name.Variable.Global */
.vi { color: #f8f8f2 } /* Name.Variable.Instance */
.il { color: #ae81ff } /* Literal.Number.Integer.Long */
.gh { } /* Generic Heading & Diff Header */
.gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
.gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */
.gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */
......
......@@ -21,11 +21,6 @@
// Diff line
.line_holder {
td.diff-line-num.hll:not(.empty-cell),
td.line_content.hll:not(.empty-cell) {
background-color: #f8eec7;
border-color: darken(#f8eec7, 15%);
}
.diff-line-num {
&.old {
......@@ -37,11 +32,16 @@
background-color: $line-number-new;
border-color: $line-added-dark;
}
&.hll:not(.empty-cell) {
background-color: $line-number-select;
border-color: $line-select-yellow-dark;
}
}
.line_content {
&.old {
background: $line-removed;
background-color: $line-removed;
span.idiff {
background-color: $line-removed-dark;
......@@ -58,7 +58,11 @@
&.match {
color: $black-transparent;
background: $match-line;
background-color: $match-line;
}
&.hll:not(.empty-cell) {
background-color: $line-select-yellow;
}
}
}
......
......@@ -83,3 +83,12 @@
}
}
}
table.builds {
.build-link {
a {
color: $gl-dark-link-color;
}
}
}
......@@ -31,9 +31,23 @@
}
.commit-committer-link,
.commit-author-link {
color: #444;
color: $gl-gray;
font-weight: bold;
}
.time_ago {
margin-left: 8px;
}
.fa-clipboard {
color: $dropdown-title-btn-color;
}
.commit-info {
&.branches {
margin-left: 8px;
}
}
}
.commit-box {
......@@ -42,7 +56,7 @@
.commit-title {
margin: 0;
font-size: 23px;
color: #313236;
color: $gl-gray-dark;
}
.commit-description {
......@@ -83,6 +97,14 @@
}
}
.commit-action-buttons {
i {
color: $gl-icon-color;
font-size: 13px;
margin-right: 3px;
}
}
/*
* Commit message textarea for web editor and
* custom merge request message
......
.well-confirmation {
margin-bottom: 20px;
border-bottom: 1px solid #eee;
> h1 {
font-weight: 400;
}
.lead {
margin-bottom: 20px;
}
}
.confirmation-content {
a {
color: $md-link-color;
}
}
.detail-page-header {
padding: 11px 0;
padding: $gl-padding-top 0;
border-bottom: 1px solid $border-color;
color: #5c5d5e;
font-size: 16px;
......@@ -16,18 +16,13 @@
.issue_created_ago, .author_link {
white-space: nowrap;
}
.issue-meta {
display: inline-block;
line-height: 20px;
}
}
.detail-page-description {
.title {
margin: 0;
font-size: 23px;
color: #313236;
color: $gl-gray-dark;
}
.description {
......@@ -41,4 +36,11 @@
}
}
}
.wiki {
code {
white-space: pre-wrap;
word-break: keep-all;
}
}
}
......@@ -34,6 +34,7 @@
background: #fff;
color: #333;
border-radius: 0 0 3px 3px;
-webkit-overflow-scrolling: auto;
.unfold {
cursor: pointer;
......@@ -86,7 +87,7 @@
}
span {
white-space: pre;
white-space: pre-wrap;
}
}
}
......@@ -97,7 +98,11 @@
}
td.line_content.parallel {
width: 50%;
width: 46%;
}
.add-diff-note {
margin-left: -65px;
}
}
......@@ -126,8 +131,13 @@
margin: 0;
padding: 0 0.5em;
border: none;
&.parallel {
display: table-cell;
span {
word-break: break-all;
}
}
}
......@@ -335,7 +345,7 @@
}
.diff-file .line_content {
white-space: pre;
white-space: pre-wrap;
}
.diff-wrap-lines .line_content {
......
......@@ -26,6 +26,10 @@
line-height: 42px;
padding-top: 7px;
padding-bottom: 7px;
.pull-right {
height: 20px;
}
}
.editor-ref {
......@@ -53,4 +57,9 @@
.select2 {
float: right;
}
.encoding-selector,
.license-selector {
display: inline-block;
}
}
......@@ -18,9 +18,6 @@
}
.graphs {
.graph-author-commits-count {
}
.graph-author-email {
float: right;
color: #777;
......
......@@ -55,23 +55,6 @@
}
}
.modal-body {
position: relative;
overflow-y: auto;
padding: 15px;
.form-actions {
margin: -$gl-padding+1;
}
}
body.modal-open {
overflow: hidden;
}
.modal .modal-dialog {
width: 860px;
}
.documentation {
padding: 7px;
}
......@@ -16,3 +16,24 @@ i.icon-gitorious-big {
width: 18px;
height: 18px;
}
.import-jobs-from-col,
.import-jobs-to-col {
width: 40%;
}
.import-jobs-status-col {
width: 20%;
}
.btn-import {
.loading-icon {
display: none;
}
&.is-loading {
.loading-icon {
display: inline-block;
}
}
}
......@@ -128,6 +128,7 @@
top: 58px;
bottom: 0;
right: 0;
z-index: 10;
transition: width .3s;
background: $gray-light;
padding: 10px 20px;
......@@ -241,16 +242,20 @@
}
}
.btn {
.issuable-pager {
background: $gray-normal;
border: 1px solid $border-gray-normal;
&:hover {
background: $gray-dark;
border: 1px solid $border-gray-dark;
}
&.btn-primary {
@extend .btn-primary
}
}
a:not(.btn) {
a:not(.issuable-pager) {
&:hover {
color: $md-link-color;
text-decoration: none;
......@@ -273,10 +278,6 @@
}
}
.btn-default.gutter-toggle {
margin-top: 4px;
}
.detail-page-description {
small {
color: $gray-darkest;
......@@ -322,3 +323,50 @@
padding-top: 7px;
}
}
.issuable-status-box {
float: none;
display: inline-block;
margin-top: 0;
@media (max-width: $screen-xs-max) {
position: absolute;
top: 0;
left: 0;
}
}
.issuable-header {
position: relative;
padding-left: 45px;
padding-right: 45px;
line-height: 35px;
@media (min-width: $screen-sm-min) {
float: left;
padding-left: 0;
padding-right: 0;
}
}
.issuable-actions {
padding-top: 10px;
@media (min-width: $screen-sm-min) {
float: right;
padding-top: 0;
}
}
.issuable-gutter-toggle {
@media (max-width: $screen-sm-max) {
position: absolute;
top: 0;
right: 0;
}
}
.issuable-meta {
display: inline-block;
line-height: 18px;
}
......@@ -86,41 +86,9 @@ form.edit-issue {
@media (max-width: $screen-xs-max) {
.issue-btn-group {
width: 100%;
margin-top: 5px;
.btn-group {
width: 100%;
ul {
width: 100%;
text-align: center;
}
}
.btn {
width: 100%;
&:first-child:not(:last-child) {
}
&:not(:first-child):not(:last-child) {
margin-top: 10px;
}
&:last-child:not(:first-child) {
margin-top: 10px;
}
}
}
.issue {
&:hover .issue-actions {
display: none !important;
}
.issue-updated-at {
display: none;
}
}
}
......@@ -133,11 +101,3 @@ form.edit-issue {
color: $gl-text-color;
margin-left: 52px;
}
.editor-details {
display: block;
@media (min-width: $screen-sm-min) {
display: inline-block;
}
}
......@@ -104,7 +104,7 @@
font-weight: 600;
font-size: 17px;
margin: 5px 0;
color: #313236;
color: $gl-gray-dark;
}
p:last-child {
......@@ -136,7 +136,7 @@
}
.label-branch {
color: #313236;
color: $gl-gray-dark;
font-family: $monospace_font;
font-weight: bold;
overflow: hidden;
......@@ -272,3 +272,19 @@
display: inline-block;
width: 250px;
}
.table-holder {
.builds {
th {
background-color: $white-light;
color: $gl-placeholder-color;
}
th,
td {
padding: 16px;
}
}
}
......@@ -28,7 +28,7 @@ li.milestone {
// Issue title
span a {
color: rgba(0,0,0,0.64);
color: $gl-text-color;
}
}
}
......@@ -51,7 +51,7 @@ li.milestone {
margin-top: 7px;
.issuable-number {
color: rgba(0,0,0,0.44);
color: $gl-placeholder-color;
margin-right: 5px;
}
.avatar {
......
......@@ -42,6 +42,7 @@
.note-textarea {
display: block;
padding: 10px 0;
color: $gl-gray;
font-family: $regular_font;
border: 0;
......@@ -61,11 +62,11 @@
padding: $gl-padding-top $gl-padding;
border: 1px solid $note-form-border-color;
border-radius: $border-radius-base;
transition: border-color ease-in-out 0.15s,
box-shadow ease-in-out 0.15s;
&.is-focused {
border-color: $focus-border-color;
box-shadow: 0 0 2px $black-transparent,
0 0 4px rgba($focus-border-color, .4);
@extend .form-control:focus;
.comment-toolbar,
.nav-links {
......@@ -83,18 +84,6 @@
border-color: $gl-success;
}
}
p {
code {
white-space: normal;
}
pre {
code {
white-space: pre;
}
}
}
}
}
......
......@@ -80,16 +80,8 @@ ul.notes {
@include md-typography;
// On diffs code should wrap nicely and not overflow
p {
code {
white-space: normal;
}
pre {
code {
white-space: pre;
}
}
code {
white-space: pre-wrap;
}
// Reset ul style types since we're nested inside a ul already
......@@ -116,10 +108,10 @@ ul.notes {
border-color: darken(#f5f5f5, 8%);
margin: 10px 0;
}
}
a {
word-break: break-all;
code {
word-break: keep-all;
}
}
}
......@@ -136,7 +128,7 @@ ul.notes {
margin-right: 10px;
}
.line_content {
white-space: pre;
white-space: pre-wrap;
}
}
......@@ -175,6 +167,11 @@ ul.notes {
.notes {
background-color: $white-light;
}
a code {
top: 0;
margin-right: 0;
}
}
}
}
......@@ -190,6 +187,9 @@ ul.notes {
}
}
.author_link {
color: $gl-gray;
}
}
.note-headline-light,
......@@ -197,6 +197,12 @@ ul.notes {
color: $notes-light-color;
}
.discussion-headline-light {
a {
color: $gl-link-color;
}
}
/**
* Actions for Discussions/Notes
*/
......@@ -208,6 +214,17 @@ ul.notes {
color: $notes-action-color;
}
.discussion-actions {
@media (max-width: $screen-md-max) {
float: none;
margin-left: 0;
.note-action-button {
margin-left: 0;
}
}
}
.note-action-button,
.discussion-action-button {
display: inline-block;
......@@ -285,7 +302,7 @@ ul.notes {
padding: 4px;
font-size: 16px;
color: $gl-link-color;
margin-left: -60px;
margin-left: -56px;
position: absolute;
z-index: 10;
width: 32px;
......
......@@ -18,7 +18,8 @@
}
.account-btn-link,
.profile-settings-sidebar a {
.profile-settings-sidebar a,
.settings-sidebar a {
color: $md-link-color;
}
......@@ -123,12 +124,6 @@
}
}
.key-icon {
color: $ssh-key-icon-color;
font-size: $ssh-key-icon-size;
line-height: 42px;
}
.key-created-at {
line-height: 42px;
}
......@@ -180,14 +175,6 @@
}
}
.profile-settings-message {
line-height: 32px;
color: $warning-message-color;
background-color: $warning-message-bg;
border: 1px solid $warning-message-border;
border-radius: $border-radius-base;
}
.oauth-applications {
form {
display: inline-block;
......@@ -218,3 +205,21 @@
text-align: center;
}
}
.user-profile {
@media (max-width: $screen-xs-max) {
.cover-block {
padding-top: 20px;
}
.cover-controls {
position: static;
margin-bottom: 20px;
.btn {
display: inline-block;
width: 46%;
}
}
}
}
......@@ -178,7 +178,7 @@
.option-title {
font-weight: normal;
display: inline-block;
color: #313236;
color: $gl-gray-dark;
}
.option-descr {
......@@ -202,8 +202,31 @@
min-width: 200px;
}
.deploy-project-label {
margin: 1px;
.deploy-key-content {
@media (min-width: $screen-sm-min) {
float: left;
&:last-child {
float: right;
}
}
}
.deploy-key-projects {
@media (min-width: $screen-sm-min) {
line-height: 42px;
}
}
a.deploy-project-label {
padding: 5px;
margin-right: 5px;
color: $gl-gray;
background-color: $row-hover;
&:hover {
color: $gl-link-color;
}
}
.vs-public {
......@@ -256,12 +279,6 @@
}
}
table.table.protected-branches-list tr.no-border {
th, td {
border: 0;
}
}
.project-import .btn {
float: left;
margin-right: 10px;
......@@ -474,3 +491,14 @@ pre.light-well {
color: #fff;
}
}
.protected-branches-list {
a {
color: $gl-gray;
font-weight: 600;
&:hover {
color: $gl-link-color;
}
}
}
......@@ -10,17 +10,6 @@
}
}
.search-holder {
max-width: 600px;
margin: 0 auto;
margin-bottom: 20px;
input {
border-color: #bbb;
font-weight: bold;
}
}
.search {
margin-right: 10px;
margin-left: 10px;
......@@ -159,7 +148,85 @@
&.has-location-badge {
.search-input-wrap {
width: 78%;
width: 68%;
}
}
}
.search-holder {
@media (min-width: $screen-sm-min) {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.search-field-holder {
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
position: relative;
margin-right: 0;
@media (min-width: $screen-sm-min) {
margin-right: 5px;
}
}
.search-icon {
position: absolute;
left: 10px;
top: 10px;
color: $gray-darkest;
pointer-events: none;
}
.search-text-input {
padding-left: $gl-padding + 15px;
padding-right: $gl-padding + 15px;
}
.btn-search {
width: 100%;
margin-top: 5px;
@media (min-width: $screen-sm-min) {
width: auto;
margin-top: 0;
margin-left: 5px;
}
}
.dropdown {
@media (min-width: $screen-sm-min) {
margin-left: 5px;
margin-right: 5px;
}
}
.dropdown-menu-toggle {
width: 100%;
margin-top: 5px;
@media (min-width: $screen-sm-min) {
width: 160px;
margin-top: 0;
}
}
}
.search-clear {
position: absolute;
right: 10px;
top: 10px;
padding: 0;
color: $gray-darkest;
line-height: 0;
background: none;
border: 0;
&:hover,
&:focus {
color: $gl-link-color;
outline: none;
}
}
.settings-list-icon {
color: $gl-placeholder-color;
font-size: $settings-icon-size;
line-height: 42px;
}
.settings-message {
padding: 5px;
line-height: 1.3;
color: $warning-message-color;
background-color: $warning-message-bg;
border: 1px solid $warning-message-border;
border-radius: $border-radius-base;
}
.container-fluid {
.ci-status {
padding: 2px 7px;
margin-right: 5px;
margin-right: 10px;
border: 1px solid #eee;
white-space: nowrap;
@include border-radius(4px);
......
......@@ -6,9 +6,16 @@
.navbar-nav {
li {
.badge.todos-pending-count {
background-color: $gl-icon-color;
margin-top: -5px;
font-weight: normal;
background: $todo-alert-blue;
margin-left: -17px;
font-size: 11px;
color: white;
padding: 3px;
padding-top: 1px;
padding-bottom: 1px;
border-radius: 3px;
}
}
}
......
......@@ -16,7 +16,7 @@
tr {
> td, > th {
line-height: 26px;
line-height: 23px;
}
&:hover {
......
/* Generic print styles */
header, nav, nav.main-nav, nav.navbar-collapse, nav.navbar-collapse.collapse {display: none!important;}
.profiler-results {display: none;}
/* Styles targeted specifically at printing files */
.tree-ref-holder, .tree-holder .breadcrumb, .blob-commit-info {display: none;}
.file-title {display: none;}
.file-holder {border: none;}
.wiki h1, .wiki h2, .wiki h3, .wiki h4, .wiki h5, .wiki h6 {margin-top: 17px; }
.wiki h1 {font-size: 30px;}
.wiki h2 {font-size: 22px;}
.wiki h3 {font-size: 18px; font-weight: bold; }
.sidebar-wrapper { display: none; }
.nav { display: none; }
.btn { display: none; }
header,
nav,
nav.main-nav,
nav.navbar-collapse,
nav.navbar-collapse.collapse,
.profiler-results,
.tree-ref-holder,
.tree-holder .breadcrumb,
.blob-commit-info,
.file-title,
.file-holder,
.sidebar-wrapper,
.nav,
.btn,
ul.notes-form,
.merge-request-ci-status .ci-status-link:after,
.issuable-gutter-toggle,
.gutter-toggle,
.issuable-details .content-block-small,
.edit-link,
.note-action-button {
display: none!important;
}
.page-gutter {
padding-top: 0;
padding-left: 0;
}
.right-sidebar {
top: 0;
}
......@@ -6,12 +6,6 @@ class Admin::ApplicationController < ApplicationController
layout 'admin'
def authenticate_admin!
return render_404 unless current_user.is_admin?
end
def authorize_impersonator!
if session[:impersonator_id]
User.find_by!(username: session[:impersonator_id]).admin?
end
render_404 unless current_user.is_admin?
end
end
......@@ -75,6 +75,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:admin_notification_email,
:user_oauth_applications,
:shared_runners_enabled,
:shared_runners_text,
:max_artifacts_size,
:metrics_enabled,
:metrics_host,
......@@ -92,6 +93,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:akismet_api_key,
:email_author_in_body,
:repository_checks_enabled,
:metrics_packet_size,
restricted_visibility_levels: [],
import_sources: []
)
......
......@@ -39,6 +39,12 @@ class Admin::HooksController < Admin::ApplicationController
end
def hook_params
params.require(:hook).permit(:url, :enable_ssl_verification)
params.require(:hook).permit(
:enable_ssl_verification,
:push_events,
:tag_push_events,
:token,
:url
)
end
end
class Admin::ImpersonationController < Admin::ApplicationController
skip_before_action :authenticate_admin!, only: :destroy
before_action :user
before_action :authorize_impersonator!
def create
if @user.blocked?
flash[:alert] = "You cannot impersonate a blocked user"
redirect_to admin_user_path(@user)
else
session[:impersonator_id] = current_user.username
session[:impersonator_return_to] = admin_user_path(@user)
warden.set_user(user, scope: 'user')
flash[:alert] = "You are impersonating #{user.username}."
redirect_to root_path
end
end
def destroy
redirect = session[:impersonator_return_to]
warden.set_user(user, scope: 'user')
session[:impersonator_return_to] = nil
session[:impersonator_id] = nil
redirect_to redirect || root_path
end
def user
@user ||= User.find_by!(username: params[:id] || session[:impersonator_id])
end
end
class Admin::ImpersonationsController < Admin::ApplicationController
skip_before_action :authenticate_admin!
before_action :authenticate_impersonator!
def destroy
original_user = current_user
warden.set_user(impersonator, scope: :user)
Gitlab::AppLogger.info("User #{original_user.username} has stopped impersonating #{impersonator.username}")
session[:impersonator_id] = nil
redirect_to admin_user_path(original_user)
end
private
def impersonator
@impersonator ||= User.find(session[:impersonator_id]) if session[:impersonator_id]
end
def authenticate_impersonator!
render_404 unless impersonator && impersonator.is_admin? && !impersonator.blocked?
end
end
......@@ -31,6 +31,24 @@ class Admin::UsersController < Admin::ApplicationController
user
end
def impersonate
if user.blocked?
flash[:alert] = "You cannot impersonate a blocked user"
redirect_to admin_user_path(user)
else
session[:impersonator_id] = current_user.id
warden.set_user(user, scope: :user)
Gitlab::AppLogger.info("User #{current_user.username} has started impersonating #{user.username}")
flash[:alert] = "You are now impersonating #{user.username}"
redirect_to root_path
end
end
def block
if user.block
redirect_back_or_admin_user(notice: "Successfully blocked")
......
......@@ -117,7 +117,7 @@ class ApplicationController < ActionController::Base
end
def after_sign_out_path_for(resource)
current_application_settings.after_sign_out_path || new_user_session_path
current_application_settings.after_sign_out_path.presence || new_user_session_path
end
def abilities
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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