Commit b165b097 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into ce-7-to-ee

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>

Conflicts:
	LICENSE
	VERSION
	app/controllers/omniauth_callbacks_controller.rb
	app/helpers/application_helper.rb
	app/helpers/merge_requests_helper.rb
	app/models/group.rb
	app/models/project.rb
	app/models/project_team.rb
	app/views/admin/groups/edit.html.haml
	app/views/groups/_projects.html.haml
	app/views/groups/edit.html.haml
	db/schema.rb
	doc/install/installation.md
	doc/integration/README.md
	lib/gitlab/git_access.rb
	lib/gitlab/markdown.rb
	spec/helpers/merge_requests_helper.rb
	spec/models/merge_request_spec.rb
parents e2cd20cc e44e2316
...@@ -21,6 +21,7 @@ config/gitlab.yml ...@@ -21,6 +21,7 @@ config/gitlab.yml
config/database.yml config/database.yml
config/initializers/omniauth.rb config/initializers/omniauth.rb
config/initializers/rack_attack.rb config/initializers/rack_attack.rb
config/initializers/smtp_settings.rb
config/unicorn.rb config/unicorn.rb
config/resque.yml config/resque.yml
config/aws.yml config/aws.yml
......
...@@ -17,3 +17,10 @@ targets: ...@@ -17,3 +17,10 @@ targets:
- libicu52 - libicu52
- libpcre3 - libpcre3
- git - git
centos-6:
build_dependencies:
- libicu-devel
dependencies:
- libicu
- pcre
- git
...@@ -3,18 +3,22 @@ env: ...@@ -3,18 +3,22 @@ env:
global: global:
- TRAVIS=true - TRAVIS=true
matrix: matrix:
- TASK=spinach DB=mysql - TASK=spinach_project DB=mysql
- TASK=spinach_other DB=mysql
- TASK=spec:api DB=mysql - TASK=spec:api DB=mysql
- TASK=spec:feature DB=mysql - TASK=spec:feature DB=mysql
- TASK=spec:other DB=mysql - TASK=spec:other DB=mysql
- TASK=jasmine:ci DB=mysql - TASK=jasmine:ci DB=mysql
- TASK=spinach DB=postgresql - TASK=spinach_project DB=postgresql
- TASK=spinach_other DB=postgresql
- TASK=spec:api DB=postgresql - TASK=spec:api DB=postgresql
- TASK=spec:feature DB=postgresql - TASK=spec:feature DB=postgresql
- TASK=spec:other DB=postgresql - TASK=spec:other DB=postgresql
- TASK=jasmine:ci DB=postgresql - TASK=jasmine:ci DB=postgresql
before_install: before_install:
- sudo apt-get install libicu-dev -y - sudo apt-get install libicu-dev -y
install:
- "bundle install --deployment --without production"
branches: branches:
only: only:
- 'master' - 'master'
......
v 7.0.0
- The CPU no longer overheats when you hold down the spacebar
- Improve edit file UI
- Add ability to upload group avatar when create
- Protected branch cannot be removed
- Developers can remove normal branches with UI
- Remove branch via API (sponsored by O'Reilly Media)
- Move protected branches page to Project settings area
- Redirect to Files view when create new branch via UI
- Drag and drop upload of image in every markdown-area (Earle Randolph Bunao and Neil Francis Calabroso)
- Refactor the markdown relative links processing
- Make it easier to implement other CI services for GitLab
- Group masters can create projects in group
- Deprecate ruby 1.9.3 support
- Only masters can rewrite/remove git tags
- Add X-Frame-Options SAMEORIGIN to Nginx config so Sidekiq admin is visible
- UI improvements
- Case-insensetive search for issues
- Update to rails 4.1
- Improve performance of application for projects and groups with a lot of members
- Formally support Ruby 2.1
- Include Nginx gitlab-ssl config
- Add manual language detection for highlight.js
- Added example.com/:username routing
- Show notice if your profile is public
- UI improvements for mobile devices
- Improve diff rendering performance
- Drag-n-drop for issues and merge requests between states at milestone page
- Fix '0 commits' message for huge repositories on project home page
- Prevent 500 error page when visit commit page from large repo
- Add notice about huge push over http to unicorn config
- File action in satellites uses default 30 seconds timeout instead of old 10 seconds one
- Overall performance improvements
- Skip init script check on omnibus-gitlab
- Be more selective when killing stray Sidekiqs
- Check LDAP user filter during sign-in
- Remove wall feature (no data loss - you can take it from database)
- Dont expose user emails via API unless you are admin
- Detect issues closed by Merge Request description
- Better email subject lines from email on push service (Alex Elman)
- Enable identicon for gravatar be default
v 6.9.2
- Revert the commit that broke the LDAP user filter
v 6.9.1
- Fix scroll to highlighted line
- Fix the pagination on load for commits page
v 6.9.0 v 6.9.0
- Store Rails cache data in the Redis `cache:gitlab` namespace - Store Rails cache data in the Redis `cache:gitlab` namespace
- Adjust MySQL limits for existing installations - Adjust MySQL limits for existing installations
...@@ -18,6 +67,8 @@ v 6.9.0 ...@@ -18,6 +67,8 @@ v 6.9.0
- Accept merge request via API (sponsored by O'Reilly Media) - Accept merge request via API (sponsored by O'Reilly Media)
- Add more access checks during API calls - Add more access checks during API calls
- Block SSH access for 'disabled' Active Directory users - Block SSH access for 'disabled' Active Directory users
- Labels for merge requests (Drew Blessing)
- Threaded emails by setting a Message-ID (Philip Blatter)
v 6.8.1 v 6.8.1
- Bump required gitlab-shell version to 1.9.3 - Bump required gitlab-shell version to 1.9.3
......
...@@ -24,16 +24,11 @@ Issues and merge requests should be in English and contain appropriate language ...@@ -24,16 +24,11 @@ Issues and merge requests should be in English and contain appropriate language
To get support for your particular problem please use the channels as detailed in the [getting help section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#getting-help). Professional [support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from [GitLab.com](http://www.gitlab.com/). To get support for your particular problem please use the channels as detailed in the [getting help section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#getting-help). Professional [support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from [GitLab.com](http://www.gitlab.com/).
The [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) is only for obvious errors in the latest [stable or development release of GitLab](MAINTENANCE.md). The [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) is only for obvious errors in the latest [stable or development release of GitLab](MAINTENANCE.md). If something is wrong but it is not a regression compared to older versions of GitLab please do not open an issue but a feature request. When submitting an issue please conform to the issue submission guidelines listed below. Not all issues will be addressed and your issue is more likely to be addressed if you submit a merge request which partially or fully addresses the issue.
If something is wrong but it is not a regression compared to older versions of GitLab please do not open an issue but a feature request.
When submitting an issue please conform to the issue submission guidelines listed below.
Not all issues will be addressed and your issue is more likely to be addressed if you submit a merge request which partially or fully addresses the issue.
Issues can be filed either at [gitlab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues) or [github.com](https://github.com/gitlabhq/gitlabhq/issues). Issues can be filed either at [gitlab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues) or [github.com](https://github.com/gitlabhq/gitlabhq/issues).
Do not use the issue tracker for feature requests. Do not use the issue tracker for feature requests. We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose. Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple.
We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose.
Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple.
Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there. Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there.
...@@ -42,16 +37,16 @@ Please send a merge request with a tested solution or a merge request with a fai ...@@ -42,16 +37,16 @@ Please send a merge request with a tested solution or a merge request with a fai
**[Search the issues](https://gitlab.com/gitlab-org/gitlab-ce/issues)** for similar entries before submitting your own, there's a good chance somebody else had the same issue. Show your support with `:+1:` and/or join the discussion. Please submit issues in the following format (as the first post): **[Search the issues](https://gitlab.com/gitlab-org/gitlab-ce/issues)** for similar entries before submitting your own, there's a good chance somebody else had the same issue. Show your support with `:+1:` and/or join the discussion. Please submit issues in the following format (as the first post):
1. **Summary:** Summarize your issue in one sentence (what goes wrong, what did you expect to happen) 1. **Summary:** Summarize your issue in one sentence (what goes wrong, what did you expect to happen)
2. **Steps to reproduce:** How can we reproduce the issue, preferably on the [GitLab development virtual machine with vagrant](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/doc/development.md) (start your issue with: `vagrant destroy && vagrant up && vagrant ssh`) 1. **Steps to reproduce:** How can we reproduce the issue, preferably on the [GitLab development virtual machine with vagrant](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/doc/development.md) (start your issue with: `vagrant destroy && vagrant up && vagrant ssh`)
3. **Expected behavior:** Describe your issue in detail 1. **Expected behavior:** Describe your issue in detail
4. **Observed behavior** 1. **Observed behavior**
5. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise. 1. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise.
6. **Output of checks** 1. **Output of checks**
* Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production`); we will only investigate if the tests are passing * Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production`); we will only investigate if the tests are passing
* Version of GitLab you are running; we will only investigate issues in the latest stable and development releases as per the [maintenance policy](MAINTENANCE.md) * Version of GitLab you are running; we will only investigate issues in the latest stable and development releases as per the [maintenance policy](MAINTENANCE.md)
* Add the last commit sha1 of the GitLab version you used to replicate the issue (obtainable from the help page) * Add the last commit sha1 of the GitLab version you used to replicate the issue (obtainable from the help page)
* Describe your setup (use relevant parts from `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`) * Describe your setup (use relevant parts from `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
7. **Possible fixes**: If you can, link to the line of code that might be responsible for the problem 1. **Possible fixes**: If you can, link to the line of code that might be responsible for the problem
## Merge requests ## Merge requests
...@@ -78,7 +73,7 @@ If you can, please submit a merge request with the fix or improvements including ...@@ -78,7 +73,7 @@ If you can, please submit a merge request with the fix or improvements including
1. Be prepared to answer questions and incorporate feedback even if requests for this arrive weeks or months after your MR submittion 1. Be prepared to answer questions and incorporate feedback even if requests for this arrive weeks or months after your MR submittion
1. If your MR touches code that executes shell commands, make sure it adheres to the [shell command guidelines]( doc/development/shell_commands.md). 1. If your MR touches code that executes shell commands, make sure it adheres to the [shell command guidelines]( doc/development/shell_commands.md).
The **official merge window** is in the beginning of the month from the 1st to the 7th day of the month. The best time to submit a MR and get feedback fast. Before this time the GitLab.com team is still dealing with work that is created by the monthly release such as assisting subscribers with upgrade issues, the release of Enterprise Edition and the upgrade of GitLab Cloud. After the 7th it is already getting closer to the release date of the next version. This means there is less time to fix the issues created by merging large new features. The **official merge window** is in the beginning of the month from the 1st to the 7th day of the month. The best time to submit a MR and get feedback fast. Before this time the GitLab B.V. team is still dealing with work that is created by the monthly release such as assisting subscribers with upgrade issues, the release of Enterprise Edition and the upgrade of GitLab Cloud. After the 7th it is already getting closer to the release date of the next version. This means there is less time to fix the issues created by merging large new features.
Please keep the change in a single MR **as small as possible**. If you want to contribute a large feature think very hard what the minimum viable change is. Can you split functionality? Can you only submit the backend/API code? Can you start with a very simple UI? The smaller a MR is the more likely it is it will be merged, after that you can send more MR's to enhance it. Please keep the change in a single MR **as small as possible**. If you want to contribute a large feature think very hard what the minimum viable change is. Can you split functionality? Can you only submit the backend/API code? Can you start with a very simple UI? The smaller a MR is the more likely it is it will be merged, after that you can send more MR's to enhance it.
...@@ -87,10 +82,10 @@ For examples of feedback on merge requests please look at already [closed merge ...@@ -87,10 +82,10 @@ For examples of feedback on merge requests please look at already [closed merge
**Please format your merge request description as follows:** **Please format your merge request description as follows:**
1. What does this MR do? 1. What does this MR do?
2. Are there points in the code the reviewer needs to double check? 1. Are there points in the code the reviewer needs to double check?
3. Why was this MR needed? 1. Why was this MR needed?
4. What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)? 1. What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)?
5. Screenshots (If appropiate) 1. Screenshots (If appropiate)
## Contribution acceptance criteria ## Contribution acceptance criteria
...@@ -106,11 +101,16 @@ For examples of feedback on merge requests please look at already [closed merge ...@@ -106,11 +101,16 @@ For examples of feedback on merge requests please look at already [closed merge
1. It conforms to the following style guides 1. It conforms to the following style guides
## Style guides ## Style guides
1. [Ruby](https://github.com/bbatsov/ruby-style-guide)
1. [Rails](https://github.com/bbatsov/rails-style-guide) 1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
1. [Formatting](https://github.com/thoughtbot/guides/tree/master/style#formatting) Important sections include [Source Code Layout](https://github.com/bbatsov/ruby-style-guide#source-code-layout)
1. [Naming](https://github.com/thoughtbot/guides/tree/master/style#naming) and [Naming](https://github.com/bbatsov/ruby-style-guide#naming). Use:
1. [Testing](https://github.com/thoughtbot/guides/tree/master/style#testing) - multi-line method chaining style **Option B**: dot `.` on previous line
1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style#coffeescript) - string literal quoting style **Option A**: single quoted by default
1. [Shell commands](doc/development/shell_commands.md) 1. [Rails](https://github.com/bbatsov/rails-style-guide)
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide) 1. [Testing](https://github.com/thoughtbot/guides/tree/master/style#testing)
1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style#coffeescript)
1. [Shell commands](doc/development/shell_commands.md) created by GitLab contributors to enhance security
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
This is also the style used by linting tools such as [Rubocop](https://github.com/bbatsov/rubocop), PullReview[https://www.pullreview.com/] and [Hound CI](https://houndci.com).
...@@ -8,11 +8,14 @@ def linux_only(require_as) ...@@ -8,11 +8,14 @@ def linux_only(require_as)
RUBY_PLATFORM.include?('linux') && require_as RUBY_PLATFORM.include?('linux') && require_as
end end
gem "rails", "~> 4.0.0" gem "rails", "~> 4.1.0"
gem "protected_attributes" gem "protected_attributes"
gem 'rails-observers' gem 'rails-observers'
# Make links from text
gem 'rails_autolink', '~> 1.1'
# Default values for AR models # Default values for AR models
gem "default_value_for", "~> 3.0.0" gem "default_value_for", "~> 3.0.0"
...@@ -30,7 +33,7 @@ gem 'omniauth-github' ...@@ -30,7 +33,7 @@ gem 'omniauth-github'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem "gitlab_git", '~> 5.8' gem "gitlab_git", '~> 6.0'
# Ruby/Rack Git Smart-HTTP Server Handler # Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack' gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
...@@ -51,9 +54,6 @@ gem "grape", "~> 0.6.1" ...@@ -51,9 +54,6 @@ gem "grape", "~> 0.6.1"
gem "grape-entity", "~> 0.4.2" gem "grape-entity", "~> 0.4.2"
gem 'rack-cors', require: 'rack/cors' gem 'rack-cors', require: 'rack/cors'
# Email validation
gem "email_validator", "~> 1.4.0", :require => 'email_validator/strict'
# Format dates and times # Format dates and times
# based on human-friendly examples # based on human-friendly examples
gem "stamp" gem "stamp"
...@@ -70,6 +70,9 @@ gem "haml-rails" ...@@ -70,6 +70,9 @@ gem "haml-rails"
# Files attachments # Files attachments
gem "carrierwave" gem "carrierwave"
# Drag and Drop UI
gem 'dropzonejs-rails'
# for aws storage # for aws storage
gem "fog", "~> 1.14", group: :aws gem "fog", "~> 1.14", group: :aws
gem "unf", group: :aws gem "unf", group: :aws
...@@ -83,6 +86,7 @@ gem "seed-fu" ...@@ -83,6 +86,7 @@ gem "seed-fu"
# Markdown to HTML # Markdown to HTML
gem "redcarpet", "~> 2.2.2" gem "redcarpet", "~> 2.2.2"
gem "github-markup" gem "github-markup"
gem "org-ruby" # For rendering .org files
# Diffs # Diffs
gem 'diffy', '~> 3.0.3' gem 'diffy', '~> 3.0.3'
...@@ -153,6 +157,9 @@ gem "rack-attack" ...@@ -153,6 +157,9 @@ gem "rack-attack"
# Ace editor # Ace editor
gem 'ace-rails-ap' gem 'ace-rails-ap'
# Semantic UI Sass for Sidebar
gem 'semantic-ui-sass', '~> 0.16.1.0'
gem "sass-rails", '~> 4.0.2' gem "sass-rails", '~> 4.0.2'
gem "coffee-rails" gem "coffee-rails"
gem "uglifier" gem "uglifier"
...@@ -164,6 +171,7 @@ gem 'select2-rails' ...@@ -164,6 +171,7 @@ gem 'select2-rails'
gem 'jquery-atwho-rails', "~> 0.3.3" gem 'jquery-atwho-rails', "~> 0.3.3"
gem "jquery-rails" gem "jquery-rails"
gem "jquery-ui-rails" gem "jquery-ui-rails"
gem "jquery-scrollto-rails"
gem "raphael-rails", "~> 2.1.2" gem "raphael-rails", "~> 2.1.2"
gem 'bootstrap-sass', '~> 3.0' gem 'bootstrap-sass', '~> 3.0'
gem "font-awesome-rails", '~> 3.2' gem "font-awesome-rails", '~> 3.2'
...@@ -195,7 +203,7 @@ group :development, :test do ...@@ -195,7 +203,7 @@ group :development, :test do
# gem 'rails-dev-tweaks' # gem 'rails-dev-tweaks'
gem 'spinach-rails' gem 'spinach-rails'
gem "rspec-rails" gem "rspec-rails"
gem "capybara" gem "capybara", '~> 2.2.1'
gem "pry" gem "pry"
gem "awesome_print" gem "awesome_print"
gem "database_cleaner" gem "database_cleaner"
...@@ -203,7 +211,7 @@ group :development, :test do ...@@ -203,7 +211,7 @@ group :development, :test do
gem 'factory_girl_rails' gem 'factory_girl_rails'
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826) # Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
gem 'minitest', '~> 4.7.0' gem 'minitest', '~> 5.3.0'
# Generate Fake data # Generate Fake data
gem "ffaker" gem "ffaker"
...@@ -218,9 +226,9 @@ group :development, :test do ...@@ -218,9 +226,9 @@ group :development, :test do
gem 'rb-inotify', require: linux_only('rb-inotify') gem 'rb-inotify', require: linux_only('rb-inotify')
# PhantomJS driver for Capybara # PhantomJS driver for Capybara
gem 'poltergeist', '~> 1.4.1' gem 'poltergeist', '~> 1.5.1'
gem 'jasmine', '2.0.0.rc5' gem 'jasmine', '2.0.2'
gem "spring", '1.1.1' gem "spring", '1.1.1'
gem "spring-commands-rspec", '1.0.1' gem "spring-commands-rspec", '1.0.1'
...@@ -236,5 +244,5 @@ group :test do ...@@ -236,5 +244,5 @@ group :test do
end end
group :production do group :production do
gem "gitlab_meta", '6.0' gem "gitlab_meta", '7.0'
end end
...@@ -2,37 +2,39 @@ GEM ...@@ -2,37 +2,39 @@ GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
ace-rails-ap (2.0.1) ace-rails-ap (2.0.1)
actionmailer (4.0.5) actionmailer (4.1.1)
actionpack (= 4.0.5) actionpack (= 4.1.1)
actionview (= 4.1.1)
mail (~> 2.5.4) mail (~> 2.5.4)
actionpack (4.0.5) actionpack (4.1.1)
activesupport (= 4.0.5) actionview (= 4.1.1)
builder (~> 3.1.0) activesupport (= 4.1.1)
erubis (~> 2.7.0)
rack (~> 1.5.2) rack (~> 1.5.2)
rack-test (~> 0.6.2) rack-test (~> 0.6.2)
activemodel (4.0.5) actionview (4.1.1)
activesupport (= 4.0.5) activesupport (= 4.1.1)
builder (~> 3.1.0) builder (~> 3.1)
activerecord (4.0.5) erubis (~> 2.7.0)
activemodel (= 4.0.5) activemodel (4.1.1)
activerecord-deprecated_finders (~> 1.0.2) activesupport (= 4.1.1)
activesupport (= 4.0.5) builder (~> 3.1)
arel (~> 4.0.0) activerecord (4.1.1)
activerecord-deprecated_finders (1.0.3) activemodel (= 4.1.1)
activesupport (4.0.5) activesupport (= 4.1.1)
arel (~> 5.0.0)
activesupport (4.1.1)
i18n (~> 0.6, >= 0.6.9) i18n (~> 0.6, >= 0.6.9)
minitest (~> 4.2) json (~> 1.7, >= 1.7.7)
multi_json (~> 1.3) minitest (~> 5.1)
thread_safe (~> 0.1) thread_safe (~> 0.1)
tzinfo (~> 0.3.37) tzinfo (~> 1.1)
acts-as-taggable-on (2.4.1) acts-as-taggable-on (2.4.1)
rails (>= 3, < 5) rails (>= 3, < 5)
addressable (2.3.5) addressable (2.3.5)
annotate (2.6.0) annotate (2.6.0)
activerecord (>= 2.3.0) activerecord (>= 2.3.0)
rake (>= 0.8.7) rake (>= 0.8.7)
arel (4.0.2) arel (5.0.1.20140414130214)
asciidoctor (0.1.4) asciidoctor (0.1.4)
awesome_print (1.2.0) awesome_print (1.2.0)
axiom-types (0.0.5) axiom-types (0.0.5)
...@@ -46,8 +48,8 @@ GEM ...@@ -46,8 +48,8 @@ GEM
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
bootstrap-sass (3.0.3.0) bootstrap-sass (3.0.3.0)
sass (~> 3.2) sass (~> 3.2)
builder (3.1.4) builder (3.2.2)
capybara (2.1.0) capybara (2.2.1)
mime-types (>= 1.16) mime-types (>= 1.16)
nokogiri (>= 1.3.3) nokogiri (>= 1.3.3)
rack (>= 1.0.0) rack (>= 1.0.0)
...@@ -60,7 +62,7 @@ GEM ...@@ -60,7 +62,7 @@ GEM
celluloid (0.15.2) celluloid (0.15.2)
timers (~> 1.1.0) timers (~> 1.1.0)
charlock_holmes (0.6.9.4) charlock_holmes (0.6.9.4)
cliver (0.2.2) cliver (0.3.2)
code_analyzer (0.4.3) code_analyzer (0.4.3)
sexp_processor sexp_processor
coderay (1.1.0) coderay (1.1.0)
...@@ -87,7 +89,7 @@ GEM ...@@ -87,7 +89,7 @@ GEM
d3_rails (3.1.10) d3_rails (3.1.10)
railties (>= 3.1.0) railties (>= 3.1.0)
daemons (1.1.9) daemons (1.1.9)
database_cleaner (1.2.0) database_cleaner (1.3.0)
debug_inspector (0.0.2) debug_inspector (0.0.2)
default_value_for (3.0.0) default_value_for (3.0.0)
activerecord (>= 3.2.0, < 5.0) activerecord (>= 3.2.0, < 5.0)
...@@ -103,11 +105,11 @@ GEM ...@@ -103,11 +105,11 @@ GEM
diffy (3.0.3) diffy (3.0.3)
docile (1.1.1) docile (1.1.1)
dotenv (0.9.0) dotenv (0.9.0)
dropzonejs-rails (0.4.14)
rails (> 3.1)
email_spec (1.5.0) email_spec (1.5.0)
launchy (~> 2.1) launchy (~> 2.1)
mail (~> 2.2) mail (~> 2.2)
email_validator (1.4.0)
activemodel
emoji (1.0.1) emoji (1.0.1)
json json
enumerize (0.7.0) enumerize (0.7.0)
...@@ -162,7 +164,7 @@ GEM ...@@ -162,7 +164,7 @@ GEM
multi_json multi_json
gitlab-grack (2.0.0.pre) gitlab-grack (2.0.0.pre)
rack (~> 1.5.1) rack (~> 1.5.1)
gitlab-grit (2.6.7) gitlab-grit (2.6.9)
charlock_holmes (~> 0.6) charlock_holmes (~> 0.6)
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
mime-types (~> 1.15) mime-types (~> 1.15)
...@@ -173,13 +175,13 @@ GEM ...@@ -173,13 +175,13 @@ GEM
mime-types (~> 1.19) mime-types (~> 1.19)
gitlab_emoji (0.0.1.1) gitlab_emoji (0.0.1.1)
emoji (~> 1.0.1) emoji (~> 1.0.1)
gitlab_git (5.8.0) gitlab_git (6.0.0)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.6) charlock_holmes (~> 0.6)
gitlab-grit (~> 2.6) gitlab-grit (~> 2.6)
gitlab-linguist (~> 3.0) gitlab-linguist (~> 3.0)
rugged (~> 0.19.0) rugged (~> 0.19.0)
gitlab_meta (6.0) gitlab_meta (7.0)
gitlab_omniauth-ldap (1.0.4) gitlab_omniauth-ldap (1.0.4)
net-ldap (~> 0.3.1) net-ldap (~> 0.3.1)
omniauth (~> 1.0) omniauth (~> 1.0)
...@@ -221,13 +223,13 @@ GEM ...@@ -221,13 +223,13 @@ GEM
guard-spinach (0.0.2) guard-spinach (0.0.2)
guard (>= 1.1) guard (>= 1.1)
spinach spinach
haml (4.0.4) haml (4.0.5)
tilt tilt
haml-rails (0.5.1) haml-rails (0.5.3)
actionpack (~> 4.0.0) actionpack (>= 4.0.1)
activesupport (~> 4.0.0) activesupport (>= 4.0.1)
haml (>= 3.1, < 5.0) haml (>= 3.1, < 5.0)
railties (~> 4.0.0) railties (>= 4.0.1)
hashie (2.0.5) hashie (2.0.5)
hike (1.2.3) hike (1.2.3)
hipchat (0.14.0) hipchat (0.14.0)
...@@ -240,16 +242,18 @@ GEM ...@@ -240,16 +242,18 @@ GEM
httpauth (0.2.0) httpauth (0.2.0)
i18n (0.6.9) i18n (0.6.9)
ice_nine (0.10.0) ice_nine (0.10.0)
jasmine (2.0.0.rc5) jasmine (2.0.2)
jasmine-core (~> 2.0.0.rc5) jasmine-core (~> 2.0.0)
phantomjs phantomjs
rack (>= 1.2.1) rack (>= 1.2.1)
rake rake
jasmine-core (2.0.0.rc5) jasmine-core (2.0.0)
jquery-atwho-rails (0.3.3) jquery-atwho-rails (0.3.3)
jquery-rails (3.1.0) jquery-rails (3.1.0)
railties (>= 3.0, < 5.0) railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0) thor (>= 0.14, < 2.0)
jquery-scrollto-rails (1.4.3)
railties (> 3.1, < 5.0)
jquery-turbolinks (2.0.1) jquery-turbolinks (2.0.1)
railties (>= 3.1.0) railties (>= 3.1.0)
turbolinks turbolinks
...@@ -277,18 +281,18 @@ GEM ...@@ -277,18 +281,18 @@ GEM
treetop (~> 1.4.8) treetop (~> 1.4.8)
method_source (0.8.2) method_source (0.8.2)
mime-types (1.25.1) mime-types (1.25.1)
mini_portile (0.5.3) mini_portile (0.6.0)
minitest (4.7.5) minitest (5.3.4)
multi_json (1.10.0) multi_json (1.10.1)
multi_xml (0.5.5) multi_xml (0.5.5)
multipart-post (1.2.0) multipart-post (1.2.0)
mysql2 (0.3.11) mysql2 (0.3.16)
net-ldap (0.3.1) net-ldap (0.3.1)
net-scp (1.1.2) net-scp (1.1.2)
net-ssh (>= 2.6.5) net-ssh (>= 2.6.5)
net-ssh (2.8.0) net-ssh (2.8.0)
nokogiri (1.6.1) nokogiri (1.6.2.1)
mini_portile (~> 0.5.0) mini_portile (= 0.6.0)
nprogress-rails (0.1.2.3) nprogress-rails (0.1.2.3)
oauth (0.4.7) oauth (0.4.7)
oauth2 (0.8.1) oauth2 (0.8.1)
...@@ -315,12 +319,14 @@ GEM ...@@ -315,12 +319,14 @@ GEM
omniauth-twitter (1.0.1) omniauth-twitter (1.0.1)
multi_json (~> 1.3) multi_json (~> 1.3)
omniauth-oauth (~> 1.0) omniauth-oauth (~> 1.0)
org-ruby (0.9.6)
rubypants (>= 0.2.0)
orm_adapter (0.5.0) orm_adapter (0.5.0)
pg (0.15.1) pg (0.15.1)
phantomjs (1.9.2.0) phantomjs (1.9.2.0)
poltergeist (1.4.1) poltergeist (1.5.1)
capybara (~> 2.1.0) capybara (~> 2.1)
cliver (~> 0.2.1) cliver (~> 0.3.1)
multi_json (~> 1.0) multi_json (~> 1.0)
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
polyglot (0.3.4) polyglot (0.3.4)
...@@ -349,16 +355,20 @@ GEM ...@@ -349,16 +355,20 @@ GEM
rack rack
rack-test (0.6.2) rack-test (0.6.2)
rack (>= 1.0) rack (>= 1.0)
rails (4.0.5) rails (4.1.1)
actionmailer (= 4.0.5) actionmailer (= 4.1.1)
actionpack (= 4.0.5) actionpack (= 4.1.1)
activerecord (= 4.0.5) actionview (= 4.1.1)
activesupport (= 4.0.5) activemodel (= 4.1.1)
activerecord (= 4.1.1)
activesupport (= 4.1.1)
bundler (>= 1.3.0, < 2.0) bundler (>= 1.3.0, < 2.0)
railties (= 4.0.5) railties (= 4.1.1)
sprockets-rails (~> 2.0.0) sprockets-rails (~> 2.0)
rails-observers (0.1.2) rails-observers (0.1.2)
activemodel (~> 4.0) activemodel (~> 4.0)
rails_autolink (1.1.6)
rails (> 3.1)
rails_best_practices (1.14.4) rails_best_practices (1.14.4)
activesupport activesupport
awesome_print awesome_print
...@@ -368,13 +378,13 @@ GEM ...@@ -368,13 +378,13 @@ GEM
i18n i18n
require_all require_all
ruby-progressbar ruby-progressbar
railties (4.0.5) railties (4.1.1)
actionpack (= 4.0.5) actionpack (= 4.1.1)
activesupport (= 4.0.5) activesupport (= 4.1.1)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
raindrops (0.12.0) raindrops (0.12.0)
rake (10.3.1) rake (10.3.2)
raphael-rails (2.1.2) raphael-rails (2.1.2)
rb-fsevent (0.9.3) rb-fsevent (0.9.3)
rb-inotify (0.9.2) rb-inotify (0.9.2)
...@@ -423,6 +433,7 @@ GEM ...@@ -423,6 +433,7 @@ GEM
rspec-mocks (~> 2.14.0) rspec-mocks (~> 2.14.0)
ruby-progressbar (1.2.0) ruby-progressbar (1.2.0)
rubyntlm (0.1.1) rubyntlm (0.1.1)
rubypants (0.2.0)
rugged (0.19.0) rugged (0.19.0)
safe_yaml (0.9.7) safe_yaml (0.9.7)
sanitize (2.1.0) sanitize (2.1.0)
...@@ -436,11 +447,13 @@ GEM ...@@ -436,11 +447,13 @@ GEM
sdoc (0.3.20) sdoc (0.3.20)
json (>= 1.1.3) json (>= 1.1.3)
rdoc (~> 3.10) rdoc (~> 3.10)
seed-fu (2.3.0) seed-fu (2.3.1)
activerecord (>= 3.1, < 4.1) activerecord (>= 3.1, < 4.2)
activesupport (>= 3.1, < 4.1) activesupport (>= 3.1, < 4.2)
select2-rails (3.5.2) select2-rails (3.5.2)
thor (~> 0.14) thor (~> 0.14)
semantic-ui-sass (0.16.1.0)
sass (~> 3.2)
settingslogic (2.0.9) settingslogic (2.0.9)
sexp_processor (4.4.0) sexp_processor (4.4.0)
shoulda-matchers (2.1.0) shoulda-matchers (2.1.0)
...@@ -484,7 +497,7 @@ GEM ...@@ -484,7 +497,7 @@ GEM
multi_json (~> 1.0) multi_json (~> 1.0)
rack (~> 1.0) rack (~> 1.0)
tilt (~> 1.1, != 1.3.0) tilt (~> 1.1, != 1.3.0)
sprockets-rails (2.0.1) sprockets-rails (2.1.3)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
sprockets (~> 2.8) sprockets (~> 2.8)
...@@ -503,7 +516,7 @@ GEM ...@@ -503,7 +516,7 @@ GEM
eventmachine (>= 1.0.0) eventmachine (>= 1.0.0)
rack (>= 1.0.0) rack (>= 1.0.0)
thor (0.19.1) thor (0.19.1)
thread_safe (0.3.3) thread_safe (0.3.4)
tilt (1.4.1) tilt (1.4.1)
timers (1.1.0) timers (1.1.0)
tinder (1.9.3) tinder (1.9.3)
...@@ -525,7 +538,8 @@ GEM ...@@ -525,7 +538,8 @@ GEM
eventmachine (>= 0.12.8) eventmachine (>= 0.12.8)
http_parser.rb (~> 0.5.1) http_parser.rb (~> 0.5.1)
simple_oauth (~> 0.1.4) simple_oauth (~> 0.1.4)
tzinfo (0.3.39) tzinfo (1.2.1)
thread_safe (~> 0.1)
uglifier (2.3.2) uglifier (2.3.2)
execjs (>= 0.3.0) execjs (>= 0.3.0)
json (>= 1.8.0) json (>= 1.8.0)
...@@ -550,7 +564,7 @@ GEM ...@@ -550,7 +564,7 @@ GEM
webmock (1.16.0) webmock (1.16.0)
addressable (>= 2.2.7) addressable (>= 2.2.7)
crack (>= 0.3.2) crack (>= 0.3.2)
websocket-driver (0.3.1) websocket-driver (0.3.3)
xpath (2.0.0) xpath (2.0.0)
nokogiri (~> 1.3) nokogiri (~> 1.3)
...@@ -566,7 +580,7 @@ DEPENDENCIES ...@@ -566,7 +580,7 @@ DEPENDENCIES
better_errors better_errors
binding_of_caller binding_of_caller
bootstrap-sass (~> 3.0) bootstrap-sass (~> 3.0)
capybara capybara (~> 2.2.1)
carrierwave carrierwave
coffee-rails coffee-rails
colored colored
...@@ -577,8 +591,8 @@ DEPENDENCIES ...@@ -577,8 +591,8 @@ DEPENDENCIES
devise (= 3.0.4) devise (= 3.0.4)
devise-async (= 0.8.0) devise-async (= 0.8.0)
diffy (~> 3.0.3) diffy (~> 3.0.3)
dropzonejs-rails
email_spec email_spec
email_validator (~> 1.4.0)
enumerize enumerize
factory_girl_rails factory_girl_rails
ffaker ffaker
...@@ -591,8 +605,8 @@ DEPENDENCIES ...@@ -591,8 +605,8 @@ DEPENDENCIES
gitlab-grack (~> 2.0.0.pre) gitlab-grack (~> 2.0.0.pre)
gitlab-linguist (~> 3.0.0) gitlab-linguist (~> 3.0.0)
gitlab_emoji (~> 0.0.1.1) gitlab_emoji (~> 0.0.1.1)
gitlab_git (~> 5.8) gitlab_git (~> 6.0)
gitlab_meta (= 6.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (= 1.0.4) gitlab_omniauth-ldap (= 1.0.4)
gollum-lib (~> 3.0.0) gollum-lib (~> 3.0.0)
gon (~> 5.0.0) gon (~> 5.0.0)
...@@ -604,15 +618,16 @@ DEPENDENCIES ...@@ -604,15 +618,16 @@ DEPENDENCIES
haml-rails haml-rails
hipchat (~> 0.14.0) hipchat (~> 0.14.0)
httparty httparty
jasmine (= 2.0.0.rc5) jasmine (= 2.0.2)
jquery-atwho-rails (~> 0.3.3) jquery-atwho-rails (~> 0.3.3)
jquery-rails jquery-rails
jquery-scrollto-rails
jquery-turbolinks jquery-turbolinks
jquery-ui-rails jquery-ui-rails
kaminari (~> 0.15.1) kaminari (~> 0.15.1)
launchy launchy
letter_opener letter_opener
minitest (~> 4.7.0) minitest (~> 5.3.0)
mysql2 mysql2
net-ldap net-ldap
nprogress-rails nprogress-rails
...@@ -620,16 +635,18 @@ DEPENDENCIES ...@@ -620,16 +635,18 @@ DEPENDENCIES
omniauth-github omniauth-github
omniauth-google-oauth2 omniauth-google-oauth2
omniauth-twitter omniauth-twitter
org-ruby
pg pg
poltergeist (~> 1.4.1) poltergeist (~> 1.5.1)
protected_attributes protected_attributes
pry pry
quiet_assets (~> 1.0.1) quiet_assets (~> 1.0.1)
rack-attack rack-attack
rack-cors rack-cors
rack-mini-profiler rack-mini-profiler
rails (~> 4.0.0) rails (~> 4.1.0)
rails-observers rails-observers
rails_autolink (~> 1.1)
rails_best_practices rails_best_practices
raphael-rails (~> 2.1.2) raphael-rails (~> 2.1.2)
rb-fsevent rb-fsevent
...@@ -642,6 +659,7 @@ DEPENDENCIES ...@@ -642,6 +659,7 @@ DEPENDENCIES
sdoc sdoc
seed-fu seed-fu
select2-rails select2-rails
semantic-ui-sass (~> 0.16.1.0)
settingslogic settingslogic
shoulda-matchers (~> 2.1.0) shoulda-matchers (~> 2.1.0)
sidekiq (= 2.17.0) sidekiq (= 2.17.0)
......
# GitLab Maintenance Policy # GitLab Maintenance Policy
GitLab is a fast moving and evolving project. We currently don't have the GitLab is a fast moving and evolving project. We currently don't have the resources to support many releases concurrently. We support exactly one stable release at any given time.
resources to support many releases concurrently. We support exactly one stable
release at any given time.
GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)`.
`(Major).(Minor).(Patch)`.
* **Major version**: Whenever there is something significant or any backwards - **Major version**: Whenever there is something significant or any backwards incompatible changes are introduced to the public API.
incompatible changes are introduced to the public API. - **Minor version**: When new, backwards compatible functionality is introduced to the public API or a minor feature is introduced, or when a set of smaller features is rolled out.
* **Minor version**: When new, backwards compatible functionality is introduced - **Patch number**: When backwards compatible bug fixes are introduced that fix incorrect behavior.
to the public API or a minor feature is introduced, or when a set of smaller
features is rolled out.
* **Patch number**: When backwards compatible bug fixes are introduced that fix
incorrect behavior.
The current stable release will receive security patches and bug fixes The current stable release will receive security patches and bug fixes (eg. `5.0` -> `5.0.1`). Feature releases will mark the next supported stable release where the minor version is increased numerically by increments of one (eg. `5.0 -> 5.1`).
(eg. `5.0` -> `5.0.1`). Feature releases will mark the next supported stable
release where the minor version is increased numerically by increments of one
(eg. `5.0 -> 5.1`).
We encourage everyone to run the latest stable release to ensure that you can easily upgrade to the most secure and feature rich GitLab experience. In order to make sure you can easily run the most recent stable release, we are working hard to keep the update process simple and reliable. We encourage everyone to run the latest stable release to ensure that you can easily upgrade to the most secure and feature rich GitLab experience. In order to make sure you can easily run the most recent stable release, we are working hard to keep the update process simple and reliable.
......
...@@ -13,7 +13,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co ...@@ -13,7 +13,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co
- Monitors all issues for feedback (but especially ones commented on since automatically watching them) - Monitors all issues for feedback (but especially ones commented on since automatically watching them)
- Closes issues with no feedback from the reporter for two weeks - Closes issues with no feedback from the reporter for two weeks
### Merge request officers ### Merge marshal
- Responds to merge requests the issue team mentions them in and monitors for new merge requests - Responds to merge requests the issue team mentions them in and monitors for new merge requests
- Provides feedback to the merge request submitter to improve the merge request (style, tests, etc.) - Provides feedback to the merge request submitter to improve the merge request (style, tests, etc.)
...@@ -24,9 +24,9 @@ Below we describe the contributing process to GitLab for two reasons. So that co ...@@ -24,9 +24,9 @@ Below we describe the contributing process to GitLab for two reasons. So that co
## Priorities of the issue team ## Priorities of the issue team
1. Mentioning people (critical) 1. Mentioning people (critical)
2. Workflow labels (normal) 1. Workflow labels (normal)
3. Functional labels (minor) 1. Functional labels (minor)
4. Assigning issues (avoid if possible) 1. Assigning issues (avoid if possible)
## Mentioning people ## Mentioning people
...@@ -36,11 +36,11 @@ The most important thing is making sure valid issues receive feedback from the d ...@@ -36,11 +36,11 @@ The most important thing is making sure valid issues receive feedback from the d
Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when 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. Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when 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.
- _Awaiting feedback_: Feedback pending from the reporter - *Awaiting feedback*: Feedback pending from the reporter
- _Awaiting confirmation of fix_: The issue should already be solved in **master** (generally you can avoid this workflow item and just close the issue right away) - *Awaiting confirmation of fix*: The issue should already be solved in **master** (generally you can avoid this workflow item and just close the issue right away)
- _Attached MR_: There is a MR attached and the discussion should happen there - *Attached MR*: There is a MR attached and the discussion should happen there
- We need to let issues stay in sync with the MR's. We can do this with a "Closing #XXXX" or "Fixes #XXXX" comment in the MR. We can't close the issue when there is a merge request because sometimes a MR is not good and we just close the MR, then the issue must stay. - We need to let issues stay in sync with the MR's. We can do this with a "Closing #XXXX" or "Fixes #XXXX" comment in the MR. We can't close the issue when there is a merge request because sometimes a MR is not good and we just close the MR, then the issue must stay.
- _Awaiting developer action/feedback_: Issue needs to be fixed or clarified by a developer - *Awaiting developer action/feedback*: Issue needs to be fixed or clarified by a developer
## Functional labels ## Functional labels
...@@ -51,12 +51,13 @@ These labels describe what development specialities are involved such as: Postgr ...@@ -51,12 +51,13 @@ These labels describe what development specialities are involved such as: Postgr
If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover. If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover.
## Label colors ## Label colors
- Light orange `#fef2c0`: workflow labels for issue team members (awaiting feedback, awaiting confirmation of fix)
- Bright orange `#eb6420`: workflow labels for core team members (attached MR, awaiting developer action/feedback) - Light orange `#fef2c0`: workflow labels for issue team members (awaiting feedback, awaiting confirmation of fix)
- Light blue `#82C5FF`: functional labels - Bright orange `#eb6420`: workflow labels for core team members (attached MR, awaiting developer action/feedback)
- Green labels `#009800`: issues that can generally be ignored. For example, issues given the following labels normally can be closed immediately: - Light blue `#82C5FF`: functional labels
- Feature request (see copy & paste response: [Feature requests](#feature-requests)) - Green labels `#009800`: issues that can generally be ignored. For example, issues given the following labels normally can be closed immediately:
- Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions) - Feature request (see copy & paste response: [Feature requests](#feature-requests))
- Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions)
## Be kind ## Be kind
...@@ -102,8 +103,4 @@ This merge request has been closed because a request for more information has no ...@@ -102,8 +103,4 @@ This merge request has been closed because a request for more information has no
### Accepting merge requests ### Accepting merge requests
Is there a request on [the feature request forum](http://feedback.gitlab.com/forums/176466-general) that is similar to this? Is there a request on [the feature request forum](http://feedback.gitlab.com/forums/176466-general) that is similar to this? If so, can you make a comment with a link to it? Please be aware that new functionality that is not marked [accepting merge/pull requests](http://feedback.gitlab.com/forums/176466-general/status/796455) on the forum might not make it into GitLab. You might be asked to make changes and even after implementing them your feature might still be declined. If you want to reduce the chance of this happening please have a discussion in the forum first.
If so, can you make a comment with a link to it?
Please be aware that new functionality that is not marked [accepting merge/pull requests](http://feedback.gitlab.com/forums/176466-general/status/796455) on the forum might not make it into GitLab.
You might be asked to make changes and even after implementing them your feature might still be declined.
If you want to reduce the chance of this happening please have a discussion in the forum first.
This diff is collapsed.
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#= require jquery.history #= require jquery.history
#= require jquery.waitforimages #= require jquery.waitforimages
#= require jquery.atwho #= require jquery.atwho
#= require jquery.scrollto #= require jquery.scrollTo
#= require jquery.blockUI #= require jquery.blockUI
#= require turbolinks #= require turbolinks
#= require jquery.turbolinks #= require jquery.turbolinks
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#= require underscore #= require underscore
#= require nprogress #= require nprogress
#= require nprogress-turbolinks #= require nprogress-turbolinks
#= require dropzone
#= require semantic-ui/sidebar
#= require_tree . #= require_tree .
window.slugify = (text) -> window.slugify = (text) ->
......
$ -> $ ->
$("body").on "click", ".js-toggler-target", ->
container = $(@).closest(".js-toggler-container")
container.toggleClass("on")
# Toggle button. Show/hide content inside parent container. # Toggle button. Show/hide content inside parent container.
# Button does not change visibility. If button has icon - it changes chevron style. # Button does not change visibility. If button has icon - it changes chevron style.
# #
......
...@@ -26,7 +26,7 @@ class BlobView ...@@ -26,7 +26,7 @@ class BlobView
unless isNaN first_line unless isNaN first_line
$("#tree-content-holder .highlight .line").removeClass("hll") $("#tree-content-holder .highlight .line").removeClass("hll")
$("#LC#{line}").addClass("hll") for line in [first_line..last_line] $("#LC#{line}").addClass("hll") for line in [first_line..last_line]
$("#L#{first_line}").ScrollTo() unless e? $.scrollTo("#L#{first_line}") unless e?
# parse selected lines from hash # parse selected lines from hash
# always return first and last line (initialized to NaN) # always return first and last line (initialized to NaN)
......
...@@ -12,7 +12,7 @@ class CommitsList ...@@ -12,7 +12,7 @@ class CommitsList
$('.loading').hide() $('.loading').hide()
@init: (ref, limit) -> @init: (ref, limit) ->
$(".day-commits-table li.commit").live 'click', (event) -> $("body").on "click", ".day-commits-table li.commit", (event) ->
if event.target.nodeName != "A" if event.target.nodeName != "A"
location.href = $(this).attr("url") location.href = $(this).attr("url")
e.stopPropagation() e.stopPropagation()
......
...@@ -4,7 +4,7 @@ class Dashboard ...@@ -4,7 +4,7 @@ class Dashboard
$(".dash-filter").keyup -> $(".dash-filter").keyup ->
terms = $(this).val() terms = $(this).val()
uiBox = $(this).parents('.ui-box').first() uiBox = $(this).parents('.panel').first()
if terms == "" || terms == undefined if terms == "" || terms == undefined
uiBox.find(".dash-list li").show() uiBox.find(".dash-list li").show()
else else
......
...@@ -21,6 +21,8 @@ class Dispatcher ...@@ -21,6 +21,8 @@ class Dispatcher
Issues.init() Issues.init()
when 'projects:issues:show' when 'projects:issues:show'
new Issue() new Issue()
when 'projects:milestones:show'
new Milestone()
when 'projects:issues:new', 'projects:merge_requests:new' when 'projects:issues:new', 'projects:merge_requests:new'
GitLab.GfmAutoComplete.setup() GitLab.GfmAutoComplete.setup()
when 'dashboard:show' when 'dashboard:show'
...@@ -32,8 +34,6 @@ class Dispatcher ...@@ -32,8 +34,6 @@ class Dispatcher
new Activities() new Activities()
when 'projects:new', 'projects:edit' when 'projects:new', 'projects:edit'
new Project() new Project()
when 'projects:walls:show'
new Wall(project_id)
when 'projects:teams:members:index' when 'projects:teams:members:index'
new TeamMembers() new TeamMembers()
when 'groups:members' when 'groups:members'
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
initChecks: -> initChecks: ->
$(".check_all_issues").click -> $(".check_all_issues").click ->
$(".selected_issue").attr "checked", @checked $(".selected_issue").prop("checked", @checked)
Issues.checkChanged() Issues.checkChanged()
$(".selected_issue").bind "change", Issues.checkChanged $(".selected_issue").bind "change", Issues.checkChanged
......
formatLink = (str) ->
"![" + str.alt + "](" + str.url + ")"
$(document).ready ->
alertClass = "alert alert-danger alert-dismissable div-dropzone-alert"
alertAttr = "class=\"close\" data-dismiss=\"alert\"" + "aria-hidden=\"true\""
divHover = "<div class=\"div-dropzone-hover\"></div>"
divSpinner = "<div class=\"div-dropzone-spinner\"></div>"
divAlert = "<div class=\"" + alertClass + "\"></div>"
iconPicture = "<i class=\"icon-picture div-dropzone-icon\"></i>"
iconSpinner = "<i class=\"icon-spinner icon-spin div-dropzone-icon\"></i>"
btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
project_image_path_upload = window.project_image_path_upload or null
$("textarea.markdown-area").wrap "<div class=\"div-dropzone\"></div>"
$(".div-dropzone").parent().addClass "div-dropzone-wrapper"
$(".div-dropzone").append divHover
$(".div-dropzone-hover").append iconPicture
$(".div-dropzone").append divSpinner
$(".div-dropzone-spinner").append iconSpinner
dropzone = $(".div-dropzone").dropzone(
url: project_image_path_upload
dictDefaultMessage: ""
clickable: true
paramName: "markdown_img"
maxFilesize: 10
uploadMultiple: false
acceptedFiles: "image/jpg,image/jpeg,image/gif,image/png"
headers:
"X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
previewContainer: false
processing: ->
$(".div-dropzone-alert").alert "close"
dragover: ->
$(".div-dropzone > textarea").addClass "div-dropzone-focus"
$(".div-dropzone-hover").css "opacity", 0.7
return
dragleave: ->
$(".div-dropzone > textarea").removeClass "div-dropzone-focus"
$(".div-dropzone-hover").css "opacity", 0
return
drop: ->
$(".div-dropzone > textarea").removeClass "div-dropzone-focus"
$(".div-dropzone-hover").css "opacity", 0
$(".div-dropzone > textarea").focus()
return
success: (header, response) ->
child = $(dropzone[0]).children("textarea")
$(child).val $(child).val() + formatLink(response.link) + "\n"
return
error: (temp, errorMessage) ->
checkIfMsgExists = $(".error-alert").children().length
if checkIfMsgExists is 0
$(".error-alert").append divAlert
$(".div-dropzone-alert").append btnAlert + errorMessage
return
sending: ->
$(".div-dropzone-spinner").css "opacity", 0.7
return
complete: ->
$(".dz-preview").remove()
$(".markdown-area").trigger "input"
$(".div-dropzone-spinner").css "opacity", 0
return
)
$(".markdown-selector").click (e) ->
e.preventDefault()
$(".div-dropzone").click()
return
return
\ No newline at end of file
...@@ -43,7 +43,7 @@ class MergeRequest ...@@ -43,7 +43,7 @@ class MergeRequest
, 'json' , 'json'
bindEvents: -> bindEvents: ->
this.$('.nav-tabs').on 'click', 'a', (event) => this.$('.merge-request-tabs').on 'click', 'a', (event) =>
a = $(event.currentTarget) a = $(event.currentTarget)
href = a.attr('href') href = a.attr('href')
...@@ -51,7 +51,7 @@ class MergeRequest ...@@ -51,7 +51,7 @@ class MergeRequest
event.preventDefault() event.preventDefault()
this.$('.nav-tabs').on 'click', 'li', (event) => this.$('.merge-request-tabs').on 'click', 'li', (event) =>
this.activateTab($(event.currentTarget).data('action')) this.activateTab($(event.currentTarget).data('action'))
this.$('.accept_merge_request').on 'click', -> this.$('.accept_merge_request').on 'click', ->
...@@ -71,15 +71,15 @@ class MergeRequest ...@@ -71,15 +71,15 @@ class MergeRequest
this.$('.remove_source_branch_widget.failed').show() this.$('.remove_source_branch_widget.failed').show()
activateTab: (action) -> activateTab: (action) ->
this.$('.nav-tabs li').removeClass 'active' this.$('.merge-request-tabs li').removeClass 'active'
this.$('.tab-content').hide() this.$('.tab-content').hide()
switch action switch action
when 'diffs' when 'diffs'
this.$('.nav-tabs .diffs-tab').addClass 'active' this.$('.merge-request-tabs .diffs-tab').addClass 'active'
this.loadDiff() unless @diffs_loaded this.loadDiff() unless @diffs_loaded
this.$('.diffs').show() this.$('.diffs').show()
else else
this.$('.nav-tabs .notes-tab').addClass 'active' this.$('.merge-request-tabs .notes-tab').addClass 'active'
this.$('.notes').show() this.$('.notes').show()
showState: (state) -> showState: (state) ->
...@@ -107,7 +107,7 @@ class MergeRequest ...@@ -107,7 +107,7 @@ class MergeRequest
loadDiff: (event) -> loadDiff: (event) ->
$.ajax $.ajax
type: 'GET' type: 'GET'
url: this.$('.nav-tabs .diffs-tab a').attr('href') url: this.$('.merge-request-tabs .diffs-tab a').attr('href')
beforeSend: => beforeSend: =>
this.$('.status').addClass 'loading' this.$('.status').addClass 'loading'
complete: => complete: =>
......
class Milestone
@updateIssue: (li, issue_url, data) ->
$.ajax
type: "PUT"
url: issue_url
data: data
success: (data) ->
if data.saved == true
if data.assignee_avatar_url
img_tag = $('<img/>')
img_tag.attr('src', data.assignee_avatar_url)
img_tag.addClass('avatar s16')
$(li).find('.assignee-icon').html(img_tag)
else
$(li).find('.assignee-icon').html('')
$(li).effect 'highlight'
else
new Flash("Issue update failed", 'alert')
dataType: "json"
@sortIssues: (data) ->
sort_issues_url = location.href + "/sort_issues"
$.ajax
type: "PUT"
url: sort_issues_url
data: data
success: (data) ->
if data.saved != true
new Flash("Issues update failed", 'alert')
dataType: "json"
@sortMergeRequests: (data) ->
sort_mr_url = location.href + "/sort_merge_requests"
$.ajax
type: "PUT"
url: sort_mr_url
data: data
success: (data) ->
if data.saved != true
new Flash("MR update failed", 'alert')
dataType: "json"
@updateMergeRequest: (li, merge_request_url, data) ->
$.ajax
type: "PUT"
url: merge_request_url
data: data
success: (data) ->
if data.saved == true
$(li).effect 'highlight'
else
new Flash("Issue update failed", 'alert')
dataType: "json"
constructor: ->
@bindIssuesSorting()
@bindMergeRequestSorting()
bindIssuesSorting: ->
$("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable(
connectWith: ".issues-sortable-list",
dropOnEmpty: true,
items: "li:not(.ui-sort-disabled)",
update: (event, ui) ->
data = $(this).sortable("serialize")
Milestone.sortIssues(data)
receive: (event, ui) ->
new_state = $(this).data('state')
issue_id = ui.item.data('iid')
issue_url = ui.item.data('url')
data = switch new_state
when 'ongoing'
"issue[assignee_id]=" + gon.current_user_id
when 'unassigned'
"issue[assignee_id]="
when 'closed'
"issue[state_event]=close"
if $(ui.sender).data('state') == "closed"
data += "&issue[state_event]=reopen"
Milestone.updateIssue(ui.item, issue_url, data)
).disableSelection()
bindMergeRequestSorting: ->
$("#merge_requests-list-unassigned, #merge_requests-list-ongoing, #merge_requests-list-closed").sortable(
connectWith: ".merge_requests-sortable-list",
dropOnEmpty: true,
items: "li:not(.ui-sort-disabled)",
update: (event, ui) ->
data = $(this).sortable("serialize")
Milestone.sortMergeRequests(data)
receive: (event, ui) ->
new_state = $(this).data('state')
merge_request_id = ui.item.data('iid')
merge_request_url = ui.item.data('url')
data = switch new_state
when 'ongoing'
"merge_request[assignee_id]=" + gon.current_user_id
when 'unassigned'
"merge_request[assignee_id]="
when 'closed'
"merge_request[state_event]=close"
if $(ui.sender).data('state') == "closed"
data += "&merge_request[state_event]=reopen"
Milestone.updateMergeRequest(ui.item, merge_request_url, data)
).disableSelection()
@Milestone = Milestone
...@@ -32,6 +32,9 @@ class Notes ...@@ -32,6 +32,9 @@ class Notes
# Preview button # Preview button
$(document).on "click", ".js-note-preview-button", @previewNote $(document).on "click", ".js-note-preview-button", @previewNote
# Preview button
$(document).on "click", ".js-note-write-button", @writeNote
# reset main target form after submit # reset main target form after submit
$(document).on "ajax:complete", ".js-main-target-form", @resetMainTargetForm $(document).on "ajax:complete", ".js-main-target-form", @resetMainTargetForm
...@@ -68,6 +71,7 @@ class Notes ...@@ -68,6 +71,7 @@ class Notes
$(document).off "click", ".js-note-delete" $(document).off "click", ".js-note-delete"
$(document).off "click", ".js-note-attachment-delete" $(document).off "click", ".js-note-attachment-delete"
$(document).off "click", ".js-note-preview-button" $(document).off "click", ".js-note-preview-button"
$(document).off "click", ".js-note-write-button"
$(document).off "ajax:complete", ".js-main-target-form" $(document).off "ajax:complete", ".js-main-target-form"
$(document).off "click", ".js-choose-note-attachment-button" $(document).off "click", ".js-choose-note-attachment-button"
$(document).off "click", ".js-discussion-reply-button" $(document).off "click", ".js-discussion-reply-button"
...@@ -144,16 +148,36 @@ class Notes ...@@ -144,16 +148,36 @@ class Notes
# cleanup after successfully creating a diff/discussion note # cleanup after successfully creating a diff/discussion note
@removeDiscussionNoteForm(form) @removeDiscussionNoteForm(form)
###
Shows write note textarea.
###
writeNote: (e) ->
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-note-write-button").parent().addClass "active"
form.find(".js-note-preview-button").parent().removeClass "active"
# toggle content
form.find(".note-write-holder").show()
form.find(".note-preview-holder").hide()
### ###
Shows the note preview. Shows the note preview.
Lets the server render GFM into Html and displays it. Lets the server render GFM into Html and displays it.
Note: uses the Toggler behavior to toggle preview/edit views/buttons
### ###
previewNote: (e) -> previewNote: (e) ->
e.preventDefault() e.preventDefault()
form = $(this).closest("form") form = $(this).closest("form")
# toggle tabs
form.find(".js-note-write-button").parent().removeClass "active"
form.find(".js-note-preview-button").parent().addClass "active"
# toggle content
form.find(".note-write-holder").hide()
form.find(".note-preview-holder").show()
preview = form.find(".js-note-preview") preview = form.find(".js-note-preview")
noteText = form.find(".js-note-text").val() noteText = form.find(".js-note-text").val()
if noteText.trim().length is 0 if noteText.trim().length is 0
...@@ -179,8 +203,7 @@ class Notes ...@@ -179,8 +203,7 @@ class Notes
form.find(".js-errors").remove() form.find(".js-errors").remove()
# reset text and preview # reset text and preview
previewContainer = form.find(".js-toggler-container.note_text_and_preview") form.find(".js-note-write-button").click()
previewContainer.removeClass "on" if previewContainer.is(".on")
form.find(".js-note-text").val("").trigger "input" form.find(".js-note-text").val("").trigger "input"
### ###
...@@ -230,7 +253,7 @@ class Notes ...@@ -230,7 +253,7 @@ class Notes
form.removeClass "js-new-note-form" form.removeClass "js-new-note-form"
# setup preview buttons # setup preview buttons
form.find(".js-note-edit-button, .js-note-preview-button").tooltip placement: "left" form.find(".js-note-write-button, .js-note-preview-button").tooltip placement: "left"
previewButton = form.find(".js-note-preview-button") previewButton = form.find(".js-note-preview-button")
form.find(".js-note-text").on "input", -> form.find(".js-note-text").on "input", ->
if $(this).val().trim() isnt "" if $(this).val().trim() isnt ""
......
...@@ -38,12 +38,8 @@ ...@@ -38,12 +38,8 @@
projectUserFormatResult: (user) -> projectUserFormatResult: (user) ->
if user.avatar_url if user.avatar_url
avatar = user.avatar_url avatar = user.avatar_url
else if gon.gravatar_enabled
avatar = gon.gravatar_url
avatar = avatar.replace('%{hash}', md5(user.email))
avatar = avatar.replace('%{size}', '24')
else else
avatar = gon.relative_url_root + "/assets/no_avatar.png" avatar = gon.default_avatar_url
if user.id == '' if user.id == ''
avatarMarkup = '' avatarMarkup = ''
......
responsive_resize = ->
current_width = $(window).width()
if current_width < 985
$('.responsive-side').addClass("ui right wide sidebar")
else
$('.responsive-side').removeClass("ui right wide sidebar")
$ ->
# Depending on window size, set the sidebar offscreen.
responsive_resize()
$('.sidebar-expand-button').click ->
$('.ui.sidebar')
.sidebar({overlay: true})
.sidebar('toggle')
# Hide sidebar on click outside of sidebar
$(document).mouseup (e) ->
container = $(".ui.sidebar")
container.sidebar "hide" if not container.is(e.target) and container.has(e.target).length is 0
return
# On resize, check if sidebar should be offscreen.
$(window).resize ->
responsive_resize()
return
...@@ -2,12 +2,8 @@ $ -> ...@@ -2,12 +2,8 @@ $ ->
userFormatResult = (user) -> userFormatResult = (user) ->
if user.avatar_url if user.avatar_url
avatar = user.avatar_url avatar = user.avatar_url
else if gon.gravatar_enabled
avatar = gon.gravatar_url
avatar = avatar.replace('%{hash}', md5(user.email))
avatar = avatar.replace('%{size}', '24')
else else
avatar = gon.relative_url_root + "/assets/no_avatar.png" avatar = gon.default_avatar_url
"<div class='user-result'> "<div class='user-result'>
<div class='user-image'><img class='avatar s24' src='#{avatar}'></div> <div class='user-image'><img class='avatar s24' src='#{avatar}'></div>
......
class Wall
constructor: (project_id) ->
@project_id = project_id
@note_ids = []
@getContent()
@initRefresh()
@initForm()
#
# Gets an initial set of notes.
#
getContent: ->
Api.notes @project_id, (notes) =>
$.each notes, (i, note) =>
# render note if it not present in loaded list
# or skip if rendered
if $.inArray(note.id, @note_ids) == -1
@note_ids.push(note.id)
@renderNote(note)
@scrollDown()
$("abbr.timeago").timeago()
initRefresh: ->
setInterval =>
@refresh()
, 10000
refresh: ->
@getContent()
scrollDown: ->
notes = $('ul.notes')
$('body, html').scrollTop(notes.height())
initForm: ->
form = $('.wall-note-form')
form.find("#target_type").val('wall')
form.on 'ajax:success', =>
@refresh()
form.find(".js-note-text").val("").trigger("input")
form.on 'ajax:complete', ->
form.find(".js-comment-button").removeAttr('disabled')
form.find(".js-comment-button").removeClass('disabled')
form.on "click", ".js-choose-note-attachment-button", ->
form.find(".js-note-attachment-input").click()
form.on "change", ".js-note-attachment-input", ->
filename = $(this).val().replace(/^.*[\\\/]/, '')
form.find(".js-attachment-filename").text(filename)
form.find('.note_text').keydown (e) ->
if e.ctrlKey && e.keyCode == 13
form.find('.js-comment-button').submit()
form.show()
renderNote: (note) ->
template = @noteTemplate()
template = template.replace('{{author_name}}', note.author.name)
template = template.replace(/{{created_at}}/g, note.created_at)
template = template.replace('{{text}}', simpleFormat(note.body))
if note.attachment
file = '<i class="icon-paper-clip"/><a href="' + gon.relative_url_root + '/files/note/' + note.id + '/' + note.attachment + '">' + note.attachment + '</a>'
else
file = ''
template = template.replace('{{file}}', file)
$('ul.notes').append(template)
noteTemplate: ->
return '<li>
<strong class="wall-author">{{author_name}}</strong>
<span class="wall-text">
{{text}}
<span class="wall-file">{{file}}</span>
</span>
<abbr class="timeago" title="{{created_at}}">{{created_at}}</abbr>
</li>'
@Wall = Wall
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*= require_self *= require_self
*= require nprogress *= require nprogress
*= require nprogress-bootstrap *= require nprogress-bootstrap
*= require dropzone/basic
*/ */
@import "main/*"; @import "main/*";
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
/** /**
* Page specific styles (issues, projects etc): * Page specific styles (issues, projects etc):
*/ */
@import "sections/*"; @import "sections/*";
/** /**
...@@ -49,3 +51,8 @@ ...@@ -49,3 +51,8 @@
* Styles for JS behaviors. * Styles for JS behaviors.
*/ */
@import "behaviors.scss"; @import "behaviors.scss";
/**
* Styles for responsive sidebar
*/
@import "semantic-ui/modules/sidebar"
...@@ -4,11 +4,3 @@ ...@@ -4,11 +4,3 @@
.js-details-container .content.hide { display: block; } .js-details-container .content.hide { display: block; }
.js-details-container.open .content { display: block; } .js-details-container.open .content { display: block; }
.js-details-container.open .content.hide { display: none; } .js-details-container.open .content.hide { display: none; }
// Toggler
//--------
.js-toggler-container .turn-on { display: inherit; }
.js-toggler-container .turn-off { display: none; }
.js-toggler-container.on .turn-on { display: none; }
.js-toggler-container.on .turn-off { display: inherit; }
...@@ -59,23 +59,21 @@ ...@@ -59,23 +59,21 @@
&.btn-primary { &.btn-primary {
color: #ffffff; color: #ffffff;
background-color: #429bca; background-color: $bg_primary;
border-color: #358ebd; border-color: $border_primary;
&.hover, &.hover,
&:hover, &:hover,
&.disabled, &.disabled,
&[disabled] { &[disabled] {
color: #ffffff; color: #ffffff;
background-color: #3286b1;
border-color: #286e8e;
} }
} }
&.btn-success { &.btn-success {
color: #ffffff; color: #ffffff;
background-color: #5cb85c; background-color: $bg_success;
border-color: #4cae4c; border-color: $border_success;
&.hover, &.hover,
...@@ -83,15 +81,27 @@ ...@@ -83,15 +81,27 @@
&.disabled, &.disabled,
&[disabled] { &[disabled] {
color: #ffffff; color: #ffffff;
background-color: #47a447;
border-color: #398439;
} }
} }
&.btn-danger { &.btn-danger {
color: #ffffff; color: #ffffff;
background-color: #d9534f; background-color: $bg_danger;
border-color: #d43f3a; border-color: $border_danger;
&.hover,
&:hover,
&.disabled,
&[disabled] {
color: #ffffff;
}
}
&.btn-warning {
color: #ffffff;
background-color: $bg_warning;
border-color: $border_warning;
&.hover, &.hover,
...@@ -99,8 +109,6 @@ ...@@ -99,8 +109,6 @@
&.disabled, &.disabled,
&[disabled] { &[disabled] {
color: #ffffff; color: #ffffff;
background-color: #d2322d;
border-color: #ac2925;
} }
} }
......
...@@ -3,12 +3,7 @@ ...@@ -3,12 +3,7 @@
.clgray { color: #BBB } .clgray { color: #BBB }
.cred { color: #D12F19 } .cred { color: #D12F19 }
.cgreen { color: #4a2 } .cgreen { color: #4a2 }
.cblue { color: #29A }
.cblack { color: #111 }
.cdark { color: #444 } .cdark { color: #444 }
.camber { color: #ffc000 }
.cwhite { color: #fff!important }
.bgred { background: #F2DEDE!important }
/** COMMON CLASSES **/ /** COMMON CLASSES **/
.prepend-top-10 { margin-top:10px } .prepend-top-10 { margin-top:10px }
...@@ -60,23 +55,12 @@ pre { ...@@ -60,23 +55,12 @@ pre {
.dropdown-menu > li > a:hover, .dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus { .dropdown-menu > li > a:focus {
background: #29b; background: $bg_style_color;
color: #FFF color: #FFF
} }
.breadcrumb > li + li:before {
content: "/";
padding: 0;
color: #666;
}
.str-truncated { .str-truncated {
display: inline-block; @include str-truncated;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
white-space: nowrap;
max-width: 82%;
} }
/** FLASH message **/ /** FLASH message **/
......
...@@ -16,11 +16,11 @@ ...@@ -16,11 +16,11 @@
text-shadow: 0 1px 1px #fff; text-shadow: 0 1px 1px #fff;
margin: 0; margin: 0;
text-align: left; text-align: left;
padding: 9px 10px; padding: 10px 15px;
.options { .options {
float: right; float: right;
margin-top: -5px; margin-top: -3px;
} }
.left-options { .left-options {
......
...@@ -82,6 +82,7 @@ label { ...@@ -82,6 +82,7 @@ label {
font-family: $monospace_font; font-family: $monospace_font;
$left: 12px; $left: 12px;
.max-width-marker { .max-width-marker {
width: 72ch;
color: rgba(0, 0, 0, 0.0); color: rgba(0, 0, 0, 0.0);
font-family: inherit; font-family: inherit;
left: $left; left: $left;
...@@ -98,3 +99,7 @@ label { ...@@ -98,3 +99,7 @@ label {
z-index: 2; z-index: 2;
} }
} }
.fieldset-form fieldset {
margin-bottom: 20px;
}
...@@ -17,52 +17,36 @@ ...@@ -17,52 +17,36 @@
&.issue-box-closed { &.issue-box-closed {
border-color: $border_danger; border-color: $border_danger;
.state { .state {
background-color: $bg_light_danger; background-color: $bg_danger;
color: #FFF;
border-color: $border_danger; border-color: $border_danger;
color: $color_danger;
.state-label {
background-color: $bg_danger;
color: #FFF;
}
} }
} }
&.issue-box-merged { &.issue-box-merged {
border-color: $border_primary; border-color: $border_primary;
.state { .state {
background-color: $bg_light_primary; background-color: $bg_primary;
color: #FFF;
border-color: $border_primary; border-color: $border_primary;
color: $color_primary;
.state-label {
background-color: $bg_primary;
color: #FFF;
}
} }
} }
&.issue-box-open { &.issue-box-open {
border-color: $border_success; border-color: $border_success;
.state { .state {
background-color: $bg_light_success;
border-color: $border_success; border-color: $border_success;
color: $color_success; background-color: $bg_success;
.state-label { color: #FFF;
background-color: $bg_success;
color: #FFF;
}
} }
} }
&.issue-box-expired { &.issue-box-expired {
border-color: #cea61b; border-color: #cea61b;
.state { .state {
background-color: #fcf8e3;
border-color: #faebcc; border-color: #faebcc;
color: #8a6d3b; background: #cea61b;
.state-label { color: #FFF;
background: #cea61b;
color: #FFF;
}
} }
} }
...@@ -72,23 +56,22 @@ ...@@ -72,23 +56,22 @@
.state { .state {
border-bottom: 1px solid #DDD; border-bottom: 1px solid #DDD;
line-height: 32px; padding: 10px 15px;
} }
.title { .title {
font-size: 22px; font-size: 28px;
font-weight: 500; font-weight: normal;
line-height: 1.5; line-height: 1.5;
margin: 0; margin: 0;
color: #333; color: #333;
padding-bottom: 0; padding: 10px 15px;
padding: 15px 25px;
} }
.context { .context {
border: none; border: none;
border-top: 1px solid #eee; border-top: 1px solid #eee;
padding: 15px 25px; padding: 10px 15px;
// Reset text align for children // Reset text align for children
.text-right > * { text-align: left; } .text-right > * { text-align: left; }
...@@ -104,7 +87,7 @@ ...@@ -104,7 +87,7 @@
} }
.description { .description {
padding: 0 25px 15px 25px; padding: 0 15px 10px 15px;
} }
.title, .context, .description { .title, .context, .description {
...@@ -115,14 +98,15 @@ ...@@ -115,14 +98,15 @@
.state-label { .state-label {
font-size: 14px; font-size: 14px;
padding: 1px 25px; float: left;
text-align: center; font-weight: bold;
text-shadow: none;
display: inline-block;
line-height: 34px;
} }
.creator { .creator {
padding: 2px 15px; float: right;
a {
color: #FFF;
text-decoration: underline;
}
} }
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
list-style: none; list-style: none;
li { li {
padding: 10px; padding: 10px 15px;
min-height: 20px; min-height: 20px;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
border-bottom: 1px solid rgba(0, 0, 0, 0.05); border-bottom: 1px solid rgba(0, 0, 0, 0.05);
...@@ -72,6 +72,15 @@ ...@@ -72,6 +72,15 @@
font-size: 14px; font-size: 14px;
line-height: 18px; line-height: 18px;
} }
.row_title {
font-weight: 500;
color: #444;
&:hover {
color: #444;
text-decoration: underline;
}
}
} }
} }
......
.div-dropzone-wrapper {
.div-dropzone {
position: relative;
padding: 0;
border: 0;
margin-bottom: 5px;
.div-dropzone-focus {
border-color: #66afe9 !important;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6) !important;
outline: 0 !important;
}
.div-dropzone-hover {
position: absolute;
top: 50%;
left: 50%;
margin-top: -0.5em;
margin-left: -0.6em;
opacity: 0;
font-size: 50px;
transition: opacity 200ms ease-in-out;
}
.div-dropzone-spinner {
position: absolute;
top: 100%;
left: 100%;
margin-top: -1.1em;
margin-left: -1.1em;
opacity: 0;
font-size: 30px;
transition: opacity 200ms ease-in-out;
}
.div-dropzone-icon {
display: block;
text-align: center;
font-size: inherit;
}
.dz-preview {
display: none;
}
}
}
.div-dropzone-alert {
margin-top: 5px;
margin-bottom: 0;
transition: opacity 200ms ease-in-out;
}
...@@ -3,13 +3,29 @@ ...@@ -3,13 +3,29 @@
.select2-choice { .select2-choice {
background: #FFF; background: #FFF;
border-color: #BBB; border-color: #BBB;
padding: 6px 12px;
font-size: 13px;
line-height: 18px;
height: auto;
.select2-arrow { .select2-arrow {
background: #FFF; background: #FFF;
border-left: 1px solid #DDD;
} }
} }
} }
.select2-container-multi .select2-choices {
@include border-radius(4px)
}
.select2-container-multi .select2-choices .select2-search-field input {
padding: 6px 12px;
font-size: 13px;
line-height: 18px;
height: auto;
}
.select2-drop-active { .select2-drop-active {
border: 1px solid #BBB !important; border: 1px solid #BBB !important;
margin-top: 4px; margin-top: 4px;
......
.ui.sidebar {
z-index: 1000 !important;
background: #fff;
padding: 10px;
width: 285px;
}
.ui.right.sidebar {
border-left: 1px solid #e1e1e1;
border-right: 0;
}
.sidebar-expand-button {
cursor: pointer;
transition: all 0.4s;
-moz-transition: all 0.4s;
-webkit-transition: all 0.4s;
}
.fixed.sidebar-expand-button {
background: #f9f9f9;
color: #555;
padding: 9px 12px 6px 14px;
border: 1px solid #E1E1E1;
border-right: 0;
position: fixed;
top: 108px;
right: 0px;
margin-right: 0;
&:hover {
background: #ddd;
color: #333;
padding-right: 25px;
}
}
.btn.btn-default.sidebar-expand-button {
margin-left: 12px;
display: inline-block !important;
}
@media (min-width: 767px) {
.btn.btn-default.sidebar-expand-button {
display: none!important;
}
}
...@@ -14,6 +14,7 @@ h2.page-title { ...@@ -14,6 +14,7 @@ h2.page-title {
h3.page-title { h3.page-title {
@include page-title; @include page-title;
font-size: 22px;
} }
h6 { h6 {
...@@ -40,7 +41,7 @@ a { ...@@ -40,7 +41,7 @@ a {
color: $link_color; color: $link_color;
&:hover { &:hover {
text-decoration: none; text-decoration: none;
color: $primary_color; color: $link_hover_color;
} }
&:focus { &:focus {
......
/**
* UI box:
* Block element for separating information on page.
* Used for storing issues lists, grouped data.
* You can have multiple ui boxes on one page
*
* Classes:
* .ui-box - for any block & widgets
* .ui-box.ui-box-small - same but with smaller title
* .ui-box.ui-box-danger - with red title
*
* Ex. 1: List
* .ui-box
* .title
* # title here
* %ul
* # content here
*
* Ex. 2: Block data
* .ui-box
* .title
* # title here
* .body
* # content here
*
*/
.ui-box {
background: #FFF;
margin-bottom: 20px;
border: 1px solid #DDD;
word-wrap: break-word;
img {
max-width: 100%;
}
pre {
code {
background: none !important;
}
}
ul {
margin: 0;
padding: 0;
}
.title {
background-color: #EEE;
border-bottom: 1px solid #DDD;
color: #666;
font-size: 16px;
text-shadow: 0 1px 1px #fff;
padding: 0 10px;
font-size: 14px;
line-height: 40px;
font-weight: normal;
margin: 0;
> a {
text-shadow: 0 1px 1px #fff;
}
form {
margin-bottom: 0;
margin-top: 0;
}
.btn {
vertical-align: middle;
padding: 4px 12px;
@include box-shadow(0 0px 1px 1px #f2f2f2);
}
.nav-pills {
> li {
> a {
padding: 13px;
margin: 0;
font-size: 13px;
}
&.active {
> a {
background: #D5D5D5;
color: $style_color;
@include border-radius(0);
border-radius: 0;
border-left: 1px solid #CCC;
border-right: 1px solid #CCC;
}
}
}
}
}
.body {
padding: 10px;
}
&.padded {
h5, .title {
margin: -20px;
margin-bottom: 0;
padding: 5px 20px;
}
}
.row_title {
font-weight: 500;
color: #444;
&:hover {
color: #444;
text-decoration: underline;
}
}
.form-holder {
padding-top: 20px;
form {
margin-bottom: 0;
legend {
text-indent: 10px;
}
.form-actions {
margin-bottom: 0;
}
}
}
}
/*
* Small box
*/
.ui-box.ui-box-small {
margin-bottom: 10px;
.title {
font-size: 13px;
line-height: 30px;
a {
color: #666;
&:hover {
text-decoration: underline;
}
}
}
}
/*
* Danger box
*/
.ui-box.ui-box-danger {
background: #f7f7f7;
border: none;
.title {
background: #D65;
color: #fff;
text-shadow: none;
font-weight: 500;
}
}
/*
* Block under tw-bootstrap tabs
*/
.tab-pane {
.ui-box {
margin: 3px 3px 25px 3px;
}
}
...@@ -7,8 +7,9 @@ ...@@ -7,8 +7,9 @@
*/ */
$font-size-base: 13px !default; $font-size-base: 13px !default;
$nav-pills-active-link-hover-bg: $bg_style_color; $nav-pills-active-link-hover-bg: $bg_primary;
$pagination-active-bg: $bg_style_color; $pagination-active-bg: $bg_primary;
$list-group-active-bg: $bg_style_color;
// Core variables and mixins // Core variables and mixins
@import "bootstrap/variables"; @import "bootstrap/variables";
...@@ -113,8 +114,7 @@ $pagination-active-bg: $bg_style_color; ...@@ -113,8 +114,7 @@ $pagination-active-bg: $bg_style_color;
li { li {
> a { > a {
padding: 8px 20px; margin-right: 5px;
margin-right: 7px;
line-height: 20px; line-height: 20px;
border-color: #EEE; border-color: #EEE;
color: #888; color: #888;
...@@ -199,20 +199,6 @@ $pagination-active-bg: $bg_style_color; ...@@ -199,20 +199,6 @@ $pagination-active-bg: $bg_style_color;
color: #3c763d; color: #3c763d;
} }
// Breadcrumb
ul.breadcrumb {
background: white;
border: none;
li {
display: inline;
text-shadow: 0 1px 0 white
}
a {
font-size: 16px;
}
}
/** /**
* fix to keep tooltips position in top navigation bar * fix to keep tooltips position in top navigation bar
* *
...@@ -221,3 +207,108 @@ ul.breadcrumb { ...@@ -221,3 +207,108 @@ ul.breadcrumb {
position: relative; position: relative;
white-space: nowrap; white-space: nowrap;
} }
/**
* Add some extra stuff to panels
*
*/
.panel {
@include border-radius(0px);
.panel-heading {
@include border-radius(0px);
font-size: 14px;
line-height: 18px;
.panel-head-actions {
position: relative;
top: -7px;
float: right;
}
}
.panel-body {
form {
margin: 0;
}
.form-actions {
margin-bottom: 0;
background: #FFF;
}
}
.panel-footer {
.pagination {
margin: 0;
}
}
&.panel-small {
.panel-heading {
padding: 6px 15px;
font-size: 13px;
a {
color: #777;
}
}
}
}
.panel-default {
.panel-heading {
background-color: #EEE;
}
}
.panel-danger {
border-color: $border_danger;
.panel-heading {
color: #ffffff;
background-color: $bg_danger;
border-color: $border_danger;
a {
color: #FFF;
text-decoration: underline;
}
}
}
.panel-success {
border-color: $border_success;
.panel-heading {
color: #ffffff;
background-color: $bg_success;
border-color: $border_success;
a {
color: #FFF;
text-decoration: underline;
}
}
}
.panel-primary {
border-color: $border_primary;
.panel-heading {
color: #ffffff;
background-color: $bg_primary;
border-color: $border_primary;
a {
color: #FFF;
text-decoration: underline;
}
}
}
.panel-warning {
border-color: $border_warning;
.panel-heading {
color: #ffffff;
background-color: $bg_warning;
border-color: $border_warning;
a {
color: #FFF;
text-decoration: underline;
}
}
}
...@@ -118,8 +118,17 @@ ...@@ -118,8 +118,17 @@
@mixin page-title { @mixin page-title {
color: #333; color: #333;
font-size: 20px;
line-height: 1.5; line-height: 1.5;
font-weight: normal;
margin-top: 0px; margin-top: 0px;
margin-bottom: 15px; margin-bottom: 10px;
}
@mixin str-truncated($max_width: 82%) {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
white-space: nowrap;
max-width: $max_width;
} }
/** /*
* General Colors * General Colors
*/ */
$primary_color: #2FA0BB;
$link_color: #3A89A3;
$style_color: #474D57; $style_color: #474D57;
$bg_style_color: #2299BB; $bg_style_color: #2299BB;
$list-group-active-bg: $bg_style_color;
$hover: #D9EDF7; $hover: #D9EDF7;
/*
* Link colors
*/
$link_color: #446e9b;
$link_hover_color: #2FA0BB;
/* /*
* Success colors (green) * Success colors (green)
*/ */
$border_success: #4cae4c; $border_success: #019875;
$bg_success: #5cb85c; $bg_success: #019875;
$bg_light_success: #dff0d8;
$color_success: #3c763d;
/* /*
* Danger colors (red) * Danger colors (red)
*/ */
$border_danger: #d43f3a; $border_danger: #d43f3a;
$bg_danger: #d9534f; $bg_danger: #d9534f;
$bg_light_danger: #f2dede;
$color_danger: #a94442;
/* /*
* Primary colors (blue) * Primary colors (blue)
*/ */
$border_primary: #358ebd; $border_primary: #446e9b;
$bg_primary: #429bca; $bg_primary: #446e9b;
$bg_light_primary: #d9edf7;
$color_primary: #31708f;
/*
* Warning colors (yellow)
*/
$bg_warning: #EB9532;
$border_warning: #EB9532;
/** /**
* Commit Diff Colors * Commit Diff Colors
......
...@@ -21,12 +21,22 @@ ...@@ -21,12 +21,22 @@
} }
.admin-filter form { .admin-filter form {
label { width: 110px; } .select2-container {
.controls { margin-left: 130px; } width: 100%
.form-actions { padding-left: 130px; background: #fff } }
.visibility-levels {
.controls { .controls {
margin-bottom: 9px; margin-left: 130px;
}
.form-actions {
padding-left: 130px;
background: #fff
}
.visibility-levels {
.controls {
margin-bottom: 9px;
} }
i { i {
......
...@@ -115,10 +115,6 @@ ...@@ -115,10 +115,6 @@
line-height: 2; line-height: 2;
} }
.commit-breadcrumb {
padding: 0;
}
.commit-info-row { .commit-info-row {
margin-bottom: 10px; margin-bottom: 10px;
.avatar { .avatar {
...@@ -140,8 +136,6 @@ ...@@ -140,8 +136,6 @@
* COMMIT ROW * COMMIT ROW
*/ */
li.commit { li.commit {
padding: 8px;
.commit-row-title { .commit-row-title {
font-size: 14px; font-size: 14px;
margin-bottom: 2px; margin-bottom: 2px;
...@@ -212,3 +206,10 @@ li.commit { ...@@ -212,3 +206,10 @@ li.commit {
} }
} }
} }
.commits-feed-holder {
float: right;
.btn {
padding: 4px 12px;
}
}
.dashboard { .dashboard {
.side { .side {
.ui-box { .panel {
margin: 0px; .panel-heading {
box-shadow: none; background: #EEE;
border-top-left-radius: 0;
.nav-projects-tabs li { padding: 0; } }
border-top-left-radius: 0;
} }
} }
} }
...@@ -24,9 +25,7 @@ ...@@ -24,9 +25,7 @@
.dashboard { .dashboard {
.dash-filter { .dash-filter {
margin: 7px 0; width: 205px;
padding: 4px 6px;
width: 220px;
float: left; float: left;
height: inherit; height: inherit;
} }
...@@ -34,7 +33,7 @@ ...@@ -34,7 +33,7 @@
@media (max-width: 1200px) { @media (max-width: 1200px) {
.dashboard .dash-filter { .dashboard .dash-filter {
width: 150px; width: 140px;
} }
} }
...@@ -61,7 +60,7 @@ ...@@ -61,7 +60,7 @@
} }
.project-row, .group-row { .project-row, .group-row {
padding: 8px 12px !important; padding: 8px 15px !important;
font-size: 14px; font-size: 14px;
line-height: 24px; line-height: 24px;
...@@ -75,10 +74,8 @@ ...@@ -75,10 +74,8 @@
.arrow { .arrow {
float: right; float: right;
padding: 0px 5px;
margin: 0; margin: 0;
font-size: 20px; font-size: 20px;
color: #666;
} }
.last-activity { .last-activity {
...@@ -112,6 +109,5 @@ ...@@ -112,6 +109,5 @@
.dash-project-access-icon { .dash-project-access-icon {
float: left; float: left;
margin-right: 3px; margin-right: 3px;
color: #999;
width: 16px; width: 16px;
} }
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
> span { > span {
font-family: $monospace_font; font-family: $monospace_font;
font-size: 14px;
line-height: 2; line-height: 2;
} }
...@@ -19,9 +18,7 @@ ...@@ -19,9 +18,7 @@
float: right; float: right;
.btn { .btn {
background-color: #EEE; background-color: #FFF;
color: #666;
font-weight: bolder;
} }
} }
...@@ -32,6 +29,7 @@ ...@@ -32,6 +29,7 @@
.file-mode { .file-mode {
font-family: $monospace_font; font-family: $monospace_font;
margin-left: 10px;
} }
} }
.diff-content { .diff-content {
...@@ -51,6 +49,11 @@ ...@@ -51,6 +49,11 @@
} }
} }
.file-mode-changed {
padding: 10px;
color: #777;
}
table { table {
width: 100%; width: 100%;
font-family: $monospace_font; font-family: $monospace_font;
...@@ -330,3 +333,8 @@ ...@@ -330,3 +333,8 @@
} }
} }
} }
.file-content .diff-file {
margin: 0;
border: none;
}
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
padding: 12px 0px; padding: 12px 0px;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
.event-title { .event-title {
@include str-truncated(72%);
color: #333; color: #333;
font-weight: normal; font-weight: normal;
font-size: 14px; font-size: 14px;
...@@ -135,6 +136,12 @@ ...@@ -135,6 +136,12 @@
} }
} }
} }
.event-item-timestamp {
float: right;
color: #999;
line-height: 22px;
}
} }
/** /**
...@@ -166,3 +173,19 @@ ...@@ -166,3 +173,19 @@
} }
} }
} }
/*
* Last push widget
*/
.event-last-push {
.event-last-push-text {
@include str-truncated(75%);
line-height: 24px;
}
}
@media (max-width: $screen-xs-max) {
.event-item .event-title {
@include str-truncated(65%);
}
}
.project-network { .project-network {
border: 1px solid #CCC; border: 1px solid #CCC;
.tip { .controls {
color: #888; color: #888;
font-size: 14px; font-size: 14px;
padding: 10px; padding: 5px;
border-bottom: 1px solid #bbb; border-bottom: 1px solid #bbb;
background: #EEE; background: #EEE;
} }
......
...@@ -137,6 +137,7 @@ header { ...@@ -137,6 +137,7 @@ header {
.profile-pic { .profile-pic {
position: relative; position: relative;
top: -1px; top: -1px;
padding-right: 0px !important;
img { img {
width: 26px; width: 26px;
height: 26px; height: 26px;
......
.documentation-index {
h1 {
margin: 0;
}
h2 {
font-size: 20px;
}
li {
line-height: 24px;
color: #888;
a {
font-size: 14px;
margin-right: 3px;
}
}
}
.issues-list { .issues-list {
.issue { .issue {
padding: 10px; padding: 10px 15px;
position: relative; position: relative;
.issue-title { .issue-title {
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
display: none; display: none;
position: absolute; position: absolute;
top: 10px; top: 10px;
right: 2px; right: 15px;
} }
&:hover { &:hover {
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
height: 32px; height: 32px;
float: left; float: left;
margin-right: 12px; margin-right: 12px;
padding: 6px 10px; padding: 6px 15px;
border: 1px solid #ccc; border: 1px solid #ccc;
@include border-radius(4px); @include border-radius(4px);
} }
......
...@@ -19,12 +19,17 @@ ...@@ -19,12 +19,17 @@
} }
} }
.merge-request .nav-tabs{ .merge-request .merge-request-tabs{
border-bottom: 2px solid $border_primary;
margin: 20px 0;
li { li {
a { a {
font-weight: bold; padding: 15px 40px;
padding: 8px 20px; font-size: 14px;
text-align: center; margin-bottom: -2px;
border-bottom: 2px solid $border_primary;
@include border-radius(0px);
} }
} }
} }
...@@ -63,7 +68,7 @@ ...@@ -63,7 +68,7 @@
.mr-list { .mr-list {
.merge-request { .merge-request {
padding: 10px; padding: 10px 15px;
position: relative; position: relative;
.merge-request-title { .merge-request-title {
...@@ -99,12 +104,6 @@ ...@@ -99,12 +104,6 @@
} }
.mr-state-widget { .mr-state-widget {
@include border-radius(0px);
.panel-heading {
@include border-radius(0px);
}
.panel-body { .panel-body {
h4 { h4 {
margin-top: 0px; margin-top: 0px;
...@@ -119,3 +118,7 @@ ...@@ -119,3 +118,7 @@
.merge-request-show-labels .label { .merge-request-show-labels .label {
padding: 6px 10px; padding: 6px 10px;
} }
.mr-commits .commit {
padding: 10px 15px;
}
.issues-sortable-list .str-truncated {
max-width: 70%;
}
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
left: 50%; left: 50%;
width: 0; width: 0;
height: 0; height: 0;
border-color: transparent transparent #29b transparent; border-color: transparent transparent $link_color transparent;
border-style: solid; border-style: solid;
border-width: 6px; border-width: 6px;
margin-left: -6px; margin-left: -6px;
...@@ -116,7 +116,7 @@ ...@@ -116,7 +116,7 @@
padding: 5px 0; padding: 5px 0;
&.active { &.active {
background-color: $primary_color; background-color: $link_hover_color;
a { a {
color: #fff; color: #fff;
......
...@@ -37,7 +37,7 @@ ul.notes { ...@@ -37,7 +37,7 @@ ul.notes {
font-weight: bold; font-weight: bold;
font-size: 14px; font-size: 14px;
&:hover { &:hover {
color: $primary_color; color: $link_hover_color;
} }
} }
} }
...@@ -83,6 +83,7 @@ ul.notes { ...@@ -83,6 +83,7 @@ ul.notes {
overflow: hidden; overflow: hidden;
display: block; display: block;
position:relative; position:relative;
border-bottom: 1px solid #eee;
p { color: $style_color; } p { color: $style_color; }
.avatar { .avatar {
...@@ -98,22 +99,16 @@ ul.notes { ...@@ -98,22 +99,16 @@ ul.notes {
.note-header { .note-header {
padding-bottom: 3px; padding-bottom: 3px;
} }
&:last-child {
border-bottom: none;
}
} }
.note:target { .note:target {
-webkit-animation:target-note 2s linear; -webkit-animation:target-note 2s linear;
background: #fffff0; background: #fffff0;
} }
// paint top or bottom borders depending on notes direction
&:not(.reversed) .note,
&:not(.reversed) .discussion {
border-bottom: 1px solid #eee;
}
&.reversed .note,
&.reversed .discussion {
border-top: 1px solid #eee;
}
} }
.diff-file .notes_holder { .diff-file .notes_holder {
...@@ -140,10 +135,6 @@ ul.notes { ...@@ -140,10 +135,6 @@ ul.notes {
border-width: 1px 0; border-width: 1px 0;
padding-top: 0; padding-top: 0;
vertical-align: top; vertical-align: top;
li {
padding: 5px;
}
} }
} }
...@@ -181,7 +172,7 @@ ul.notes { ...@@ -181,7 +172,7 @@ ul.notes {
@extend .cgray; @extend .cgray;
&:hover { &:hover {
color: $primary_color; color: $link_hover_color;
&.danger { @extend .cred; } &.danger { @extend .cred; }
} }
} }
...@@ -271,29 +262,33 @@ ul.notes { ...@@ -271,29 +262,33 @@ ul.notes {
.clearfix { .clearfix {
margin-bottom: 0; margin-bottom: 0;
} }
.note_text_and_preview {
// makes the "absolute" position for links relative to this
position: relative;
// preview/edit buttons .note-preview-holder,
> a { .note_text {
position: absolute; background: #FFF;
right: 5px; border: 1px solid #ddd;
bottom: -60px; min-height: 100px;
} padding: 5px;
.note_preview { font-size: 14px;
background: #f5f5f5; box-shadow: none;
border: 1px solid #ddd; }
@include border-radius(4px);
min-height: 80px; .note-preview-holder {
padding: 4px 6px; > p {
overflow-x: auto;
} }
.note_text { }
.note_text {
width: 100%;
}
.nav-tabs {
margin-bottom: 0;
border: none;
li a,
li.active a {
border: 1px solid #DDD; border: 1px solid #DDD;
box-shadow: none;
font-size: 14px;
height: 80px;
width: 100%;
} }
} }
} }
...@@ -310,19 +305,16 @@ ul.notes { ...@@ -310,19 +305,16 @@ ul.notes {
float: none; float: none;
} }
.common-note-form { .common-note-form {
margin: 0; margin: 0;
background: #F9F9F9; background: #F9F9F9;
padding: 3px; padding: 5px;
border: 1px solid #DDD; border: 1px solid #DDD;
} }
.note-form-actions { .note-form-actions {
background: #F9F9F9; background: #F9F9F9;
height: 45px; height: 45px;
padding: 0 5px;
.note-form-option { .note-form-option {
margin-top: 8px; margin-top: 8px;
...@@ -333,6 +325,18 @@ ul.notes { ...@@ -333,6 +325,18 @@ ul.notes {
.js-notify-commit-author { .js-notify-commit-author {
float: left; float: left;
} }
.write-preview-btn {
// makes the "absolute" position for links relative to this
position: relative;
// preview/edit buttons
> a {
position: absolute;
right: 5px;
top: 8px;
}
}
} }
.note-edit-form { .note-edit-form {
...@@ -367,3 +371,8 @@ ul.notes { ...@@ -367,3 +371,8 @@ ul.notes {
.parallel-comment { .parallel-comment {
padding: 6px; padding: 6px;
} }
.error-alert > .alert {
margin-top: 5px;
margin-bottom: 5px;
}
.global-notifications-form .level-title {
font-size: 15px;
color: #333;
font-weight: bold;
}
.notification-icon-holder {
width: 20px;
float: left;
}
.ns-part {
color: $bg_primary;
}
.ns-watch {
color: $bg_success;
}
.ns-mute {
color: $bg_danger;
}
.update-notifications {
.radio-inline {
margin-right: 9%;
}
}
.account-page { .account-page {
fieldset { fieldset {
margin-bottom: 15px; margin-bottom: 15px;
...@@ -114,14 +108,3 @@ ...@@ -114,14 +108,3 @@
height: 50px; height: 50px;
} }
} }
.global-notifications-form .level-title {
font-size: 15px;
color: #333;
font-weight: bold;
}
.notification-icon-holder {
width: 20px;
float: left;
}
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
font-size: 17px; font-size: 17px;
background: #f1f1f1; background: #f1f1f1;
border-radius: 4px; border-radius: 4px;
color: #888; color: #444;
position: absolute; position: absolute;
margin-left: -55px; margin-left: -55px;
text-shadow: 0 1px 1px #FFF; text-shadow: 0 1px 1px #FFF;
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
.btn { .btn {
background: none; background: none;
color: #29b; color: $link_color;
&.active { &.active {
color: #333; color: #333;
...@@ -179,11 +179,6 @@ ul.nav.nav-projects-tabs { ...@@ -179,11 +179,6 @@ ul.nav.nav-projects-tabs {
font-weight: normal; font-weight: normal;
} }
.new-tag-btn {
position: relative;
top: -5px;
}
.public-projects .repo-info { .public-projects .repo-info {
color: #777; color: #777;
...@@ -232,3 +227,27 @@ ul.nav.nav-projects-tabs { ...@@ -232,3 +227,27 @@ ul.nav.nav-projects-tabs {
.deploy-project-label { .deploy-project-label {
margin: 1px; margin: 1px;
} }
.vs-public {
color: $bg_primary;
}
.vs-internal {
color: $bg_warning;
}
.vs-private {
color: $bg_success;
}
.breadcrumb.repo-breadcrumb {
padding: 2px 0;
background: white;
border: none;
font-size: 16px;
> li + li:before {
padding: 0 3px;
color: #999;
}
}
...@@ -3,3 +3,6 @@ ...@@ -3,3 +3,6 @@
padding-top: 0; padding-top: 0;
} }
.snippet-form-holder .file-holder .file-title {
padding: 2px;
}
...@@ -53,10 +53,14 @@ ...@@ -53,10 +53,14 @@
vertical-align: middle; vertical-align: middle;
a { a {
&:hover { &:hover {
color: $primary_color; color: $link_hover_color;
} }
} }
i {
color: $bg_primary;
}
img { img {
position: relative; position: relative;
top:-1px; top:-1px;
...@@ -109,18 +113,17 @@ ...@@ -109,18 +113,17 @@
} }
} }
.tree-btn-group { .tree-download-holder .btn {
top: 2px; padding: 4px 12px;
.btn {
margin-right: 0px;
padding: 2px 10px;
}
} }
.tree-ref-holder { .tree-ref-holder {
float: left; float: left;
margin-top: 8px; margin-right: 6px;
.select2-container .select2-choice, .select2-container.select2-drop-above .select2-choice {
padding: 4px 12px;
}
} }
.readme-holder { .readme-holder {
...@@ -141,6 +144,8 @@ ...@@ -141,6 +144,8 @@
margin-bottom: 10px; margin-bottom: 10px;
.commit { .commit {
padding: 10px 15px;
.commit-row-title { .commit-row-title {
font-size: 13px; font-size: 13px;
......
.wall-page {
.wall-note-form {
@extend .col-md-12;
margin: 0;
height: 140px;
background: #F9F9F9;
position: fixed;
bottom: 0px;
padding: 3px;
padding-bottom: 25px;
border: 1px solid #DDD;
}
.notes {
margin-bottom: 160px;
background: #FFE;
border: 1px solid #EED;
> li {
@extend .clearfix;
border-bottom: 1px solid #EED;
padding: 10px;
}
.wall-author {
color: #666;
float: left;
font-size: 12px;
width: 120px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.wall-text {
border-left: 1px solid #CCC;
margin-left: 10px;
padding-left: 10px;
float: left;
width: 75%;
}
.wall-file {
margin-left: 8px;
background: #EEE;
}
abbr {
float: right;
color: #AAA;
border: none;
}
}
}
...@@ -16,28 +16,28 @@ ...@@ -16,28 +16,28 @@
@extend .header-dark; @extend .header-dark;
&.navbar-gitlab { &.navbar-gitlab {
.navbar-inner { .navbar-inner {
background: #00AC7E; background: #019875;
border-bottom: 1px solid #00AC7E; border-bottom: 1px solid #019875;
.app_logo, .navbar-toggle { .app_logo, .navbar-toggle {
&:hover { &:hover {
background-color: #009C6E; background-color: #018865;
} }
} }
.separator { .separator {
background: #009C6F; background: #018865;
border-left: 1px solid #10BC8E; border-left: 1px solid #11A885;
} }
.nav > li > a { .nav > li > a {
color: #ADC; color: #ADC;
} }
.search-input { .search-input {
border-color: #7fd5be; border-color: #8ba;
} }
} }
} }
} }
.nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
background: #00AC7E; background: #019875;
} }
} }
...@@ -8,6 +8,8 @@ class Admin::GroupsController < Admin::ApplicationController ...@@ -8,6 +8,8 @@ class Admin::GroupsController < Admin::ApplicationController
end end
def show def show
@members = @group.members.order("group_access DESC").page(params[:members_page]).per(30)
@projects = @group.projects.page(params[:projects_page]).per(30)
end end
def new def new
......
...@@ -4,10 +4,8 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -4,10 +4,8 @@ class Admin::ProjectsController < Admin::ApplicationController
before_filter :repository, only: [:show, :transfer] before_filter :repository, only: [:show, :transfer]
def index def index
owner_id = params[:owner_id] @projects = Project.all
user = User.find_by(id: owner_id) @projects = @projects.where(namespace_id: params[:namespace_id]) if params[:namespace_id].present?
@projects = user ? user.owned_projects : Project.all
@projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present? @projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
@projects = @projects.with_push if params[:with_push].present? @projects = @projects.with_push if params[:with_push].present?
@projects = @projects.abandoned if params[:abandoned].present? @projects = @projects.abandoned if params[:abandoned].present?
...@@ -17,6 +15,11 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -17,6 +15,11 @@ class Admin::ProjectsController < Admin::ApplicationController
end end
def show def show
if @group
@group_members = @group.members.order("group_access DESC").page(params[:group_members_page]).per(30)
end
@project_members = @project.users_projects.page(params[:project_members_page]).per(30)
end end
def transfer def transfer
......
...@@ -8,7 +8,8 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -8,7 +8,8 @@ class Admin::UsersController < Admin::ApplicationController
end end
def show def show
@projects = user.authorized_projects @personal_projects = user.personal_projects
@joined_projects = user.projects.joined(@user)
end end
def new def new
......
...@@ -4,7 +4,6 @@ class ApplicationController < ActionController::Base ...@@ -4,7 +4,6 @@ class ApplicationController < ActionController::Base
before_filter :authenticate_user! before_filter :authenticate_user!
before_filter :reject_blocked! before_filter :reject_blocked!
before_filter :check_password_expiration before_filter :check_password_expiration
around_filter :set_current_user_for_thread
before_filter :add_abilities before_filter :add_abilities
before_filter :ldap_security_check before_filter :ldap_security_check
before_filter :dev_tools if Rails.env == 'development' before_filter :dev_tools if Rails.env == 'development'
...@@ -53,15 +52,6 @@ class ApplicationController < ActionController::Base ...@@ -53,15 +52,6 @@ class ApplicationController < ActionController::Base
end end
end end
def set_current_user_for_thread
Thread.current[:current_user] = current_user
begin
yield
ensure
Thread.current[:current_user] = nil
end
end
def abilities def abilities
@abilities ||= Six.new @abilities ||= Six.new
end end
...@@ -174,10 +164,13 @@ class ApplicationController < ActionController::Base ...@@ -174,10 +164,13 @@ class ApplicationController < ActionController::Base
def add_gon_variables def add_gon_variables
gon.default_issues_tracker = Project.issues_tracker.default_value gon.default_issues_tracker = Project.issues_tracker.default_value
gon.api_version = API::API.version gon.api_version = API::API.version
gon.api_token = current_user.private_token if current_user
gon.gravatar_url = request.ssl? || Gitlab.config.gitlab.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
gon.gravatar_enabled = Gitlab.config.gravatar.enabled gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s
if current_user
gon.current_user_id = current_user.id
gon.api_token = current_user.private_token
end
end end
def check_password_expiration def check_password_expiration
......
...@@ -14,4 +14,3 @@ class FilesController < ApplicationController ...@@ -14,4 +14,3 @@ class FilesController < ApplicationController
end end
end end
end end
...@@ -5,11 +5,11 @@ class GroupsController < ApplicationController ...@@ -5,11 +5,11 @@ class GroupsController < ApplicationController
# Authorize # Authorize
before_filter :authorize_read_group!, except: [:new, :create] before_filter :authorize_read_group!, except: [:new, :create]
before_filter :authorize_admin_group!, only: [:edit, :update, :destroy] before_filter :authorize_admin_group!, only: [:edit, :update, :destroy, :projects]
before_filter :authorize_create_group!, only: [:new, :create] before_filter :authorize_create_group!, only: [:new, :create]
# Load group projects # Load group projects
before_filter :projects, except: [:new, :create] before_filter :load_projects, except: [:new, :create, :projects, :edit, :update]
before_filter :default_filter, only: [:issues, :merge_requests] before_filter :default_filter, only: [:issues, :merge_requests]
...@@ -81,9 +81,13 @@ class GroupsController < ApplicationController ...@@ -81,9 +81,13 @@ class GroupsController < ApplicationController
def edit def edit
end end
def projects
@projects = @group.projects.page(params[:page])
end
def update def update
if @group.update_attributes(params[:group]) if @group.update_attributes(params[:group])
redirect_to @group, notice: 'Group was successfully updated.' redirect_to edit_group_path(@group), notice: 'Group was successfully updated.'
else else
render action: "edit" render action: "edit"
end end
...@@ -101,17 +105,17 @@ class GroupsController < ApplicationController ...@@ -101,17 +105,17 @@ class GroupsController < ApplicationController
@group ||= Group.find_by(path: params[:id]) @group ||= Group.find_by(path: params[:id])
end end
def projects def load_projects
@projects ||= ProjectsFinder.new.execute(current_user, group: group).sorted_by_activity.non_archived @projects ||= ProjectsFinder.new.execute(current_user, group: group).sorted_by_activity.non_archived
end end
def project_ids def project_ids
projects.pluck(:id) @projects.pluck(:id)
end end
# Dont allow unauthorized access to group # Dont allow unauthorized access to group
def authorize_read_group! def authorize_read_group!
unless @group and (projects.present? or can?(current_user, :read_group, @group)) unless @group and (@projects.present? or can?(current_user, :read_group, @group))
if current_user.nil? if current_user.nil?
return authenticate_user! return authenticate_user!
else else
......
...@@ -2,12 +2,12 @@ class HelpController < ApplicationController ...@@ -2,12 +2,12 @@ class HelpController < ApplicationController
def index def index
end end
def api def show
@category = params[:category] @category = params[:category]
@category = "README" if @category.blank? @file = params[:file]
if File.exists?(Rails.root.join('doc', 'api', @category + '.md')) if File.exists?(Rails.root.join('doc', @category, @file + '.md'))
render 'api' render 'show'
else else
not_found! not_found!
end end
......
class NamespacesController < ApplicationController
skip_before_filter :authenticate_user!
def show
namespace = Namespace.find_by(path: params[:id])
unless namespace
return render_404
end
if namespace.type == "Group"
redirect_to group_path(namespace)
else
redirect_to user_path(namespace.owner)
end
end
end
...@@ -4,11 +4,12 @@ class Projects::BranchesController < Projects::ApplicationController ...@@ -4,11 +4,12 @@ class Projects::BranchesController < Projects::ApplicationController
before_filter :require_non_empty_project before_filter :require_non_empty_project
before_filter :authorize_code_access! before_filter :authorize_code_access!
before_filter :authorize_push!, only: [:create] before_filter :authorize_push!, only: [:create, :destroy]
before_filter :authorize_admin_project!, only: [:destroy]
def index def index
@branches = Kaminari.paginate_array(@repository.branches).page(params[:page]).per(30) @sort = params[:sort] || 'name'
@branches = @repository.branches_sorted_by(@sort)
@branches = Kaminari.paginate_array(@branches).page(params[:page]).per(30)
end end
def recent def recent
...@@ -16,21 +17,18 @@ class Projects::BranchesController < Projects::ApplicationController ...@@ -16,21 +17,18 @@ class Projects::BranchesController < Projects::ApplicationController
end end
def create def create
CreateBranchService.new.execute(project, params[:branch_name], params[:ref], current_user) @branch = CreateBranchService.new.execute(project, params[:branch_name], params[:ref], current_user)
redirect_to project_branches_path(@project) redirect_to project_tree_path(@project, @branch.name)
end end
def destroy def destroy
branch = @repository.find_branch(params[:id]) DeleteBranchService.new.execute(project, params[:id], current_user)
@branch_name = params[:id]
if branch && @repository.rm_branch(branch.name)
Event.create_ref_event(@project, current_user, branch, 'rm')
end
respond_to do |format| respond_to do |format|
format.html { redirect_to project_branches_path(@project) } format.html { redirect_to project_branches_path(@project) }
format.js { render nothing: true } format.js
end end
end end
end end
...@@ -12,7 +12,12 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -12,7 +12,12 @@ class Projects::CommitController < Projects::ApplicationController
return git_not_found! unless @commit return git_not_found! unless @commit
@line_notes = project.notes.for_commit_id(commit.id).inline @line_notes = project.notes.for_commit_id(commit.id).inline
@branches = project.repository.branch_names_contains(commit.id)
@branches = begin
project.repository.branch_names_contains(commit.id)
rescue Grit::Git::GitTimeout
[]
end
begin begin
@suppress_diff = true if commit.diff_suppress? && !params[:force_show_diff] @suppress_diff = true if commit.diff_suppress? && !params[:force_show_diff]
......
...@@ -4,7 +4,7 @@ class Projects::GroupLinksController < Projects::ApplicationController ...@@ -4,7 +4,7 @@ class Projects::GroupLinksController < Projects::ApplicationController
def index def index
@group_links = project.project_group_links.all @group_links = project.project_group_links.all
@available_groups = Group.scoped @available_groups = Group.all
@available_groups -= project.invited_groups @available_groups -= project.invited_groups
@available_groups -= [project.group] @available_groups -= [project.group]
end end
......
...@@ -69,7 +69,9 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -69,7 +69,9 @@ class Projects::IssuesController < Projects::ApplicationController
render :new render :new
end end
end end
format.js format.js do |format|
@link = @issue.attachment.url.to_js
end
end end
end end
...@@ -85,6 +87,12 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -85,6 +87,12 @@ class Projects::IssuesController < Projects::ApplicationController
render :edit render :edit
end end
end end
format.json do
render json: {
saved: @issue.valid?,
assignee_avatar_url: @issue.assignee.try(:avatar_url)
}
end
end end
end end
......
...@@ -16,6 +16,8 @@ class Projects::LabelsController < Projects::ApplicationController ...@@ -16,6 +16,8 @@ class Projects::LabelsController < Projects::ApplicationController
redirect_to project_issues_path(@project) redirect_to project_issues_path(@project)
elsif params[:redirect] == 'merge_requests' elsif params[:redirect] == 'merge_requests'
redirect_to project_merge_requests_path(@project) redirect_to project_merge_requests_path(@project)
else
redirect_to project_labels_path(@project)
end end
end end
......
...@@ -74,15 +74,27 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -74,15 +74,27 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request.source_branch @merge_request.source_branch
) )
@compare_failed = false
@commits = compare_action.commits @commits = compare_action.commits
@commits.map! { |commit| Commit.new(commit) }
@commit = @commits.first if @commits
@commits.map! { |commit| Commit.new(commit) }
@commit = @commits.first
else
# false value because failed to get commits from satellite
@commits = []
@compare_failed = true
end
@diffs = compare_action.diffs @diffs = compare_action.diffs
@merge_request.title = @merge_request.source_branch.titleize.humanize @merge_request.title = @merge_request.source_branch.titleize.humanize
@merge_request.description = @merge_request.target_project.merge_requests_template @merge_request.description = @merge_request.target_project.merge_requests_template
@target_project = @merge_request.target_project @target_project = @merge_request.target_project
@target_repo = @target_project.repository @target_repo = @target_project.repository
diff_line_count = Commit::diff_line_count(@diffs)
@suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count)
@force_suppress_diff = @suppress_diff
end end
end end
...@@ -226,7 +238,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -226,7 +238,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request_diff = @merge_request.merge_request_diff @merge_request_diff = @merge_request.merge_request_diff
@allowed_to_merge = allowed_to_merge? @allowed_to_merge = allowed_to_merge?
@show_merge_controls = @merge_request.open? && @commits.any? && @allowed_to_merge @show_merge_controls = @merge_request.open? && @commits.any? && @allowed_to_merge
@allowed_to_remove_source_branch = allowed_to_remove_source_branch?
@source_branch = @merge_request.source_project.repository.find_branch(@merge_request.source_branch).try(:name) @source_branch = @merge_request.source_project.repository.find_branch(@merge_request.source_branch).try(:name)
end end
...@@ -239,11 +250,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -239,11 +250,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
render 'invalid' render 'invalid'
end end
def allowed_to_remove_source_branch?
allowed_to_push_code?(@merge_request.source_project, @merge_request.source_branch) &&
!@merge_request.disallow_source_branch_removal?
end
def allowed_to_push_code?(project, branch) def allowed_to_push_code?(project, branch)
action = if project.protected_branch?(branch) action = if project.protected_branch?(branch)
:push_code_to_protected_branches :push_code_to_protected_branches
......
class Projects::MilestonesController < Projects::ApplicationController class Projects::MilestonesController < Projects::ApplicationController
before_filter :module_enabled before_filter :module_enabled
before_filter :milestone, only: [:edit, :update, :destroy, :show] before_filter :milestone, only: [:edit, :update, :destroy, :show, :sort_issues, :sort_merge_requests]
# Allow read any milestone # Allow read any milestone
before_filter :authorize_read_milestone! before_filter :authorize_read_milestone!
...@@ -37,7 +37,7 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -37,7 +37,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end end
def create def create
@milestone = @project.milestones.new(params[:milestone]) @milestone = Milestones::CreateService.new(project, current_user, params[:milestone]).execute
if @milestone.save if @milestone.save
redirect_to project_milestone_path(@project, @milestone) redirect_to project_milestone_path(@project, @milestone)
...@@ -47,7 +47,7 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -47,7 +47,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end end
def update def update
@milestone.update_attributes(params[:milestone]) @milestone = Milestones::UpdateService.new(project, current_user, params[:milestone]).execute(milestone)
respond_to do |format| respond_to do |format|
format.js format.js
...@@ -72,6 +72,26 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -72,6 +72,26 @@ class Projects::MilestonesController < Projects::ApplicationController
end end
end end
def sort_issues
@issues = @milestone.issues.where(id: params['sortable_issue'])
@issues.each do |issue|
issue.position = params['sortable_issue'].index(issue.id.to_s) + 1
issue.save
end
render json: { saved: true }
end
def sort_merge_requests
@merge_requests = @milestone.merge_requests.where(id: params['sortable_merge_request'])
@merge_requests.each do |merge_request|
merge_request.position = params['sortable_merge_request'].index(merge_request.id.to_s) + 1
merge_request.save
end
render json: { saved: true }
end
protected protected
def milestone def milestone
......
class Projects::ProtectedBranchesController < Projects::ApplicationController class Projects::ProtectedBranchesController < Projects::ApplicationController
# Authorize # Authorize
before_filter :authorize_read_project!
before_filter :require_non_empty_project before_filter :require_non_empty_project
before_filter :authorize_admin_project!
before_filter :authorize_admin_project!, only: [:destroy, :create] layout "project_settings"
def index def index
@branches = @project.protected_branches.to_a @branches = @project.protected_branches.to_a
......
...@@ -31,9 +31,23 @@ class Projects::RefsController < Projects::ApplicationController ...@@ -31,9 +31,23 @@ class Projects::RefsController < Projects::ApplicationController
end end
def logs_tree def logs_tree
contents = tree.entries @offset = if params[:offset].present?
@logs = contents.map do |content| params[:offset].to_i
file = params[:path] ? File.join(params[:path], content.name) : content.name else
0
end
@limit = 10
@path = params[:path]
contents = []
contents += tree.trees
contents += tree.blobs
contents += tree.submodules
@logs = contents[@offset, @limit].to_a.map do |content|
file = @path ? File.join(@path, content.name) : content.name
last_commit = @repo.last_commit_for_path(@commit.id, file) last_commit = @repo.last_commit_for_path(@commit.id, file)
{ {
file_name: content.name, file_name: content.name,
......
...@@ -13,11 +13,8 @@ class Projects::TagsController < Projects::ApplicationController ...@@ -13,11 +13,8 @@ class Projects::TagsController < Projects::ApplicationController
end end
def create def create
@repository.add_tag(params[:tag_name], params[:ref]) @tag = CreateTagService.new.execute(@project, params[:tag_name],
params[:ref], current_user)
if new_tag = @repository.find_tag(params[:tag_name])
Event.create_ref_event(@project, current_user, new_tag, 'add', 'refs/tags')
end
redirect_to project_tags_path(@project) redirect_to project_tags_path(@project)
end end
......
class Projects::WallsController < Projects::ApplicationController
before_filter :module_enabled
respond_to :js, :html
def show
@note = @project.notes.new
respond_to do |format|
format.html
end
end
protected
def module_enabled
return render_404 unless @project.wall_enabled
end
end
...@@ -44,7 +44,7 @@ class ProjectsController < ApplicationController ...@@ -44,7 +44,7 @@ class ProjectsController < ApplicationController
end end
def transfer def transfer
::Projects::TransferService.new(project, current_user, params).execute ::Projects::TransferService.new(project, current_user, params[:project]).execute
end end
def show def show
...@@ -162,8 +162,29 @@ class ProjectsController < ApplicationController ...@@ -162,8 +162,29 @@ class ProjectsController < ApplicationController
end end
end end
def upload_image
link_to_image = ::Projects::ImageService.new(repository, params, root_url).execute
respond_to do |format|
if link_to_image
format.json { render json: { link: link_to_image } }
else
format.json { render json: "Invalid file.", status: :unprocessable_entity }
end
end
end
private private
def upload_path
base_dir = FileUploader.generate_dir
File.join(repository.path_with_namespace, base_dir)
end
def accepted_images
%w(png jpg jpeg gif)
end
def set_title def set_title
@title = 'New Project' @title = 'New Project'
end end
...@@ -190,6 +211,6 @@ class ProjectsController < ApplicationController ...@@ -190,6 +211,6 @@ class ProjectsController < ApplicationController
end end
def sorted(users) def sorted(users)
users.uniq.sort_by(&:username).map { |user| { username: user.username, name: user.name } } users.uniq.to_a.compact.sort_by(&:username).map { |user| { username: user.username, name: user.name } }
end end
end end
...@@ -14,7 +14,7 @@ class SnippetsController < ApplicationController ...@@ -14,7 +14,7 @@ class SnippetsController < ApplicationController
layout 'navless' layout 'navless'
def index def index
@snippets = Snippet.public.fresh.non_expired.page(params[:page]).per(20) @snippets = Snippet.are_public.fresh.non_expired.page(params[:page]).per(20)
end end
def user_index def user_index
...@@ -26,15 +26,15 @@ class SnippetsController < ApplicationController ...@@ -26,15 +26,15 @@ class SnippetsController < ApplicationController
if @user == current_user if @user == current_user
@snippets = case params[:scope] @snippets = case params[:scope]
when 'public' then when 'are_public' then
@snippets.public @snippets.are_public
when 'private' then when 'are_private' then
@snippets.private @snippets.are_private
else else
@snippets @snippets
end end
else else
@snippets = @snippets.public @snippets = @snippets.are_public
end end
@snippets = @snippets.page(params[:page]).per(20) @snippets = @snippets.page(params[:page]).per(20)
......
...@@ -4,12 +4,24 @@ class UsersController < ApplicationController ...@@ -4,12 +4,24 @@ class UsersController < ApplicationController
def show def show
@user = User.find_by_username!(params[:username]) @user = User.find_by_username!(params[:username])
@projects = @user.authorized_projects.accessible_to(current_user)
if !current_user && @projects.empty? unless current_user || @user.public_profile?
return authenticate_user! return authenticate_user!
end end
@groups = @user.groups.accessible_to(current_user)
@events = @user.recent_events.where(project_id: @projects.pluck(:id)).limit(20) # Projects user can view
authorized_projects_ids = ProjectsFinder.new.execute(current_user).pluck(:id)
@projects = @user.personal_projects.
where(id: authorized_projects_ids)
# Collect only groups common for both users
@groups = @user.groups & GroupsFinder.new.execute(current_user)
# Get user activity feed for projects common for both users
@events = @user.recent_events.
where(project_id: authorized_projects_ids).limit(20)
@title = @user.name @title = @user.name
end end
......
...@@ -49,7 +49,7 @@ class BaseFinder ...@@ -49,7 +49,7 @@ class BaseFinder
elsif current_user && params[:authorized_only].presence elsif current_user && params[:authorized_only].presence
klass.of_projects(current_user.authorized_projects).references(:project) klass.of_projects(current_user.authorized_projects).references(:project)
else else
klass.of_projects(Project.accessible_to(current_user)).references(:project) klass.of_projects(ProjectsFinder.new.execute(current_user)).references(:project)
end end
end end
......
class GroupsFinder
def execute(current_user, options = {})
all_groups(current_user)
end
private
def all_groups(current_user)
if current_user
if current_user.authorized_groups.any?
# User has access to groups
#
# Return only:
# groups with public projects
# groups with internal projects
# groups with joined projects
#
group_ids = Project.public_and_internal_only.pluck(:namespace_id) +
current_user.authorized_groups.pluck(:id)
Group.where(id: group_ids)
else
# User has no group membership
#
# Return only:
# groups with public projects
# groups with internal projects
#
Group.where(id: Project.public_and_internal_only.pluck(:namespace_id))
end
else
# Not authenticated
#
# Return only:
# groups with public projects
Group.where(id: Project.public_only.pluck(:namespace_id))
end
end
end
class ProjectsFinder class ProjectsFinder
def execute(current_user, options) def execute(current_user, options = {})
group = options[:group] group = options[:group]
if group if group
...@@ -56,8 +56,36 @@ class ProjectsFinder ...@@ -56,8 +56,36 @@ class ProjectsFinder
end end
end end
def all_projects def all_projects(current_user)
# TODO: implement if current_user
raise 'Not implemented yet' if current_user.authorized_projects.any?
# User has access to private projects
#
# Return only:
# public projects
# internal projects
# joined projects
#
Project.where(
"projects.id IN (?) OR projects.visibility_level IN (?)",
current_user.authorized_projects.pluck(:id),
Project.public_and_internal_levels
)
else
# User has no access to private projects
#
# Return only:
# public projects
# internal projects
#
Project.public_and_internal_only
end
else
# Not authenticated
#
# Return only:
# public projects
Project.public_only
end
end end
end end
...@@ -60,23 +60,21 @@ module ApplicationHelper ...@@ -60,23 +60,21 @@ module ApplicationHelper
def avatar_icon(user_email = '', size = nil) def avatar_icon(user_email = '', size = nil)
user = User.find_by(email: user_email) user = User.find_by(email: user_email)
if user && user.avatar.present?
user.avatar.url if user
user.avatar_url(size) || default_avatar
else else
gravatar_icon(user_email, size) gravatar_icon(user_email, size)
end end
end end
def gravatar_icon(user_email = '', size = nil) def gravatar_icon(user_email = '', size = nil)
size = 40 if size.nil? || size <= 0 GravatarService.new.execute(user_email, size) ||
default_avatar
end
if !Gitlab.config.gravatar.enabled || user_email.blank? def default_avatar
'/assets/no_avatar.png' image_path('no_avatar.png')
else
gravatar_url = request.ssl? || gitlab_config.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url
user_email.strip!
sprintf gravatar_url, hash: Digest::MD5.hexdigest(user_email.downcase), size: size, email: user_email
end
end end
def last_commit(project) def last_commit(project)
...@@ -226,8 +224,11 @@ module ApplicationHelper ...@@ -226,8 +224,11 @@ module ApplicationHelper
GitHub::Markup.render(file_name, file_content).html_safe GitHub::Markup.render(file_name, file_content).html_safe
end end
def spinner(text = nil) def spinner(text = nil, visible = false)
content_tag :div, class: 'loading hide' do css_class = "loading"
css_class << " hide" unless visible
content_tag :div, class: css_class do
content_tag(:i, nil, class: 'icon-spinner icon-spin') + text content_tag(:i, nil, class: 'icon-spinner icon-spin') + text
end end
end end
...@@ -235,4 +236,31 @@ module ApplicationHelper ...@@ -235,4 +236,31 @@ module ApplicationHelper
def ldap_enabled? def ldap_enabled?
Gitlab.config.ldap.enabled Gitlab.config.ldap.enabled
end end
def link_to(name = nil, options = nil, html_options = nil, &block)
begin
uri = URI(options)
host = uri.host
absolute_uri = uri.absolute?
rescue URI::InvalidURIError, ArgumentError
host = nil
absolute_uri = nil
end
# Add "nofollow" only to external links
if host && host != Gitlab.config.gitlab.host && absolute_uri
if html_options
if html_options[:rel]
html_options[:rel] << " nofollow"
else
html_options.merge!(rel: "nofollow")
end
else
html_options = Hash.new
html_options[:rel] = "nofollow"
end
end
super
end
end end
module BlobHelper
def highlightjs_class(blob_name)
if blob_name.include?('.')
ext = blob_name.split('.').last
return 'language-' + ext
else
if no_highlight_files.include?(blob_name.downcase)
'no-highlight'
else
blob_name.downcase
end
end
end
def no_highlight_files
%w(credits changelog copying copyright license authors)
end
end
module BranchesHelper
def can_remove_branch?(project, branch_name)
if project.protected_branch? branch_name
false
elsif branch_name == project.repository.root_ref
false
else
can?(current_user, :push_code, project)
end
end
def can_push_branch?(project, branch_name)
return false unless project.repository.branch_names.include?(branch_name)
action = if project.protected_branch?(branch_name)
:push_code_to_protected_branches
else
:push_code
end
current_user.can?(action, project)
end
end
...@@ -76,15 +76,13 @@ module CommitsHelper ...@@ -76,15 +76,13 @@ module CommitsHelper
# Add the root project link and the arrow icon # Add the root project link and the arrow icon
crumbs = content_tag(:li) do crumbs = content_tag(:li) do
content_tag(:span, nil, class: 'arrow') + link_to(@project.path, project_commits_path(@project, @ref))
link_to(@project.name, project_commits_path(@project, @ref))
end end
if @path if @path
parts = @path.split('/') parts = @path.split('/')
parts.each_with_index do |part, i| parts.each_with_index do |part, i|
crumbs += content_tag(:span, ' / ', class: 'divider')
crumbs += content_tag(:li) do crumbs += content_tag(:li) do
# The text is just the individual part, but the link needs all the parts before it # The text is just the individual part, but the link needs all the parts before it
link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/'))) link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
...@@ -195,11 +193,11 @@ module CommitsHelper ...@@ -195,11 +193,11 @@ module CommitsHelper
def commit_person_link(commit, options = {}) def commit_person_link(commit, options = {})
source_name = commit.send "#{options[:source]}_name".to_sym source_name = commit.send "#{options[:source]}_name".to_sym
source_email = commit.send "#{options[:source]}_email".to_sym source_email = commit.send "#{options[:source]}_email".to_sym
user = User.find_for_commit(source_email, source_name) user = User.find_for_commit(source_email, source_name)
person_name = user.nil? ? source_name : user.name person_name = user.nil? ? source_name : user.name
person_email = user.nil? ? source_email : user.email person_email = user.nil? ? source_email : user.email
text = if options[:avatar] text = if options[:avatar]
avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>} %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>}
...@@ -218,4 +216,8 @@ module CommitsHelper ...@@ -218,4 +216,8 @@ module CommitsHelper
link_to(text.html_safe, user_path(user), options) link_to(text.html_safe, user_path(user), options)
end end
end end
def diff_file_mode_changed?(diff)
diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
end
end end
...@@ -109,8 +109,6 @@ module EventsHelper ...@@ -109,8 +109,6 @@ module EventsHelper
"#{event.note_target_type} ##{truncate event.note_target_iid}" "#{event.note_target_type} ##{truncate event.note_target_iid}"
end end
end end
elsif event.wall_note?
link_to 'wall', project_wall_path(event.project)
else else
content_tag :strong do content_tag :strong do
"(deleted)" "(deleted)"
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
File mode changed from 100755 to 100644
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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