Commit feeffc44 authored by Vinnie Okada's avatar Vinnie Okada

Merge branch 'master' into markdown-tags

Use the latest HTML pipeline gem
parents 1a9c2ddc 5bbc70da

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

CHANGELOG merge=union
\ No newline at end of file
*.log
*.swp
.DS_Store
.bundle .bundle
.chef
.directory
.envrc
.gitlab_shell_secret
.idea
.rbenv-version
.rbx/ .rbx/
db/*.sqlite3
db/*.sqlite3-journal
log/*.log*
tmp/
.sass-cache/
coverage/*
backups/*
*.swp
public/uploads/
.ruby-version
.ruby-gemset .ruby-gemset
.ruby-version
.rvmrc .rvmrc
.rbenv-version .sass-cache/
.directory .secret
nohup.out
Vagrantfile
.vagrant .vagrant
config/gitlab.yml Vagrantfile
backups/*
config/aws.yml
config/database.yml config/database.yml
config/gitlab.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/initializers/smtp_settings.rb
config/unicorn.rb
config/resque.yml config/resque.yml
config/aws.yml config/unicorn.rb
coverage/*
db/*.sqlite3
db/*.sqlite3-journal
db/data.yml db/data.yml
.idea
.DS_Store
.chef
vendor/bundle/*
rails_best_practices_output.html
doc/code/* doc/code/*
.secret
*.log
public/uploads.*
public/assets/
.envrc
dump.rdb dump.rdb
log/*.log*
nohup.out
public/assets/
public/uploads.*
public/uploads/
rails_best_practices_output.html
tags tags
tmp/
vendor/bundle/*
user: git user: git
group: git group: git
services:
- postgres
before_precompile: ./bin/pkgr_before_precompile.sh before_precompile: ./bin/pkgr_before_precompile.sh
targets: targets:
debian-7: &wheezy debian-7: &wheezy
build_dependencies: build_dependencies:
- libkrb5-dev
- libicu-dev - libicu-dev
- cmake - cmake
- pkg-config - pkg-config
...@@ -14,6 +17,7 @@ targets: ...@@ -14,6 +17,7 @@ targets:
ubuntu-12.04: *wheezy ubuntu-12.04: *wheezy
ubuntu-14.04: ubuntu-14.04:
build_dependencies: build_dependencies:
- libkrb5-dev
- libicu-dev - libicu-dev
- cmake - cmake
- pkg-config - pkg-config
...@@ -23,6 +27,7 @@ targets: ...@@ -23,6 +27,7 @@ targets:
- git - git
centos-6: centos-6:
build_dependencies: build_dependencies:
- krb5-devel
- libicu-devel - libicu-devel
- cmake - cmake
- pkgconfig - pkgconfig
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -28,22 +28,30 @@ gem 'omniauth-google-oauth2' ...@@ -28,22 +28,30 @@ gem 'omniauth-google-oauth2'
gem 'omniauth-twitter' gem 'omniauth-twitter'
gem 'omniauth-github' gem 'omniauth-github'
gem 'omniauth-shibboleth' gem 'omniauth-shibboleth'
gem 'omniauth-kerberos'
gem 'omniauth-gitlab'
gem 'omniauth-bitbucket'
gem 'doorkeeper', '2.1.0'
gem "rack-oauth2", "~> 1.0.5"
# Browser detection
gem "browser"
# 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", '7.0.0.rc9' gem "gitlab_git", '~> 7.1.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.rc2', require: 'grack'
# LDAP Auth # LDAP Auth
gem 'gitlab_omniauth-ldap', '1.1.0', require: "omniauth-ldap" gem 'gitlab_omniauth-ldap', '1.2.1', require: "omniauth-ldap"
# Git Wiki # Git Wiki
gem 'gollum-lib', '~> 3.0.0' gem 'gollum-lib', '~> 4.0.0'
# Language detection # Language detection
gem "gitlab-linguist", "~> 3.0.0", require: "linguist" gem "gitlab-linguist", "~> 3.0.1", require: "linguist"
# API # API
gem "grape", "~> 0.6.1" gem "grape", "~> 0.6.1"
...@@ -80,7 +88,7 @@ gem "six" ...@@ -80,7 +88,7 @@ gem "six"
gem "seed-fu" gem "seed-fu"
# Markup pipeline for GitLab # Markup pipeline for GitLab
gem 'html-pipeline-gitlab', '~> 0.1.0' gem 'html-pipeline-gitlab', '~> 0.1'
# Markdown to HTML # Markdown to HTML
gem "github-markup" gem "github-markup"
...@@ -89,7 +97,7 @@ gem "github-markup" ...@@ -89,7 +97,7 @@ gem "github-markup"
gem 'redcarpet', '~> 3.1.2' gem 'redcarpet', '~> 3.1.2'
gem 'RedCloth' gem 'RedCloth'
gem 'rdoc', '~>3.6' gem 'rdoc', '~>3.6'
gem 'org-ruby', '= 0.9.9' gem 'org-ruby', '= 0.9.12'
gem 'creole', '~>0.3.6' gem 'creole', '~>0.3.6'
gem 'wikicloth', '=0.8.1' gem 'wikicloth', '=0.8.1'
gem 'asciidoctor', '= 0.1.4' gem 'asciidoctor', '= 0.1.4'
...@@ -112,7 +120,7 @@ gem "acts-as-taggable-on" ...@@ -112,7 +120,7 @@ gem "acts-as-taggable-on"
# Background jobs # Background jobs
gem 'slim' gem 'slim'
gem 'sinatra', require: nil gem 'sinatra', require: nil
gem 'sidekiq', '2.17.0' gem 'sidekiq', '~> 3.3'
# HTTP requests # HTTP requests
gem "httparty" gem "httparty"
...@@ -134,7 +142,7 @@ gem "redis-rails" ...@@ -134,7 +142,7 @@ gem "redis-rails"
gem 'tinder', '~> 1.9.2' gem 'tinder', '~> 1.9.2'
# HipChat integration # HipChat integration
gem "hipchat", "~> 0.14.0" gem "hipchat", "~> 1.4.0"
# Flowdock integration # Flowdock integration
gem "gitlab-flowdock-git-hook", "~> 0.4.2" gem "gitlab-flowdock-git-hook", "~> 0.4.2"
...@@ -143,11 +151,17 @@ gem "gitlab-flowdock-git-hook", "~> 0.4.2" ...@@ -143,11 +151,17 @@ gem "gitlab-flowdock-git-hook", "~> 0.4.2"
gem "gemnasium-gitlab-service", "~> 0.2" gem "gemnasium-gitlab-service", "~> 0.2"
# Slack integration # Slack integration
gem "slack-notifier", "~> 0.3.2" gem "slack-notifier", "~> 1.0.0"
# Asana integration
gem 'asana', '~> 0.0.6'
# d3 # d3
gem "d3_rails", "~> 3.1.4" gem "d3_rails", "~> 3.1.4"
#cal-heatmap
gem "cal-heatmap-rails", "~> 0.0.1"
# underscore-rails # underscore-rails
gem "underscore-rails", "~> 1.4.4" gem "underscore-rails", "~> 1.4.4"
...@@ -163,13 +177,15 @@ gem 'ace-rails-ap' ...@@ -163,13 +177,15 @@ gem 'ace-rails-ap'
# Keyboard shortcuts # Keyboard shortcuts
gem 'mousetrap-rails' gem 'mousetrap-rails'
# Semantic UI Sass for Sidebar # Detect and convert string character encoding
gem 'semantic-ui-sass', '~> 0.16.1.0' gem 'charlock_holmes'
# Shutting down requests that take too long
gem "slowpoke"
gem "sass-rails", '~> 4.0.2' gem "sass-rails", '~> 4.0.2'
gem "coffee-rails" gem "coffee-rails"
gem "uglifier" gem "uglifier"
gem "therubyracer"
gem 'turbolinks' gem 'turbolinks'
gem 'jquery-turbolinks' gem 'jquery-turbolinks'
...@@ -181,24 +197,25 @@ gem "jquery-scrollto-rails" ...@@ -181,24 +197,25 @@ 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", '~> 4.2' gem "font-awesome-rails", '~> 4.2'
gem "gitlab_emoji", "~> 0.0.1.1" gem "gitlab_emoji", "~> 0.1"
gem "gon", '~> 5.0.0' gem "gon", '~> 5.0.0'
gem 'nprogress-rails' gem 'nprogress-rails'
gem 'request_store' gem 'request_store'
gem "virtus" gem "virtus"
gem 'addressable'
group :development do group :development do
gem 'brakeman', require: false
gem "annotate", "~> 2.6.0.beta2" gem "annotate", "~> 2.6.0.beta2"
gem "letter_opener" gem "letter_opener"
gem 'quiet_assets', '~> 1.0.1' gem 'quiet_assets', '~> 1.0.1'
gem 'rack-mini-profiler', require: false gem 'rack-mini-profiler', require: false
gem "byebug"
# Better errors handler # Better errors handler
gem 'better_errors' gem 'better_errors'
gem 'binding_of_caller' gem 'binding_of_caller'
gem 'rails_best_practices'
# Docs generator # Docs generator
gem "sdoc" gem "sdoc"
...@@ -208,11 +225,12 @@ end ...@@ -208,11 +225,12 @@ end
group :development, :test do group :development, :test do
gem 'coveralls', require: false gem 'coveralls', require: false
gem 'rubocop', '0.28.0', require: false
# gem 'rails-dev-tweaks' # gem 'rails-dev-tweaks'
gem 'spinach-rails' gem 'spinach-rails'
gem "rspec-rails" gem "rspec-rails", '2.99'
gem "capybara", '~> 2.2.1' gem "capybara", '~> 2.2.1'
gem "pry" gem "pry-rails"
gem "awesome_print" gem "awesome_print"
gem "database_cleaner" gem "database_cleaner"
gem "launchy" gem "launchy"
...@@ -238,14 +256,14 @@ group :development, :test do ...@@ -238,14 +256,14 @@ group :development, :test do
gem 'jasmine', '2.0.2' gem 'jasmine', '2.0.2'
gem "spring", '1.1.3' gem "spring", '~> 1.3.1'
gem "spring-commands-rspec", '1.0.1' gem "spring-commands-rspec", '1.0.4'
gem "spring-commands-spinach", '1.0.0' gem "spring-commands-spinach", '1.0.0'
end end
group :test do group :test do
gem "simplecov", require: false gem "simplecov", require: false
gem "shoulda-matchers", "~> 2.1.0" gem "shoulda-matchers", "~> 2.7.0"
gem 'email_spec' gem 'email_spec'
gem "webmock" gem "webmock"
gem 'test_after_commit' gem 'test_after_commit'
...@@ -256,3 +274,6 @@ group :production do ...@@ -256,3 +274,6 @@ group :production do
end end
gem "newrelic_rpm" gem "newrelic_rpm"
gem 'octokit', '3.7.0'
gem "rugments"
This diff is collapsed.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
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. 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.
GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)`. GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)` in a [pragmatic way](https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e).
- **Major version**: Whenever there is something significant or any backwards incompatible changes are introduced to the public API. - **Major version**: Whenever there is something significant or any backwards 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 to the public API or a minor feature is introduced, or when a set of smaller features is rolled out.
......
...@@ -71,7 +71,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue ...@@ -71,7 +71,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue
### Feature requests ### Feature requests
Thank you for your interest in improving GitLab. We don't use the issue tracker for feature requests. Things that are wrong but are not a regression compared to older versions of GitLab are considered feature requests and not issues. Please use the [feature request forum](http://feedback.gitlab.com/) for this purpose or create a merge request implementing this feature. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information. Thank you for your interest in improving GitLab. We don't use the issue tracker for feature requests. Things that are wrong but are not a regression compared to older versions of GitLab are considered feature requests and not issues. Please use the \[feature request forum\]\(http://feedback.gitlab.com/) for this purpose or create a merge request implementing this feature. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information.
### Issue report for old version ### Issue report for old version
...@@ -104,3 +104,10 @@ This merge request has been closed because a request for more information has no ...@@ -104,3 +104,10 @@ 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? 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. 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.
### Only accepting merge requests with green tests
We can only accept a merge request if all the tests are green. I've just
restarted the build. When the tests are still not passing after this restart and
you're sure that is does not have anything to do with your code changes, please
rebase with master to see if that solves the issue.
web: bundle exec unicorn_rails -p ${PORT:="3000"} -E ${RAILS_ENV:="development"} -c ${UNICORN_CONFIG:="config/unicorn.rb"} web: bundle exec unicorn_rails -p ${PORT:="3000"} -E ${RAILS_ENV:="development"} -c ${UNICORN_CONFIG:="config/unicorn.rb"}
worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitlab_shell worker: bundle exec sidekiq -q post_receive -q mailer -q system_hook -q project_web_hook -q gitlab_shell -q common -q default
...@@ -9,11 +9,19 @@ ...@@ -9,11 +9,19 @@
- Each project can also have an issue tracker and a wiki - Each project can also have an issue tracker and a wiki
- Used by more than 100,000 organizations, GitLab is the most popular solution to manage Git repositories on-premises - Used by more than 100,000 organizations, GitLab is the most popular solution to manage Git repositories on-premises
- Completely free and open source (MIT Expat license) - Completely free and open source (MIT Expat license)
- Powered by Ruby on Rails - Powered by [Ruby on Rails](https://github.com/rails/rails)
## Editions
There are two editions of GitLab.
*GitLab [Community Edition](https://about.gitlab.com/features/) (CE)* is available without any costs under an MIT license.
*GitLab Enterprise Edition (EE)* includes [extra features](https://about.gitlab.com/features/#compare) that are most useful for organizations with more than 100 users.
To get access to the EE and support please [become a subscriber](https://about.gitlab.com/pricing/).
## Canonical source ## Canonical source
- The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible. The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible.
## Code status ## Code status
...@@ -25,8 +33,6 @@ ...@@ -25,8 +33,6 @@
- [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master) - [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master)
- [![PullReview stats](https://www.pullreview.com/gitlab/gitlab-org/gitlab-ce/badges/master.svg?)](https://www.pullreview.com/gitlab.gitlab.com/gitlab-org/gitlab-ce/reviews/master)
## Website ## Website
On [about.gitlab.com](https://about.gitlab.com/) you can find more information about: On [about.gitlab.com](https://about.gitlab.com/) you can find more information about:
...@@ -40,87 +46,45 @@ On [about.gitlab.com](https://about.gitlab.com/) you can find more information a ...@@ -40,87 +46,45 @@ On [about.gitlab.com](https://about.gitlab.com/) you can find more information a
## Requirements ## Requirements
- Ubuntu/Debian/CentOS/RHEL** GitLab requires the following software:
- ruby 2.0+
- git 1.7.10+ - Ubuntu/Debian/CentOS/RHEL
- redis 2.0+ - Ruby (MRI) 2.0 or 2.1
- Git 1.7.10+
- Redis 2.0+
- MySQL or PostgreSQL - MySQL or PostgreSQL
** More details are in the [requirements doc](doc/install/requirements.md). Please see the [requirements documentation](doc/install/requirements.md) for system requirements and more information about the supported operating systems.
## Installation ## Installation
Please see [the installation page on the GitLab website](https://about.gitlab.com/installation/) for the various options. The recommended way to install GitLab is using the provided [Omnibus packages](https://about.gitlab.com/downloads/). Compared to an installation from source, this is faster and less error prone. Just select your operating system, download the respective package (Debian or RPM) and install it using the system's package manager.
Since a manual installation is a lot of work and error prone we strongly recommend fast and reliable Omnibus package installation (deb/rpm) on that page.
## Third-party applications
Access GitLab from multiple platforms with applications below. There are various other options to install GitLab, please refer to the [installation page on the GitLab website](https://about.gitlab.com/installation/) for more information.
These applications are maintained by contributors, GitLab B.V. does not offer support for them.
- [iPhone app](http://gitlabcontrol.com/) You can access a new installation with the login **`root`** and password **`5iveL!fe`**, after login you are required to set a unique password.
- [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en)
- [Chrome app](https://chrome.google.com/webstore/detail/chrome-gitlab-notifier/eageapgbnjicdjjihgclpclilenjbobi)
- [Command line client](https://github.com/drewblessing/gitlab-cli)
- [Ruby API wrapper](https://github.com/NARKOZ/gitlab)
### New versions ## Third-party applications
Since 2011 a minor or major version of GitLab is released on the 22nd of every month. Patch and security releases come out when needed. New features are detailed on the [blog](https://about.gitlab.com/blog/) and in the [changelog](CHANGELOG). For more information about the release process see the release [documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/release). Features that will likely be in the next releases can be found on the [feature request forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
### Upgrading
For updating the the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For manual installations there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update).
## Run in production mode
The Installation guide contains instructions on how to download an init script and run it automatically on boot. You can also start the init script manually: There are a lot of [third-party applications integrating with GitLab](https://about.gitlab.com/applications/). These include GUI Git clients, mobile applications and API wrappers for various languages.
sudo service gitlab start ## GitLab release cycle
or by directly calling the script: Since 2011 a minor or major version of GitLab is released on the 22nd of every month. Patch and security releases are published when needed. New features are detailed on the [blog](https://about.gitlab.com/blog/) and in the [changelog](CHANGELOG). For more information about the release process see the [release documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/release). Features that will likely be in the next releases can be found on the [feature request forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
sudo /etc/init.d/gitlab start ## Upgrading
Please login with `root` / `5iveL!fe` For updating the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For installations from source there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update) detailing all necessary commands to migrate to the next version.
## Install a development environment ## Install a development environment
We recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit). To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
If you do not use the development kit you might need to copy the example development unicorn configuration file If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone.
One small thing you also have to do when installing it yourself is to copy the example development unicorn configuration file:
cp config/unicorn.rb.example.development config/unicorn.rb cp config/unicorn.rb.example.development config/unicorn.rb
## Run in development mode Instructions on how to start GitLab and how to run the tests can be found in the [development section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#development).
Start it with [Foreman](https://github.com/ddollar/foreman)
bundle exec foreman start -p 3000
or start each component separately:
bundle exec rails s
bin/background_jobs start
And surf to [localhost:3000](http://localhost:3000/) and login with `root` / `5iveL!fe`.
## Run the tests
- Run all tests:
bundle exec rake test
- [RSpec](http://rspec.info/) unit and functional tests.
All RSpec tests: `bundle exec rake spec`
Single RSpec file: `bundle exec rspec spec/controllers/commit_controller_spec.rb`
- [Spinach](https://github.com/codegram/spinach) integration tests.
All Spinach tests: `bundle exec rake spinach`
Single Spinach test: `bundle exec spinach features/project/issues/milestones.feature`
## Documentation ## Documentation
...@@ -137,4 +101,4 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on ...@@ -137,4 +101,4 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on
## Is it awesome? ## Is it awesome?
Thanks for [asking this question](https://twitter.com/supersloth/status/489462789384056832) Joshua. Thanks for [asking this question](https://twitter.com/supersloth/status/489462789384056832) Joshua.
[These people](https://twitter.com/gitlabhq/favorites) seem to like it. [These people](https://twitter.com/gitlab/favorites) seem to like it.
7.4.0-pre 7.10.0.pre
app/assets/images/bg-header.png

210 Bytes | W: | H:

app/assets/images/bg-header.png

90 Bytes | W: | H:

app/assets/images/bg-header.png
app/assets/images/bg-header.png
app/assets/images/bg-header.png
app/assets/images/bg-header.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/bg_fallback.png

2.91 KB | W: | H:

app/assets/images/bg_fallback.png

167 Bytes | W: | H:

app/assets/images/bg_fallback.png
app/assets/images/bg_fallback.png
app/assets/images/bg_fallback.png
app/assets/images/bg_fallback.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/brand_logo.png

31.4 KB | W: | H:

app/assets/images/brand_logo.png

26.4 KB | W: | H:

app/assets/images/brand_logo.png
app/assets/images/brand_logo.png
app/assets/images/brand_logo.png
app/assets/images/brand_logo.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/chosen-sprite.png

396 Bytes | W: | H:

app/assets/images/chosen-sprite.png

367 Bytes | W: | H:

app/assets/images/chosen-sprite.png
app/assets/images/chosen-sprite.png
app/assets/images/chosen-sprite.png
app/assets/images/chosen-sprite.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/diff_note_add.png

691 Bytes | W: | H:

app/assets/images/diff_note_add.png

418 Bytes | W: | H:

app/assets/images/diff_note_add.png
app/assets/images/diff_note_add.png
app/assets/images/diff_note_add.png
app/assets/images/diff_note_add.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/icon-link.png

1019 Bytes | W: | H:

app/assets/images/icon-link.png

726 Bytes | W: | H:

app/assets/images/icon-link.png
app/assets/images/icon-link.png
app/assets/images/icon-link.png
app/assets/images/icon-link.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/icon-search.png

331 Bytes | W: | H:

app/assets/images/icon-search.png

222 Bytes | W: | H:

app/assets/images/icon-search.png
app/assets/images/icon-search.png
app/assets/images/icon-search.png
app/assets/images/icon-search.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/icon_sprite.png

2.72 KB | W: | H:

app/assets/images/icon_sprite.png

2.57 KB | W: | H:

app/assets/images/icon_sprite.png
app/assets/images/icon_sprite.png
app/assets/images/icon_sprite.png
app/assets/images/icon_sprite.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/images.png

6.49 KB | W: | H:

app/assets/images/images.png

5.71 KB | W: | H:

app/assets/images/images.png
app/assets/images/images.png
app/assets/images/images.png
app/assets/images/images.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/logo-white.png

7.33 KB | W: | H:

app/assets/images/logo-white.png

7.52 KB | W: | H:

app/assets/images/logo-white.png
app/assets/images/logo-white.png
app/assets/images/logo-white.png
app/assets/images/logo-white.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/move.png

260 Bytes | W: | H:

app/assets/images/move.png

197 Bytes | W: | H:

app/assets/images/move.png
app/assets/images/move.png
app/assets/images/move.png
app/assets/images/move.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/no_avatar.png

704 Bytes | W: | H:

app/assets/images/no_avatar.png

621 Bytes | W: | H:

app/assets/images/no_avatar.png
app/assets/images/no_avatar.png
app/assets/images/no_avatar.png
app/assets/images/no_avatar.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/no_group_avatar.png

4.77 KB | W: | H:

app/assets/images/no_group_avatar.png

942 Bytes | W: | H:

app/assets/images/no_group_avatar.png
app/assets/images/no_group_avatar.png
app/assets/images/no_group_avatar.png
app/assets/images/no_group_avatar.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/slider_handles.png

4.03 KB | W: | H:

app/assets/images/slider_handles.png

1.34 KB | W: | H:

app/assets/images/slider_handles.png
app/assets/images/slider_handles.png
app/assets/images/slider_handles.png
app/assets/images/slider_handles.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/switch_icon.png

1.17 KB | W: | H:

app/assets/images/switch_icon.png

231 Bytes | W: | H:

app/assets/images/switch_icon.png
app/assets/images/switch_icon.png
app/assets/images/switch_icon.png
app/assets/images/switch_icon.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/trans_bg.gif

50 Bytes | W: | H:

app/assets/images/trans_bg.gif

49 Bytes | W: | H:

app/assets/images/trans_bg.gif
app/assets/images/trans_bg.gif
app/assets/images/trans_bg.gif
app/assets/images/trans_bg.gif
  • 2-up
  • Swipe
  • Onion skin
class Activities class @Activities
constructor: -> constructor: ->
Pager.init 20, true Pager.init 20, true
$(".event_filter_link").bind "click", (event) => $(".event_filter_link").bind "click", (event) =>
...@@ -12,7 +12,7 @@ class Activities ...@@ -12,7 +12,7 @@ class Activities
toggleFilter: (sender) -> toggleFilter: (sender) ->
sender.parent().toggleClass "inactive" sender.parent().toggleClass "active"
event_filters = $.cookie("event_filter") event_filters = $.cookie("event_filter")
filter = sender.attr("id").split("_")[0] filter = sender.attr("id").split("_")[0]
if event_filters if event_filters
...@@ -27,5 +27,3 @@ class Activities ...@@ -27,5 +27,3 @@ class Activities
event_filters.splice index, 1 event_filters.splice index, 1
$.cookie "event_filter", event_filters.join(","), { path: '/' } $.cookie "event_filter", event_filters.join(","), { path: '/' }
@Activities = Activities
class Admin class @Admin
constructor: -> constructor: ->
$('input#user_force_random_password').on 'change', (elem) -> $('input#user_force_random_password').on 'change', (elem) ->
elems = $('#user_password, #user_password_confirmation') elems = $('#user_password, #user_password_confirmation')
...@@ -51,5 +51,3 @@ class Admin ...@@ -51,5 +51,3 @@ class Admin
$('li.group_member').bind 'ajax:success', -> $('li.group_member').bind 'ajax:success', ->
Turbolinks.visit(location.href) Turbolinks.visit(location.href)
@Admin = Admin
@Api = @Api =
groups_path: "/api/:version/groups.json"
group_path: "/api/:version/groups/:id.json"
users_path: "/api/:version/users.json" users_path: "/api/:version/users.json"
user_path: "/api/:version/users/:id.json" user_path: "/api/:version/users/:id.json"
notes_path: "/api/:version/projects/:id/notes.json" notes_path: "/api/:version/projects/:id/notes.json"
...@@ -51,6 +53,33 @@ ...@@ -51,6 +53,33 @@
).done (users) -> ).done (users) ->
callback(users) callback(users)
group: (group_id, callback) ->
url = Api.buildUrl(Api.group_path)
url = url.replace(':id', group_id)
$.ajax(
url: url
data:
private_token: gon.api_token
dataType: "json"
).done (group) ->
callback(group)
# Return groups list. Filtered by query
# Only active groups retrieved
groups: (query, skip_ldap, callback) ->
url = Api.buildUrl(Api.groups_path)
$.ajax(
url: url
data:
private_token: gon.api_token
search: query
per_page: 20
dataType: "json"
).done (groups) ->
callback(groups)
# Return project users list. Filtered by query # Return project users list. Filtered by query
# Only active users retrieved # Only active users retrieved
projectUsers: (project_id, query, callback) -> projectUsers: (project_id, query, callback) ->
......
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
#= require jquery.scrollTo #= require jquery.scrollTo
#= require jquery.blockUI #= require jquery.blockUI
#= require jquery.turbolinks #= require jquery.turbolinks
#= require jquery.sticky-kit.min
#= require turbolinks #= require turbolinks
#= require autosave
#= require bootstrap #= require bootstrap
#= require select2 #= require select2
#= require raphael #= require raphael
...@@ -24,7 +26,6 @@ ...@@ -24,7 +26,6 @@
#= require g.bar-min #= require g.bar-min
#= require chart-lib.min #= require chart-lib.min
#= require branch-graph #= require branch-graph
#= require highlight.pack
#= require ace/ace #= require ace/ace
#= require ace/ext-searchbox #= require ace/ext-searchbox
#= require d3 #= require d3
...@@ -32,7 +33,6 @@ ...@@ -32,7 +33,6 @@
#= require nprogress #= require nprogress
#= require nprogress-turbolinks #= require nprogress-turbolinks
#= require dropzone #= require dropzone
#= require semantic-ui/sidebar
#= require mousetrap #= require mousetrap
#= require mousetrap/pause #= require mousetrap/pause
#= require shortcuts #= require shortcuts
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#= require shortcuts_dashboard_navigation #= require shortcuts_dashboard_navigation
#= require shortcuts_issueable #= require shortcuts_issueable
#= require shortcuts_network #= require shortcuts_network
#= require cal-heatmap
#= require_tree . #= require_tree .
window.slugify = (text) -> window.slugify = (text) ->
...@@ -50,12 +51,6 @@ window.ajaxGet = (url) -> ...@@ -50,12 +51,6 @@ window.ajaxGet = (url) ->
window.showAndHide = (selector) -> window.showAndHide = (selector) ->
window.errorMessage = (message) ->
ehtml = $("<p>")
ehtml.addClass("error_message")
ehtml.html(message)
ehtml
window.split = (val) -> window.split = (val) ->
return val.split( /,\s*/ ) return val.split( /,\s*/ )
...@@ -63,7 +58,7 @@ window.extractLast = (term) -> ...@@ -63,7 +58,7 @@ window.extractLast = (term) ->
return split( term ).pop() return split( term ).pop()
window.rstrip = (val) -> window.rstrip = (val) ->
return val.replace(/\s+$/, '') return if val then val.replace(/\s+$/, '') else val
# Disable button if text field is empty # Disable button if text field is empty
window.disableButtonIfEmptyField = (field_selector, button_selector) -> window.disableButtonIfEmptyField = (field_selector, button_selector) ->
...@@ -81,24 +76,18 @@ window.disableButtonIfEmptyField = (field_selector, button_selector) -> ...@@ -81,24 +76,18 @@ window.disableButtonIfEmptyField = (field_selector, button_selector) ->
# Disable button if any input field with given selector is empty # Disable button if any input field with given selector is empty
window.disableButtonIfAnyEmptyField = (form, form_selector, button_selector) -> window.disableButtonIfAnyEmptyField = (form, form_selector, button_selector) ->
closest_submit = form.find(button_selector) closest_submit = form.find(button_selector)
empty = false updateButtons = ->
form.find('input').filter(form_selector).each -> filled = true
empty = true if rstrip($(this).val()) is ""
if empty
closest_submit.disable()
else
closest_submit.enable()
form.keyup ->
empty = false
form.find('input').filter(form_selector).each -> form.find('input').filter(form_selector).each ->
empty = true if rstrip($(this).val()) is "" filled = rstrip($(this).val()) != "" || !$(this).attr('required')
if empty if filled
closest_submit.disable()
else
closest_submit.enable() closest_submit.enable()
else
closest_submit.disable()
updateButtons()
form.keyup(updateButtons)
window.sanitize = (str) -> window.sanitize = (str) ->
return str.replace(/<(?:.|\n)*?>/gm, '') return str.replace(/<(?:.|\n)*?>/gm, '')
...@@ -114,8 +103,17 @@ window.unbindEvents = -> ...@@ -114,8 +103,17 @@ window.unbindEvents = ->
$(document).unbind('scroll') $(document).unbind('scroll')
$(document).off('scroll') $(document).off('scroll')
window.shiftWindow = ->
scrollBy 0, -50
document.addEventListener("page:fetch", unbindEvents) document.addEventListener("page:fetch", unbindEvents)
# Scroll the window to avoid the topnav bar
# https://github.com/twitter/bootstrap/issues/1768
if location.hash
setTimeout shiftWindow, 1
window.addEventListener "hashchange", shiftWindow
$ -> $ ->
# Click a .one_click_select field, select the contents # Click a .one_click_select field, select the contents
$(".one_click_select").on 'click', -> $(@).select() $(".one_click_select").on 'click', -> $(@).select()
...@@ -184,6 +182,8 @@ $ -> ...@@ -184,6 +182,8 @@ $ ->
form = btn.closest("form") form = btn.closest("form")
new ConfirmDangerModal(form, text) new ConfirmDangerModal(form, text)
new Aside()
(($) -> (($) ->
# Disable an element and add the 'disabled' Bootstrap class # Disable an element and add the 'disabled' Bootstrap class
$.fn.extend disable: -> $.fn.extend disable: ->
......
class @Aside
constructor: ->
$(document).off "click", "a.show-aside"
$(document).on "click", 'a.show-aside', (e) ->
e.preventDefault()
btn = $(e.currentTarget)
icon = btn.find('i')
console.log('1')
if icon.hasClass('fa-angle-left')
btn.parent().find('section').hide()
btn.parent().find('aside').fadeIn()
icon.removeClass('fa-angle-left').addClass('fa-angle-right')
else
btn.parent().find('aside').hide()
btn.parent().find('section').fadeIn()
icon.removeClass('fa-angle-right').addClass('fa-angle-left')
class @Autosave
constructor: (field, key) ->
@field = field
key = key.join("/") if key.join?
@key = "autosave/#{key}"
@field.data "autosave", this
@restore()
@field.on "input", => @save()
restore: ->
return unless window.localStorage?
try
text = window.localStorage.getItem @key
catch
return
@field.val text if text?.length > 0
@field.trigger "input"
save: ->
return unless window.localStorage?
text = @field.val()
if text?.length > 0
try
window.localStorage.setItem @key, text
else
@reset()
reset: ->
return unless window.localStorage?
try
window.localStorage.removeItem @key
class BlobView class @BlobView
constructor: -> constructor: ->
# handle multi-line select # handle multi-line select
handleMultiSelect = (e) -> handleMultiSelect = (e) ->
...@@ -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]
$.scrollTo("#L#{first_line}") unless e? $.scrollTo("#L#{first_line}", offset: -50) 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)
...@@ -71,6 +71,3 @@ class BlobView ...@@ -71,6 +71,3 @@ class BlobView
# Highlight the correct lines when the hash part of the URL changes # Highlight the correct lines when the hash part of the URL changes
$(window).on("hashchange", highlightBlobLines) $(window).on("hashchange", highlightBlobLines)
@BlobView = BlobView
class @EditBlob
constructor: (assets_path, mode)->
ace.config.set "modePath", assets_path + '/ace'
ace.config.loadModule "ace/ext/searchbox"
if mode
ace_mode = mode
editor = ace.edit("editor")
editor.focus()
@editor = editor
if ace_mode
editor.getSession().setMode "ace/mode/" + ace_mode
disableButtonIfEmptyField "#commit_message", ".js-commit-button"
$(".js-commit-button").click ->
$("#file-content").val editor.getValue()
$(".file-editor form").submit()
return false
editModePanes = $(".js-edit-mode-pane")
editModeLinks = $(".js-edit-mode a")
editModeLinks.click (event) ->
event.preventDefault()
currentLink = $(this)
paneId = currentLink.attr("href")
currentPane = editModePanes.filter(paneId)
editModeLinks.parent().removeClass "active hover"
currentLink.parent().addClass "active hover"
editModePanes.hide()
if paneId is "#preview"
currentPane.fadeIn 200
$.post currentLink.data("preview-url"),
content: editor.getValue()
, (response) ->
currentPane.empty().append response
return
else
currentPane.fadeIn 200
editor.focus()
return
editor: ->
return @editor
class @NewBlob
constructor: (assets_path, mode)->
ace.config.set "modePath", assets_path + '/ace'
ace.config.loadModule "ace/ext/searchbox"
if mode
ace_mode = mode
editor = ace.edit("editor")
editor.focus()
@editor = editor
if ace_mode
editor.getSession().setMode "ace/mode/" + ace_mode
disableButtonIfEmptyField "#commit_message", ".js-commit-button"
$(".js-commit-button").click ->
$("#file-content").val editor.getValue()
$(".file-editor form").submit()
return false
editor: ->
return @editor
class @calendar
options =
month: "short"
day: "numeric"
year: "numeric"
constructor: (timestamps, starting_year, starting_month) ->
cal = new CalHeatMap()
cal.init
itemName: ["commit"]
data: timestamps
start: new Date(starting_year, starting_month)
domainLabelFormat: "%b"
id: "cal-heatmap"
domain: "month"
subDomain: "day"
range: 12
tooltip: true
label:
position: "top"
legend: [
0
1
4
7
]
legendCellPadding: 3
onClick: (date, count) ->
return
return
class Commit class @Commit
constructor: -> constructor: ->
$('.files .diff-file').each -> $('.files .diff-file').each ->
new CommitFile(this) new CommitFile(this)
@Commit = Commit
class CommitFile class @CommitFile
constructor: (file) -> constructor: (file) ->
if $('.image', file).length if $('.image', file).length
new ImageFile(file) new ImageFile(file)
@CommitFile = CommitFile
class ImageFile class @ImageFile
# Width where images must fits in, for 2-up this gets divided by 2 # Width where images must fits in, for 2-up this gets divided by 2
@availWidth = 900 @availWidth = 900
...@@ -124,5 +124,3 @@ class ImageFile ...@@ -124,5 +124,3 @@ class ImageFile
else else
img.on 'load', => img.on 'load', =>
callback.call(this, domImg.naturalWidth, domImg.naturalHeight) callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
@ImageFile = ImageFile
class CommitsList class @CommitsList
@data = @data =
ref: null ref: null
limit: 0 limit: 0
...@@ -53,5 +53,3 @@ class CommitsList ...@@ -53,5 +53,3 @@ class CommitsList
@disable @disable
callback: => callback: =>
this.getOld() this.getOld()
this.CommitsList = CommitsList
class ConfirmDangerModal class @ConfirmDangerModal
constructor: (form, text) -> constructor: (form, text) ->
@form = form @form = form
$('.js-confirm-text').text(text || '') $('.js-confirm-text').text(text || '')
...@@ -16,5 +16,3 @@ class ConfirmDangerModal ...@@ -16,5 +16,3 @@ class ConfirmDangerModal
$('.js-confirm-danger-submit').on 'click', => $('.js-confirm-danger-submit').on 'click', =>
@form.submit() @form.submit()
@ConfirmDangerModal = ConfirmDangerModal
class Dashboard class @Dashboard
constructor: -> constructor: ->
@initSidebarTab() new ProjectsList()
$(".dash-filter").keyup ->
terms = $(this).val()
uiBox = $(this).parents('.panel').first()
if terms == "" || terms == undefined
uiBox.find(".dash-list li").show()
else
uiBox.find(".dash-list li").each (index) ->
name = $(this).find(".filter-title").text()
if name.toLowerCase().search(terms.toLowerCase()) == -1
$(this).hide()
else
$(this).show()
initSidebarTab: ->
key = "dashboard_sidebar_filter"
# store selection in cookie
$('.dash-sidebar-tabs a').on 'click', (e) ->
$.cookie(key, $(e.target).attr('id'))
# show tab from cookie
sidebar_filter = $.cookie(key)
$("#" + sidebar_filter).tab('show') if sidebar_filter
@Dashboard = Dashboard
class Diff class @Diff
UNFOLD_COUNT = 20 UNFOLD_COUNT = 20
constructor: -> constructor: ->
$(document).off('click', '.js-unfold')
$(document).on('click', '.js-unfold', (event) => $(document).on('click', '.js-unfold', (event) =>
target = $(event.target) target = $(event.target)
unfoldBottom = target.hasClass('js-unfold-bottom') unfoldBottom = target.hasClass('js-unfold-bottom')
...@@ -36,11 +37,10 @@ class Diff ...@@ -36,11 +37,10 @@ class Diff
) )
) )
$('.diff-header').stick_in_parent(recalc_every: 1, offset_top: $('.navbar').height())
lineNumbers: (line) -> lineNumbers: (line) ->
return ([0, 0]) unless line.children().length return ([0, 0]) unless line.children().length
lines = line.children().slice(0, 2) lines = line.children().slice(0, 2)
line_numbers = ($(l).attr('data-linenumber') for l in lines) line_numbers = ($(l).attr('data-linenumber') for l in lines)
(parseInt(line_number) for line_number in line_numbers) (parseInt(line_number) for line_number in line_numbers)
@Diff = Diff
...@@ -4,7 +4,6 @@ $ -> ...@@ -4,7 +4,6 @@ $ ->
class Dispatcher class Dispatcher
constructor: () -> constructor: () ->
@initSearch() @initSearch()
@initHighlight()
@initPageScripts() @initPageScripts()
initPageScripts: -> initPageScripts: ->
...@@ -27,46 +26,61 @@ class Dispatcher ...@@ -27,46 +26,61 @@ class Dispatcher
new ZenMode() new ZenMode()
when 'projects:milestones:show' when 'projects:milestones:show'
new Milestone() new Milestone()
when 'projects:milestones:new' when 'projects:milestones:new', 'projects:milestones:edit'
new ZenMode() new ZenMode()
when 'projects:issues:new','projects:issues:edit' when 'projects:issues:new','projects:issues:edit'
GitLab.GfmAutoComplete.setup() GitLab.GfmAutoComplete.setup()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
new ZenMode() new ZenMode()
new DropzoneInput($('.issue-form'))
if page == 'projects:issues:new'
new IssuableForm($('.issue-form'))
when 'projects:merge_requests:new', 'projects:merge_requests:edit' when 'projects:merge_requests:new', 'projects:merge_requests:edit'
GitLab.GfmAutoComplete.setup() GitLab.GfmAutoComplete.setup()
new Diff() new Diff()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
new ZenMode() new ZenMode()
new DropzoneInput($('.merge-request-form'))
if page == 'projects:merge_requests:new'
new IssuableForm($('.merge-request-form'))
when 'projects:merge_requests:show' when 'projects:merge_requests:show'
new Diff() new Diff()
shortcut_handler = new ShortcutsIssueable() shortcut_handler = new ShortcutsIssueable()
new ZenMode() new ZenMode()
when "projects:merge_requests:diffs" when "projects:merge_requests:diffs"
new Diff() new Diff()
new ZenMode()
when 'projects:merge_requests:index' when 'projects:merge_requests:index'
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
MergeRequests.init()
when 'dashboard:show' when 'dashboard:show'
new Dashboard() new Dashboard()
new Activities() new Activities()
when 'dashboard:projects:starred'
new Activities()
new ProjectsList()
when 'projects:commit:show' when 'projects:commit:show'
new Commit() new Commit()
new Diff() new Diff()
new ZenMode()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'projects:commits:show' when 'projects:commits:show'
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'groups:show', 'projects:show' when 'projects:show'
new Activities() new Activities()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'projects:new' when 'groups:show'
new Project() new Activities()
when 'projects:edit'
new Project()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'projects:teams:members:index' new ProjectsList()
new TeamMembers() when 'groups:group_members:index'
when 'groups:members'
new GroupMembers() new GroupMembers()
new UsersSelect()
when 'projects:project_members:index'
new ProjectMembers()
new UsersSelect()
when 'groups:new', 'groups:edit', 'admin:groups:edit'
new GroupAvatar()
when 'projects:tree:show' when 'projects:tree:show'
new TreeView() new TreeView()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
...@@ -79,20 +93,44 @@ class Dispatcher ...@@ -79,20 +93,44 @@ class Dispatcher
# Ensure we don't create a particular shortcut handler here. This is # Ensure we don't create a particular shortcut handler here. This is
# already created, where the network graph is created. # already created, where the network graph is created.
shortcut_handler = true shortcut_handler = true
when 'projects:forks:new'
new ProjectFork()
when 'users:show'
new User()
switch path.first() switch path.first()
when 'admin' then new Admin() when 'admin'
new Admin()
switch path[1]
when 'groups'
new UsersSelect()
when 'projects'
new NamespaceSelect()
when 'dashboard' when 'dashboard'
shortcut_handler = new ShortcutsDashboardNavigation() shortcut_handler = new ShortcutsDashboardNavigation()
when 'profiles'
new Profile()
when 'projects' when 'projects'
new Project()
new ProjectAvatar()
switch path[1] switch path[1]
when 'edit'
shortcut_handler = new ShortcutsNavigation()
new ProjectNew()
when 'new'
new ProjectNew()
when 'show'
new ProjectShow()
when 'issues', 'merge_requests'
new ProjectUsersSelect()
when 'wikis' when 'wikis'
new Wikis() new Wikis()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
new ZenMode() new ZenMode()
new DropzoneInput($('.wiki-form'))
when 'snippets', 'labels', 'graphs' when 'snippets', 'labels', 'graphs'
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'team_members', 'deploy_keys', 'hooks', 'services', 'protected_branches' when 'project_members', 'deploy_keys', 'hooks', 'services', 'protected_branches'
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
...@@ -107,10 +145,3 @@ class Dispatcher ...@@ -107,10 +145,3 @@ class Dispatcher
project_ref = opts.data('autocomplete-project-ref') project_ref = opts.data('autocomplete-project-ref')
new SearchAutocomplete(path, project_id, project_ref) new SearchAutocomplete(path, project_id, project_ref)
initHighlight: ->
$('.highlight pre code').each (i, e) ->
$(e).html($.map($(e).html().split("\n"), (line, i) ->
"<span class='line' id='LC" + (i + 1) + "'>" + line + "</span>"
).join("\n"))
hljs.highlightBlock(e)
class @DropzoneInput
constructor: (form) ->
Dropzone.autoDiscover = false
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>"
iconPaperclip = "<i class=\"fa fa-paperclip div-dropzone-icon\"></i>"
iconSpinner = "<i class=\"fa fa-spinner fa-spin div-dropzone-icon\"></i>"
btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
project_uploads_path = window.project_uploads_path or null
form_textarea = $(form).find("textarea.markdown-area")
form_textarea.wrap "<div class=\"div-dropzone\"></div>"
form_textarea.bind 'paste', (event) =>
handlePaste(event)
form_dropzone = $(form).find('.div-dropzone')
form_dropzone.parent().addClass "div-dropzone-wrapper"
form_dropzone.append divHover
$(".div-dropzone-hover").append iconPaperclip
form_dropzone.append divSpinner
$(".div-dropzone-spinner").append iconSpinner
$(".div-dropzone-spinner").css
"opacity": 0
"display": "none"
# Preview button
$(document).off "click", ".js-md-preview-button"
$(document).on "click", ".js-md-preview-button", (e) ->
###
Shows the Markdown preview.
Lets the server render GFM into Html and displays it.
###
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-md-write-button").parent().removeClass "active"
form.find(".js-md-preview-button").parent().addClass "active"
# toggle content
form.find(".md-write-holder").hide()
form.find(".md-preview-holder").show()
preview = form.find(".js-md-preview")
mdText = form.find(".markdown-area").val()
if mdText.trim().length is 0
preview.text "Nothing to preview."
else
preview.text "Loading..."
$.post($(this).data("url"),
md_text: mdText
).success (previewData) ->
preview.html previewData
# Write button
$(document).off "click", ".js-md-write-button"
$(document).on "click", ".js-md-write-button", (e) ->
###
Shows the Markdown textarea.
###
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-md-write-button").parent().addClass "active"
form.find(".js-md-preview-button").parent().removeClass "active"
# toggle content
form.find(".md-write-holder").show()
form.find(".md-preview-holder").hide()
dropzone = form_dropzone.dropzone(
url: project_uploads_path
dictDefaultMessage: ""
clickable: true
paramName: "file"
maxFilesize: 10
uploadMultiple: false
headers:
"X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
previewContainer: false
processing: ->
$(".div-dropzone-alert").alert "close"
dragover: ->
form_textarea.addClass "div-dropzone-focus"
form.find(".div-dropzone-hover").css "opacity", 0.7
return
dragleave: ->
form_textarea.removeClass "div-dropzone-focus"
form.find(".div-dropzone-hover").css "opacity", 0
return
drop: ->
form_textarea.removeClass "div-dropzone-focus"
form.find(".div-dropzone-hover").css "opacity", 0
form_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: ->
form_dropzone.find(".div-dropzone-spinner").css
"opacity": 0.7
"display": "inherit"
return
complete: ->
$(".dz-preview").remove()
$(".markdown-area").trigger "input"
$(".div-dropzone-spinner").css
"opacity": 0
"display": "none"
return
)
child = $(dropzone[0]).children("textarea")
formatLink = (link) ->
text = "[#{link.alt}](#{link.url})"
text = "!#{text}" if link.is_image
text
handlePaste = (event) ->
pasteEvent = event.originalEvent
if pasteEvent.clipboardData and pasteEvent.clipboardData.items
image = isImage(pasteEvent)
if image
event.preventDefault()
filename = getFilename(pasteEvent) or "image.png"
text = "{{" + filename + "}}"
pasteText(text)
uploadFile image.getAsFile(), filename
isImage = (data) ->
i = 0
while i < data.clipboardData.items.length
item = data.clipboardData.items[i]
if item.type.indexOf("image") isnt -1
return item
i++
return false
pasteText = (text) ->
caretStart = $(child)[0].selectionStart
caretEnd = $(child)[0].selectionEnd
textEnd = $(child).val().length
beforeSelection = $(child).val().substring 0, caretStart
afterSelection = $(child).val().substring caretEnd, textEnd
$(child).val beforeSelection + text + afterSelection
form_textarea.trigger "input"
getFilename = (e) ->
if window.clipboardData and window.clipboardData.getData
value = window.clipboardData.getData("Text")
else if e.clipboardData and e.clipboardData.getData
value = e.clipboardData.getData("text/plain")
value = value.split("\r")
value.first()
uploadFile = (item, filename) ->
formData = new FormData()
formData.append "file", item, filename
$.ajax
url: project_uploads_path
type: "POST"
data: formData
dataType: "json"
processData: false
contentType: false
headers:
"X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
beforeSend: ->
showSpinner()
closeAlertMessage()
success: (e, textStatus, response) ->
insertToTextArea(filename, formatLink(response.responseJSON.link))
error: (response) ->
showError(response.responseJSON.message)
complete: ->
closeSpinner()
insertToTextArea = (filename, url) ->
$(child).val (index, val) ->
val.replace("{{" + filename + "}}", url + "\n")
appendToTextArea = (url) ->
$(child).val (index, val) ->
val + url + "\n"
showSpinner = (e) ->
form.find(".div-dropzone-spinner").css
"opacity": 0.7
"display": "inherit"
closeSpinner = ->
form.find(".div-dropzone-spinner").css
"opacity": 0
"display": "none"
showError = (message) ->
checkIfMsgExists = $(".error-alert").children().length
if checkIfMsgExists is 0
$(".error-alert").append divAlert
$(".div-dropzone-alert").append btnAlert + message
closeAlertMessage = ->
form.find(".div-dropzone-alert").alert "close"
form.find(".markdown-selector").click (e) ->
e.preventDefault()
$(@).closest('.gfm-form').find('.div-dropzone').click()
return
formatLink: (link) ->
text = "[#{link.alt}](#{link.url})"
text = "!#{text}" if link.is_image
text
\ No newline at end of file
class Flash class @Flash
constructor: (message, type)-> constructor: (message, type)->
flash = $(".flash-container") flash = $(".flash-container")
flash.html("") flash.html("")
...@@ -10,5 +10,3 @@ class Flash ...@@ -10,5 +10,3 @@ class Flash
flash.click -> $(@).fadeOut() flash.click -> $(@).fadeOut()
flash.show() flash.show()
@Flash = Flash
class @GroupAvatar
constructor: ->
$('.js-choose-group-avatar-button').bind "click", ->
form = $(this).closest("form")
form.find(".js-group-avatar-input").click()
$('.js-group-avatar-input').bind "change", ->
form = $(this).closest("form")
filename = $(this).val().replace(/^.*[\\\/]/, '')
form.find(".js-avatar-filename").text(filename)
class GroupMembers class @GroupMembers
constructor: -> constructor: ->
$('li.group_member').bind 'ajax:success', -> $('li.group_member').bind 'ajax:success', ->
$(this).fadeOut() $(this).fadeOut()
@GroupMembers = GroupMembers
$ ->
# avatar
$('.js-choose-group-avatar-button').bind "click", ->
form = $(this).closest("form")
form.find(".js-group-avatar-input").click()
$('.js-group-avatar-input').bind "change", ->
form = $(this).closest("form")
filename = $(this).val().replace(/^.*[\\\/]/, '')
form.find(".js-avatar-filename").text(filename)
class @GroupsSelect
constructor: ->
$('.ajax-groups-select').each (i, select) =>
skip_ldap = $(select).hasClass('skip_ldap')
$(select).select2
placeholder: "Search for a group"
multiple: $(select).hasClass('multiselect')
minimumInputLength: 0
query: (query) ->
Api.groups query.term, skip_ldap, (groups) ->
data = { results: groups }
query.callback(data)
initSelection: (element, callback) ->
id = $(element).val()
if id isnt ""
Api.group(id, callback)
formatResult: (args...) =>
@formatResult(args...)
formatSelection: (args...) =>
@formatSelection(args...)
dropdownCssClass: "ajax-groups-dropdown"
escapeMarkup: (m) -> # we do not want to escape markup since we are displaying html in results
m
formatResult: (group) ->
if group.avatar_url
avatar = group.avatar_url
else
avatar = gon.default_avatar_url
"<div class='group-result'>
<div class='group-name'>#{group.name}</div>
<div class='group-path'>#{group.path}</div>
</div>"
formatSelection: (group) ->
group.name
class @ImporterStatus
constructor: (@jobs_url, @import_url) ->
this.initStatusPage()
this.setAutoUpdate()
initStatusPage: ->
$(".js-add-to-import").click (event) =>
new_namespace = null
tr = $(event.currentTarget).closest("tr")
id = tr.attr("id").replace("repo_", "")
if tr.find(".import-target input").length > 0
new_namespace = tr.find(".import-target input").prop("value")
tr.find(".import-target").empty().append(new_namespace + "/" + tr.find(".import-target").data("project_name"))
$.post @import_url, {repo_id: id, new_namespace: new_namespace}, dataType: 'script'
$(".js-import-all").click (event) =>
$(".js-add-to-import").each ->
$(this).click()
setAutoUpdate: ->
setInterval (=>
$.get @jobs_url, (data) =>
$.each data, (i, job) =>
job_item = $("#project_" + job.id)
status_field = job_item.find(".job-status")
if job.import_status == 'finished'
job_item.removeClass("active").addClass("success")
status_field.html('<span><i class="fa fa-check"></i> done</span>')
else if job.import_status == 'started'
status_field.html("<i class='fa fa-spinner fa-spin'></i> started")
else
status_field.html(job.import_status)
), 4000
class @IssuableForm
constructor: (@form) ->
@titleField = @form.find("input[name*='[title]']")
@descriptionField = @form.find("textarea[name*='[description]']")
return unless @titleField.length && @descriptionField.length
@initAutosave()
@form.on "submit", @resetAutosave
@form.on "click", ".btn-cancel", @resetAutosave
initAutosave: ->
new Autosave @titleField, [
document.location.pathname,
document.location.search,
"title"
]
new Autosave @descriptionField, [
document.location.pathname,
document.location.search,
"description"
]
resetAutosave: =>
@titleField.data("autosave").reset()
@descriptionField.data("autosave").reset()
class Issue class @Issue
constructor: -> constructor: ->
$('.edit-issue.inline-update input[type="submit"]').hide() $('.edit-issue.inline-update input[type="submit"]').hide()
$(".issue-box .inline-update").on "change", "select", -> $(".context .inline-update").on "change", "select", ->
$(this).submit() $(this).submit()
$(".issue-box .inline-update").on "change", "#issue_assignee_id", -> $(".context .inline-update").on "change", "#issue_assignee_id", ->
$(this).submit() $(this).submit()
if $("a.btn-close").length if $("a.btn-close").length
...@@ -16,4 +16,9 @@ class Issue ...@@ -16,4 +16,9 @@ class Issue
updateTaskState updateTaskState
) )
@Issue = Issue $('.issue-details').waitForImages ->
$('.issuable-affix').affix offset:
top: ->
@top = $('.issue-details').outerHeight(true) + 25
bottom: ->
@bottom = $('.footer').outerHeight(true)
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
$(this).html totalIssues + 1 $(this).html totalIssues + 1
else else
$(this).html totalIssues - 1 $(this).html totalIssues - 1
$("body").on "click", ".issues-filters .dropdown-menu a", -> $("body").on "click", ".issues-other-filters .dropdown-menu a", ->
$('.issues-list').block( $('.issues-list').block(
message: null, message: null,
overlayCSS: overlayCSS:
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
initSearch: -> initSearch: ->
@timer = null @timer = null
$("#issue_search").keyup -> $("#issue_search").keyup ->
clearTimeout(@timer); clearTimeout(@timer)
@timer = setTimeout(Issues.filterResults, 500) @timer = setTimeout(Issues.filterResults, 500)
filterResults: => filterResults: =>
...@@ -77,9 +77,9 @@ ...@@ -77,9 +77,9 @@
ids.push $(value).attr("data-id") ids.push $(value).attr("data-id")
$("#update_issues_ids").val ids $("#update_issues_ids").val ids
$(".issues-filters").hide() $(".issues-other-filters").hide()
$(".issues_bulk_update").show() $(".issues_bulk_update").show()
else else
$("#update_issues_ids").val [] $("#update_issues_ids").val []
$(".issues_bulk_update").hide() $(".issues_bulk_update").hide()
$(".issues-filters").show() $(".issues-other-filters").show()
class Labels class @Labels
constructor: -> constructor: ->
form = $('.label-form') form = $('.label-form')
@setupLabelForm(form) @setupLabelForm(form)
...@@ -31,5 +31,3 @@ class Labels ...@@ -31,5 +31,3 @@ class Labels
# Notify the form, that color has changed # Notify the form, that color has changed
$('.label-form').trigger('keyup') $('.label-form').trigger('keyup')
e.preventDefault() e.preventDefault()
@Labels = Labels
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=\"fa fa-picture-o div-dropzone-icon\"></i>"
iconSpinner = "<i class=\"fa fa-spinner fa-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
$(".div-dropzone-spinner").css
"opacity": 0
"display": "none"
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
"display": "inherit"
return
complete: ->
$(".dz-preview").remove()
$(".markdown-area").trigger "input"
$(".div-dropzone-spinner").css
"opacity": 0
"display": "none"
return
)
child = $(dropzone[0]).children("textarea")
formatLink = (str) ->
"![" + str.alt + "](" + str.url + ")"
handlePaste = (e) ->
e.preventDefault()
my_event = e.originalEvent
if my_event.clipboardData and my_event.clipboardData.items
processItem(my_event)
processItem = (e) ->
image = isImage(e)
if image
filename = getFilename(e) or "image.png"
text = "{{" + filename + "}}"
pasteText(text)
uploadFile image.getAsFile(), filename
else
text = e.clipboardData.getData("text/plain")
pasteText(text)
isImage = (data) ->
i = 0
while i < data.clipboardData.items.length
item = data.clipboardData.items[i]
if item.type.indexOf("image") isnt -1
return item
i++
return false
pasteText = (text) ->
caretStart = $(child)[0].selectionStart
caretEnd = $(child)[0].selectionEnd
textEnd = $(child).val().length
beforeSelection = $(child).val().substring 0, caretStart
afterSelection = $(child).val().substring caretEnd, textEnd
$(child).val beforeSelection + text + afterSelection
$(".markdown-area").trigger "input"
getFilename = (e) ->
if window.clipboardData and window.clipboardData.getData
value = window.clipboardData.getData("Text")
else if e.clipboardData and e.clipboardData.getData
value = e.clipboardData.getData("text/plain")
value = value.split("\r")
value.first()
uploadFile = (item, filename) ->
formData = new FormData()
formData.append "markdown_img", item, filename
$.ajax
url: project_image_path_upload
type: "POST"
data: formData
dataType: "json"
processData: false
contentType: false
headers:
"X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
beforeSend: ->
showSpinner()
closeAlertMessage()
success: (e, textStatus, response) ->
insertToTextArea(filename, formatLink(response.responseJSON.link))
error: (response) ->
showError(response.responseJSON.message)
complete: ->
closeSpinner()
insertToTextArea = (filename, url) ->
$(child).val (index, val) ->
val.replace("{{" + filename + "}}", url + "\n")
appendToTextArea = (url) ->
$(child).val (index, val) ->
val + url + "\n"
showSpinner = (e) ->
$(".div-dropzone-spinner").css
"opacity": 0.7
"display": "inherit"
closeSpinner = ->
$(".div-dropzone-spinner").css
"opacity": 0
"display": "none"
showError = (message) ->
checkIfMsgExists = $(".error-alert").children().length
if checkIfMsgExists is 0
$(".error-alert").append divAlert
$(".div-dropzone-alert").append btnAlert + message
closeAlertMessage = ->
$(".div-dropzone-alert").alert "close"
$(".markdown-selector").click (e) ->
e.preventDefault()
$(@).closest('.gfm-form').find('.div-dropzone').click()
return
return
class MergeRequest class @MergeRequest
constructor: (@opts) -> constructor: (@opts) ->
@initContextWidget() @initContextWidget()
this.$el = $('.merge-request') this.$el = $('.merge-request')
...@@ -20,15 +20,22 @@ class MergeRequest ...@@ -20,15 +20,22 @@ class MergeRequest
if $("a.btn-close").length if $("a.btn-close").length
$("li.task-list-item input:checkbox").prop("disabled", false) $("li.task-list-item input:checkbox").prop("disabled", false)
$('.merge-request-details').waitForImages ->
$('.issuable-affix').affix offset:
top: ->
@top = $('.merge-request-details').outerHeight(true) + 91
bottom: ->
@bottom = $('.footer').outerHeight(true)
# Local jQuery finder # Local jQuery finder
$: (selector) -> $: (selector) ->
this.$el.find(selector) this.$el.find(selector)
initContextWidget: -> initContextWidget: ->
$('.edit-merge_request.inline-update input[type="submit"]').hide() $('.edit-merge_request.inline-update input[type="submit"]').hide()
$(".issue-box .inline-update").on "change", "select", -> $(".context .inline-update").on "change", "select", ->
$(this).submit() $(this).submit()
$(".issue-box .inline-update").on "change", "#merge_request_assignee_id", -> $(".context .inline-update").on "change", "#merge_request_assignee_id", ->
$(this).submit() $(this).submit()
initMergeWidget: -> initMergeWidget: ->
...@@ -89,6 +96,10 @@ class MergeRequest ...@@ -89,6 +96,10 @@ class MergeRequest
this.$('.merge-request-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()
$(".diff-header").trigger("sticky_kit:recalc")
when 'commits'
this.$('.merge-request-tabs .commits-tab').addClass 'active'
this.$('.commits').show()
else else
this.$('.merge-request-tabs .notes-tab').addClass 'active' this.$('.merge-request-tabs .notes-tab').addClass 'active'
this.$('.notes').show() this.$('.notes').show()
...@@ -114,7 +125,7 @@ class MergeRequest ...@@ -114,7 +125,7 @@ class MergeRequest
loadDiff: (event) -> loadDiff: (event) ->
$.ajax $.ajax
type: 'GET' type: 'GET'
url: this.$('.merge-request-tabs .diffs-tab a').attr('href') url: this.$('.merge-request-tabs .diffs-tab a').attr('href') + ".json"
beforeSend: => beforeSend: =>
this.$('.mr-loading-status .loading').show() this.$('.mr-loading-status .loading').show()
complete: => complete: =>
...@@ -133,4 +144,15 @@ class MergeRequest ...@@ -133,4 +144,15 @@ class MergeRequest
this.$('.merge-in-progress').hide() this.$('.merge-in-progress').hide()
this.$('.automerge_widget.already_cannot_be_merged').show() this.$('.automerge_widget.already_cannot_be_merged').show()
this.MergeRequest = MergeRequest mergeInProgress: ->
$.ajax
type: 'GET'
url: $('.merge-request').data('url')
success: (data) =>
switch data.state
when 'merged'
location.reload()
else
setTimeout(merge_request.mergeInProgress, 3000)
dataType: 'json'
# #
# * Filter merge requests # * Filter merge requests
# #
@merge_requestsPage = -> @MergeRequests =
$('#assignee_id').select2() init: ->
$('#milestone_id').select2() MergeRequests.initSearch()
$('#milestone_id, #assignee_id').on 'change', ->
$(this).closest('form').submit() # Make sure we trigger ajax request only after user stop typing
initSearch: ->
@timer = null
$("#issue_search").keyup ->
clearTimeout(@timer)
@timer = setTimeout(MergeRequests.filterResults, 500)
filterResults: =>
form = $("#issue_search_form")
search = $("#issue_search").val()
$('.merge-requests-holder').css("opacity", '0.5')
issues_url = form.attr('action') + '? '+ form.serialize()
$.ajax
type: "GET"
url: form.attr('action')
data: form.serialize()
complete: ->
$('.merge-requests-holder').css("opacity", '1.0')
success: (data) ->
$('.merge-requests-holder').html(data.html)
# Change url so if user reload a page - search results are saved
History.replaceState {page: issues_url}, document.title, issues_url
MergeRequests.reload()
dataType: "json"
reload: ->
$('#filter_issue_search').val($('#issue_search').val())
class Milestone class @Milestone
@updateIssue: (li, issue_url, data) -> @updateIssue: (li, issue_url, data) ->
$.ajax $.ajax
type: "PUT" type: "PUT"
...@@ -49,6 +49,13 @@ class Milestone ...@@ -49,6 +49,13 @@ class Milestone
data: data data: data
success: (data) -> success: (data) ->
if data.saved == true 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' $(li).effect 'highlight'
else else
new Flash("Issue update failed", 'alert') new Flash("Issue update failed", 'alert')
...@@ -115,5 +122,3 @@ class Milestone ...@@ -115,5 +122,3 @@ class Milestone
Milestone.updateMergeRequest(ui.item, merge_request_url, data) Milestone.updateMergeRequest(ui.item, merge_request_url, data)
).disableSelection() ).disableSelection()
@Milestone = Milestone
$ -> class @NamespaceSelect
namespaceFormatResult = (namespace) -> constructor: ->
markup = "<div class='namespace-result'>" namespaceFormatResult = (namespace) ->
markup += "<span class='namespace-kind'>" + namespace.kind + "</span>" markup = "<div class='namespace-result'>"
markup += "<span class='namespace-path'>" + namespace.path + "</span>" markup += "<span class='namespace-kind'>" + namespace.kind + "</span>"
markup += "</div>" markup += "<span class='namespace-path'>" + namespace.path + "</span>"
markup markup += "</div>"
markup
formatSelection = (namespace) -> formatSelection = (namespace) ->
namespace.kind + ": " + namespace.path namespace.kind + ": " + namespace.path
$('.ajax-namespace-select').each (i, select) -> $('.ajax-namespace-select').each (i, select) ->
$(select).select2 $(select).select2
placeholder: "Search for namespace" placeholder: "Search for namespace"
multiple: $(select).hasClass('multiselect') multiple: $(select).hasClass('multiselect')
minimumInputLength: 0 minimumInputLength: 0
query: (query) -> query: (query) ->
Api.namespaces query.term, (namespaces) -> Api.namespaces query.term, (namespaces) ->
data = { results: namespaces } data = { results: namespaces }
query.callback(data) query.callback(data)
dropdownCssClass: "ajax-namespace-dropdown" dropdownCssClass: "ajax-namespace-dropdown"
formatResult: namespaceFormatResult formatResult: namespaceFormatResult
formatSelection: formatSelection formatSelection: formatSelection
class Notes class @Notes
@interval: null @interval: null
constructor: (notes_url, note_ids, last_fetched_at) -> constructor: (notes_url, note_ids, last_fetched_at) ->
...@@ -36,18 +36,9 @@ class Notes ...@@ -36,18 +36,9 @@ class Notes
# delete note attachment # delete note attachment
$(document).on "click", ".js-note-attachment-delete", @removeAttachment $(document).on "click", ".js-note-attachment-delete", @removeAttachment
# Preview button
$(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
# attachment button
$(document).on "click", ".js-choose-note-attachment-button", @chooseNoteAttachment
# update the file name when an attachment is selected # update the file name when an attachment is selected
$(document).on "change", ".js-note-attachment-input", @updateFormAttachment $(document).on "change", ".js-note-attachment-input", @updateFormAttachment
...@@ -64,8 +55,9 @@ class Notes ...@@ -64,8 +55,9 @@ class Notes
$(document).on "visibilitychange", @visibilityChange $(document).on "visibilitychange", @visibilityChange
@notes_forms = '.js-main-target-form textarea, .js-discussion-note-form textarea' @notes_forms = '.js-main-target-form textarea, .js-discussion-note-form textarea'
$(document).on('keypress', @notes_forms, (e)-> # Chrome doesn't fire keypress or keyup for Command+Enter, so we need keydown.
if e.keyCode == 10 || (e.ctrlKey && e.keyCode == 13) $(document).on('keydown', @notes_forms, (e) ->
if e.keyCode == 10 || ((e.metaKey || e.ctrlKey) && e.keyCode == 13)
$(@).parents('form').submit() $(@).parents('form').submit()
) )
...@@ -77,14 +69,11 @@ class Notes ...@@ -77,14 +69,11 @@ class Notes
$(document).off "click", ".note-edit-cancel" $(document).off "click", ".note-edit-cancel"
$(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-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-discussion-reply-button" $(document).off "click", ".js-discussion-reply-button"
$(document).off "click", ".js-add-diff-note-button" $(document).off "click", ".js-add-diff-note-button"
$(document).off "visibilitychange" $(document).off "visibilitychange"
$(document).off "keypress", @notes_forms $(document).off "keydown", @notes_forms
$(document).off "keyup", ".js-note-text" $(document).off "keyup", ".js-note-text"
$(document).off "click", ".js-note-target-reopen" $(document).off "click", ".js-note-target-reopen"
$(document).off "click", ".js-note-target-close" $(document).off "click", ".js-note-target-close"
...@@ -122,10 +111,6 @@ class Notes ...@@ -122,10 +111,6 @@ class Notes
if @isNewNote(note) if @isNewNote(note)
@note_ids.push(note.id) @note_ids.push(note.id)
$('ul.main-notes-list').append(note.html) $('ul.main-notes-list').append(note.html)
code = "#note_" + note.id + " .highlight pre code"
$(code).each (i, e) ->
hljs.highlightBlock(e)
### ###
Check if note does not exists on page Check if note does not exists on page
...@@ -165,47 +150,6 @@ class Notes ...@@ -165,47 +150,6 @@ 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.
Lets the server render GFM into Html and displays it.
###
previewNote: (e) ->
e.preventDefault()
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")
noteText = form.find(".js-note-text").val()
if noteText.trim().length is 0
preview.text "Nothing to preview."
else
preview.text "Loading..."
$.post($(this).data("url"),
note: noteText
).success (previewData) ->
preview.html previewData
### ###
Called in response the main target form has been successfully submitted. Called in response the main target form has been successfully submitted.
...@@ -220,17 +164,10 @@ class Notes ...@@ -220,17 +164,10 @@ class Notes
form.find(".js-errors").remove() form.find(".js-errors").remove()
# reset text and preview # reset text and preview
form.find(".js-note-write-button").click() form.find(".js-md-write-button").click()
form.find(".js-note-text").val("").trigger "input" form.find(".js-note-text").val("").trigger "input"
### form.find(".js-note-text").data("autosave").reset()
Called when clicking the "Choose File" button.
Opens the file selection dialog.
###
chooseNoteAttachment: ->
form = $(this).closest("form")
form.find(".js-note-attachment-input").click()
### ###
Shows the main form and does some setup on it. Shows the main form and does some setup on it.
...@@ -268,23 +205,34 @@ class Notes ...@@ -268,23 +205,34 @@ class Notes
setupNoteForm: (form) -> setupNoteForm: (form) ->
disableButtonIfEmptyField form.find(".js-note-text"), form.find(".js-comment-button") disableButtonIfEmptyField form.find(".js-note-text"), form.find(".js-comment-button")
form.removeClass "js-new-note-form" form.removeClass "js-new-note-form"
form.find('.div-dropzone').remove()
# setup preview buttons # setup preview buttons
form.find(".js-note-write-button, .js-note-preview-button").tooltip placement: "left" form.find(".js-md-write-button, .js-md-preview-button").tooltip placement: "left"
previewButton = form.find(".js-note-preview-button") previewButton = form.find(".js-md-preview-button")
form.find(".js-note-text").on "input", ->
textarea = form.find(".js-note-text")
textarea.on "input", ->
if $(this).val().trim() isnt "" if $(this).val().trim() isnt ""
previewButton.removeClass("turn-off").addClass "turn-on" previewButton.removeClass("turn-off").addClass "turn-on"
else else
previewButton.removeClass("turn-on").addClass "turn-off" previewButton.removeClass("turn-on").addClass "turn-off"
new Autosave textarea, [
"Note"
form.find("#note_commit_id").val()
form.find("#note_line_code").val()
form.find("#note_noteable_type").val()
form.find("#note_noteable_id").val()
]
# remove notify commit author checkbox for non-commit notes # remove notify commit author checkbox for non-commit notes
form.find(".js-notify-commit-author").remove() if form.find("#note_noteable_type").val() isnt "Commit" form.find(".js-notify-commit-author").remove() if form.find("#note_noteable_type").val() isnt "Commit"
GitLab.GfmAutoComplete.setup() GitLab.GfmAutoComplete.setup()
new DropzoneInput(form)
form.show() form.show()
### ###
Called in response to the new note form being submitted Called in response to the new note form being submitted
...@@ -308,11 +256,10 @@ class Notes ...@@ -308,11 +256,10 @@ class Notes
Updates the current note field. Updates the current note field.
### ###
updateNote: (xhr, note, status) => updateNote: (xhr, note, status) =>
note_li = $("#note_" + note.id) note_li = $(".note-row-" + note.id)
note_li.replaceWith(note.html) note_li.replaceWith(note.html)
code = "#note_" + note.id + " .highlight pre code" note_li.find('.note-edit-form').hide()
$(code).each (i, e) -> note_li.find('.note-body > .note-text').show()
hljs.highlightBlock(e)
### ###
Called in response to clicking the edit note link Called in response to clicking the edit note link
...@@ -324,12 +271,20 @@ class Notes ...@@ -324,12 +271,20 @@ class Notes
showEditForm: (e) -> showEditForm: (e) ->
e.preventDefault() e.preventDefault()
note = $(this).closest(".note") note = $(this).closest(".note")
note.find(".note-text").hide() note.find(".note-body > .note-text").hide()
note.find(".note-header").hide()
base_form = note.find(".note-edit-form")
form = base_form.clone().insertAfter(base_form)
form.addClass('current-note-edit-form')
form.find('.div-dropzone').remove()
# Show the attachment delete link # Show the attachment delete link
note.find(".js-note-attachment-delete").show() note.find(".js-note-attachment-delete").show()
# Setup markdown form
GitLab.GfmAutoComplete.setup() GitLab.GfmAutoComplete.setup()
form = note.find(".note-edit-form") new DropzoneInput(form)
form.show() form.show()
textarea = form.find("textarea") textarea = form.find("textarea")
textarea.focus() textarea.focus()
...@@ -343,9 +298,9 @@ class Notes ...@@ -343,9 +298,9 @@ class Notes
cancelEdit: (e) -> cancelEdit: (e) ->
e.preventDefault() e.preventDefault()
note = $(this).closest(".note") note = $(this).closest(".note")
note.find(".note-text").show() note.find(".note-body > .note-text").show()
note.find(".js-note-attachment-delete").hide() note.find(".note-header").show()
note.find(".note-edit-form").hide() note.find(".current-note-edit-form").remove()
### ###
Called in response to deleting a note of any kind. Called in response to deleting a note of any kind.
...@@ -377,7 +332,7 @@ class Notes ...@@ -377,7 +332,7 @@ class Notes
removeAttachment: -> removeAttachment: ->
note = $(this).closest(".note") note = $(this).closest(".note")
note.find(".note-attachment").remove() note.find(".note-attachment").remove()
note.find(".note-text").show() note.find(".note-body > .note-text").show()
note.find(".js-note-attachment-delete").hide() note.find(".js-note-attachment-delete").hide()
note.find(".note-edit-form").hide() note.find(".note-edit-form").hide()
...@@ -424,7 +379,7 @@ class Notes ...@@ -424,7 +379,7 @@ class Notes
### ###
addDiffNote: (e) => addDiffNote: (e) =>
e.preventDefault() e.preventDefault()
link = e.target link = e.currentTarget
form = $(".js-new-note-form") form = $(".js-new-note-form")
row = $(link).closest("tr") row = $(link).closest("tr")
nextRow = row.next() nextRow = row.next()
...@@ -451,6 +406,8 @@ class Notes ...@@ -451,6 +406,8 @@ class Notes
removeDiscussionNoteForm: (form)-> removeDiscussionNoteForm: (form)->
row = form.closest("tr") row = form.closest("tr")
form.find(".js-note-text").data("autosave").reset()
# show the reply button (will only work for replies) # show the reply button (will only work for replies)
form.prev(".js-discussion-reply-button").show() form.prev(".js-discussion-reply-button").show()
if row.is(".js-temp-notes-holder") if row.is(".js-temp-notes-holder")
...@@ -514,7 +471,3 @@ class Notes ...@@ -514,7 +471,3 @@ class Notes
else else
form.find('.js-note-target-reopen').text('Reopen') form.find('.js-note-target-reopen').text('Reopen')
form.find('.js-note-target-close').text('Close') form.find('.js-note-target-close').text('Close')
@Notes = Notes
class NotesVotes class @NotesVotes
updateVotes: -> updateVotes: ->
votes = $("#votes .votes") votes = $("#votes .votes")
notes = $("#notes-list .note .vote") notes = $("#notes-list .note .vote")
...@@ -18,5 +18,3 @@ class NotesVotes ...@@ -18,5 +18,3 @@ class NotesVotes
# replace vote numbers # replace vote numbers
votes.find(".upvotes").text votes.find(".upvotes").text().replace(/\d+/, upvotes) votes.find(".upvotes").text votes.find(".upvotes").text().replace(/\d+/, upvotes)
votes.find(".downvotes").text votes.find(".downvotes").text().replace(/\d+/, downvotes) votes.find(".downvotes").text votes.find(".downvotes").text().replace(/\d+/, downvotes)
@NotesVotes = NotesVotes
$ -> class @Profile
$('.edit_user .application-theme input, .edit_user .code-preview-theme input').click -> constructor: ->
# Submit the form $('.edit_user .application-theme input, .edit_user .code-preview-theme input').click ->
$('.edit_user').submit() # Submit the form
$('.edit_user').submit()
new Flash("Appearance settings saved", "notice") new Flash("Appearance settings saved", "notice")
$('.update-username form').on 'ajax:before', -> $('.update-username form').on 'ajax:before', ->
$('.loading-gif').show() $('.loading-gif').show()
$(this).find('.update-success').hide() $(this).find('.update-success').hide()
$(this).find('.update-failed').hide() $(this).find('.update-failed').hide()
$('.update-username form').on 'ajax:complete', -> $('.update-username form').on 'ajax:complete', ->
$(this).find('.btn-save').enableButton() $(this).find('.btn-save').enableButton()
$(this).find('.loading-gif').hide() $(this).find('.loading-gif').hide()
$('.update-notifications').on 'ajax:complete', -> $('.update-notifications').on 'ajax:complete', ->
$(this).find('.btn-save').enableButton() $(this).find('.btn-save').enableButton()
$('.js-choose-user-avatar-button').bind "click", -> $('.js-choose-user-avatar-button').bind "click", ->
form = $(this).closest("form") form = $(this).closest("form")
form.find(".js-user-avatar-input").click() form.find(".js-user-avatar-input").click()
$('.js-user-avatar-input').bind "change", -> $('.js-user-avatar-input').bind "change", ->
form = $(this).closest("form") form = $(this).closest("form")
filename = $(this).val().replace(/^.*[\\\/]/, '') filename = $(this).val().replace(/^.*[\\\/]/, '')
form.find(".js-avatar-filename").text(filename) form.find(".js-avatar-filename").text(filename)
$('.profile-groups-avatars').tooltip("placement": "top")
class Project class @Project
constructor: -> constructor: ->
$('.project-edit-container').on 'ajax:before', => # Git clone panel switcher
$('.project-edit-container').hide() scope = $ '.git-clone-holder'
$('.save-project-loader').show() if scope.length > 0
$('a, button', scope).click ->
@initEvents() $('a, button', scope).removeClass 'active'
$(@).addClass 'active'
$('#project_clone', scope).val $(@).data 'clone'
initEvents: -> $(".clone").text("").append $(@).data 'clone'
disableButtonIfEmptyField '#project_name', '.project-submit'
# Ref switcher
$('#project_issues_enabled').change -> $('.project-refs-select').on 'change', ->
if ($(this).is(':checked') == true) $(@).parents('form').submit()
$('#project_issues_tracker').removeAttr('disabled')
else $('.hide-no-ssh-message').on 'click', (e) ->
$('#project_issues_tracker').attr('disabled', 'disabled') path = '/'
$.cookie('hide_no_ssh_message', 'false', { path: path })
$('#project_issues_tracker').change() $(@).parents('.no-ssh-key-message').remove()
e.preventDefault()
$('#project_issues_tracker').change ->
if ($(this).val() == gon.default_issues_tracker || $(this).is(':disabled')) $('.hide-no-password-message').on 'click', (e) ->
$('#project_issues_tracker_id').attr('disabled', 'disabled') path = '/'
else $.cookie('hide_no_password_message', 'false', { path: path })
$('#project_issues_tracker_id').removeAttr('disabled') $(@).parents('.no-password-message').remove()
e.preventDefault()
@Project = Project
$ ->
# Git clone panel switcher
scope = $ '.git-clone-holder'
if scope.length > 0
$('a, button', scope).click ->
$('a, button', scope).removeClass 'active'
$(@).addClass 'active'
$('#project_clone', scope).val $(@).data 'clone'
$(".clone").text("").append $(@).data 'clone'
# Ref switcher
$('.project-refs-select').on 'change', ->
$(@).parents('form').submit()
$('.hide-no-ssh-message').on 'click', (e) ->
path = '/'
$.cookie('hide_no_ssh_message', 'false', { path: path })
$(@).parents('.no-ssh-key-message').hide()
e.preventDefault()
$('.project-home-panel .star').on 'ajax:success', (e, data, status, xhr) ->
$(@).toggleClass('on').find('.count').html(data.star_count)
.on 'ajax:error', (e, xhr, status, error) ->
new Flash('Star toggle failed. Try again later.', 'alert')
$("a[data-toggle='tab']").on "shown.bs.tab", (e) ->
$.cookie "default_view", $(e.target).attr("href")
defaultView = $.cookie("default_view")
if defaultView
$("a[href=" + defaultView + "]").tab "show"
else
$("a[data-toggle='tab']:first").tab "show"
class @ProjectAvatar
constructor: ->
$('.js-choose-project-avatar-button').bind 'click', ->
form = $(this).closest('form')
form.find('.js-project-avatar-input').click()
$('.js-project-avatar-input').bind 'change', ->
form = $(this).closest('form')
filename = $(this).val().replace(/^.*[\\\/]/, '')
form.find('.js-avatar-filename').text(filename)
class @ProjectFork
constructor: ->
$('.fork-thumbnail a').on 'click', ->
$('.fork-namespaces').hide()
$('.save-project-loader').show()
class ProjectImport class @ProjectImport
constructor: -> constructor: ->
setTimeout -> setTimeout ->
Turbolinks.visit(location.href) Turbolinks.visit(location.href)
, 5000 , 5000
@ProjectImport = ProjectImport
class @ProjectMembers
constructor: ->
$('li.project_member').bind 'ajax:success', ->
$(this).fadeOut()
class @ProjectNew
constructor: ->
$('.project-edit-container').on 'ajax:before', =>
$('.project-edit-container').hide()
$('.save-project-loader').show()
@initEvents()
initEvents: ->
disableButtonIfEmptyField '#project_name', '.project-submit'
class @ProjectShow
constructor: ->
$('.project-home-panel .star').on 'ajax:success', (e, data, status, xhr) ->
$(@).toggleClass('on').find('.count').html(data.star_count)
.on 'ajax:error', (e, xhr, status, error) ->
new Flash('Star toggle failed. Try again later.', 'alert')
$("a[data-toggle='tab']").on "shown.bs.tab", (e) ->
$.cookie "default_view", $(e.target).attr("href"), { expires: 30, path: '/' }
defaultView = $.cookie("default_view")
if defaultView
$("a[href=" + defaultView + "]").tab "show"
else
$("a[data-toggle='tab']:first").tab "show"
@projectUsersSelect = class @ProjectUsersSelect
init: -> constructor: ->
$('.ajax-project-users-select').each (i, select) -> $('.ajax-project-users-select').each (i, select) =>
project_id = $(select).data('project-id') || $('body').data('project-id') project_id = $(select).data('project-id') || $('body').data('project-id')
$(select).select2 $(select).select2
...@@ -11,14 +11,15 @@ ...@@ -11,14 +11,15 @@
Api.projectUsers project_id, query.term, (users) -> Api.projectUsers project_id, query.term, (users) ->
data = { results: users } data = { results: users }
nullUser = { if query.term.length == 0
name: 'Unassigned', nullUser = {
avatar: null, name: 'Unassigned',
username: 'none', avatar: null,
id: '' username: 'none',
} id: -1
}
data.results.unshift(nullUser) data.results.unshift(nullUser)
query.callback(data) query.callback(data)
...@@ -28,14 +29,16 @@ ...@@ -28,14 +29,16 @@
Api.user(id, callback) Api.user(id, callback)
formatResult: projectUsersSelect.projectUserFormatResult formatResult: (args...) =>
formatSelection: projectUsersSelect.projectUserFormatSelection @formatResult(args...)
formatSelection: (args...) =>
@formatSelection(args...)
dropdownCssClass: "ajax-project-users-dropdown" dropdownCssClass: "ajax-project-users-dropdown"
dropdownAutoWidth: true dropdownAutoWidth: true
escapeMarkup: (m) -> # we do not want to escape markup since we are displaying html in results escapeMarkup: (m) -> # we do not want to escape markup since we are displaying html in results
m m
projectUserFormatResult: (user) -> formatResult: (user) ->
if user.avatar_url if user.avatar_url
avatar = user.avatar_url avatar = user.avatar_url
else else
...@@ -52,8 +55,5 @@ ...@@ -52,8 +55,5 @@
<div class='user-username'>#{user.username}</div> <div class='user-username'>#{user.username}</div>
</div>" </div>"
projectUserFormatSelection: (user) -> formatSelection: (user) ->
user.name user.name
$ ->
projectUsersSelect.init()
class @ProjectsList
constructor: ->
$(".projects-list .js-expand").on 'click', (e) ->
e.preventDefault()
list = $(this).closest('.projects-list')
list.find("li").show()
list.find("li.bottom").hide()
$(".projects-list-filter").keyup ->
terms = $(this).val()
uiBox = $(this).closest('.panel')
if terms == "" || terms == undefined
uiBox.find(".projects-list li").show()
else
uiBox.find(".projects-list li").each (index) ->
name = $(this).find(".filter-title").text()
if name.toLowerCase().search(terms.toLowerCase()) == -1
$(this).hide()
else
$(this).show()
uiBox.find(".projects-list li.bottom").hide()
$ ->
$(":checkbox").change ->
name = $(this).attr("name")
if name == "developers_can_push"
id = $(this).val()
checked = $(this).is(":checked")
url = $(this).data("url")
$.ajax
type: "PUT"
url: url
dataType: "json"
data:
id: id
developers_can_push: checked
success: ->
new Flash("Branch updated.", "notice")
location.reload true
error: ->
new Flash("Failed to update branch!", "alert")
class SearchAutocomplete class @SearchAutocomplete
constructor: (search_autocomplete_path, project_id, project_ref) -> constructor: (search_autocomplete_path, project_id, project_ref) ->
project_id = '' unless project_id project_id = '' unless project_id
project_ref = '' unless project_ref project_ref = '' unless project_ref
...@@ -9,5 +9,3 @@ class SearchAutocomplete ...@@ -9,5 +9,3 @@ class SearchAutocomplete
minLength: 1 minLength: 1
select: (event, ui) -> select: (event, ui) ->
location.href = ui.item.url location.href = ui.item.url
@SearchAutocomplete = SearchAutocomplete
responsive_resize = -> $(document).on("click", '.toggle-nav-collapse', (e) ->
current_width = $(window).width() e.preventDefault()
if current_width < 985 collapsed = 'page-sidebar-collapsed'
$('.responsive-side').addClass("ui right wide sidebar") expanded = 'page-sidebar-expanded'
if $('.page-with-sidebar').hasClass(collapsed)
$('.page-with-sidebar').removeClass(collapsed).addClass(expanded)
$('.toggle-nav-collapse i').removeClass('fa-angle-right').addClass('fa-angle-left')
$.cookie("collapsed_nav", "false", { path: '/' })
else else
$('.responsive-side').removeClass("ui right wide sidebar") $('.page-with-sidebar').removeClass(expanded).addClass(collapsed)
$('.toggle-nav-collapse i').removeClass('fa-angle-left').addClass('fa-angle-right')
$ -> $.cookie("collapsed_nav", "true", { path: '/' })
# 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
class window.StatGraph class @StatGraph
@log: {} @log: {}
@get_log: -> @get_log: ->
@log @log
......
class window.ContributorsStatGraph class @ContributorsStatGraph
init: (log) -> init: (log) ->
@parsed_log = ContributorsStatGraphUtil.parse_log(log) @parsed_log = ContributorsStatGraphUtil.parse_log(log)
@set_current_field("commits") @set_current_field("commits")
......
class window.ContributorsGraph class @ContributorsGraph
MARGIN: MARGIN:
top: 20 top: 20
right: 20 right: 20
...@@ -44,9 +44,9 @@ class window.ContributorsGraph ...@@ -44,9 +44,9 @@ class window.ContributorsGraph
set_data: (data) -> set_data: (data) ->
@data = data @data = data
class window.ContributorsMasterGraph extends ContributorsGraph class @ContributorsMasterGraph extends ContributorsGraph
constructor: (@data) -> constructor: (@data) ->
@width = $('.container').width() - 70 @width = $('.container').width() - 345
@height = 200 @height = 200
@x = null @x = null
@y = null @y = null
...@@ -117,9 +117,9 @@ class window.ContributorsMasterGraph extends ContributorsGraph ...@@ -117,9 +117,9 @@ class window.ContributorsMasterGraph extends ContributorsGraph
@svg.select("path").attr("d", @area) @svg.select("path").attr("d", @area)
@svg.select(".y.axis").call(@y_axis) @svg.select(".y.axis").call(@y_axis)
class window.ContributorsAuthorGraph extends ContributorsGraph class @ContributorsAuthorGraph extends ContributorsGraph
constructor: (@data) -> constructor: (@data) ->
@width = $('.container').width()/2 - 100 @width = $('.container').width()/2 - 225
@height = 200 @height = 200
@x = null @x = null
@y = null @y = null
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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