Imported Upstream version 8.5.8+dfsg
This commit is contained in:
parent
f90c99e52e
commit
c15382a400
786 changed files with 45567 additions and 7670 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -23,6 +23,7 @@ config/gitlab.yml
|
||||||
config/gitlab_ci.yml
|
config/gitlab_ci.yml
|
||||||
config/initializers/rack_attack.rb
|
config/initializers/rack_attack.rb
|
||||||
config/initializers/smtp_settings.rb
|
config/initializers/smtp_settings.rb
|
||||||
|
config/initializers/relative_url.rb
|
||||||
config/resque.yml
|
config/resque.yml
|
||||||
config/unicorn.rb
|
config/unicorn.rb
|
||||||
config/secrets.yml
|
config/secrets.yml
|
||||||
|
|
154
.gitlab-ci.yml
154
.gitlab-ci.yml
|
@ -5,11 +5,16 @@ services:
|
||||||
- postgres:latest
|
- postgres:latest
|
||||||
- redis:latest
|
- redis:latest
|
||||||
|
|
||||||
|
cache:
|
||||||
|
key: "ruby21"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
|
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- ./scripts/prepare_build.sh
|
- source ./scripts/prepare_build.sh
|
||||||
- ruby -v
|
- ruby -v
|
||||||
- which ruby
|
- which ruby
|
||||||
- gem install bundler --no-ri --no-rdoc
|
- gem install bundler --no-ri --no-rdoc
|
||||||
|
@ -17,7 +22,7 @@ before_script:
|
||||||
- touch log/application.log
|
- touch log/application.log
|
||||||
- touch log/test.log
|
- touch log/test.log
|
||||||
- bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}"
|
- bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}"
|
||||||
- bundle exec rake db:reset db:create RAILS_ENV=test
|
- RAILS_ENV=test bundle exec rake db:drop db:create db:schema:load db:migrate
|
||||||
|
|
||||||
spec:feature:
|
spec:feature:
|
||||||
script:
|
script:
|
||||||
|
@ -134,3 +139,148 @@ bundler:audit:
|
||||||
- ruby
|
- ruby
|
||||||
- mysql
|
- mysql
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
|
|
||||||
|
# Ruby 2.2 jobs
|
||||||
|
|
||||||
|
spec:feature:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
||||||
|
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
spec:api:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:api
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
spec:models:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
spec:lib:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
spec:services:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
spec:benchmark:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test bundle exec rake spec:benchmark
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
spec:other:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:other
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
spinach:project:half:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
spinach:project:rest:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
spinach:other:ruby22:
|
||||||
|
image: ruby:2.2
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:other
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
tags:
|
||||||
|
- ruby
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
2.1.7
|
2.1.8
|
||||||
|
|
164
CHANGELOG
164
CHANGELOG
|
@ -1,5 +1,163 @@
|
||||||
Please view this file on the master branch, on stable branches it's out of date.
|
Please view this file on the master branch, on stable branches it's out of date.
|
||||||
|
|
||||||
|
v 8.6.0 (unreleased)
|
||||||
|
- Contributions to forked projects are included in calendar
|
||||||
|
- Improve the formatting for the user page bio (Connor Shea)
|
||||||
|
- Fix issue when pushing to projects ending in .wiki
|
||||||
|
- Fix avatar stretching by providing a cropping feature (Johann Pardanaud)
|
||||||
|
- Don't load all of GitLab in mail_room
|
||||||
|
- Strip leading and trailing spaces in URL validator (evuez)
|
||||||
|
- Return empty array instead of 404 when commit has no statuses in commit status API
|
||||||
|
- Update documentation to reflect Guest role not being enforced on internal projects
|
||||||
|
- Allow search for logged out users
|
||||||
|
- Don't show Issues/MRs from archived projects in Groups view
|
||||||
|
- Increase the notes polling timeout over time (Roberto Dip)
|
||||||
|
- Add shortcut to toggle markdown preview (Florent Baldino)
|
||||||
|
- Show labels in dashboard and group milestone views
|
||||||
|
- Add main language of a project in the list of projects (Tiago Botelho)
|
||||||
|
- Add ability to show archived projects on dashboard, explore and group pages
|
||||||
|
|
||||||
|
v 8.5.8
|
||||||
|
- Bump Git version requirement to 2.7.4
|
||||||
|
|
||||||
|
v 8.5.7
|
||||||
|
- Bump Git version requirement to 2.7.3
|
||||||
|
|
||||||
|
v 8.5.6
|
||||||
|
- Obtain a lease before querying LDAP
|
||||||
|
|
||||||
|
v 8.5.5
|
||||||
|
- Ensure removing a project removes associated Todo entries
|
||||||
|
- Prevent a 500 error in Todos when author was removed
|
||||||
|
- Fix pagination for filtered dashboard and explore pages
|
||||||
|
- Fix "Show all" link behavior
|
||||||
|
|
||||||
|
v 8.5.4
|
||||||
|
- Do not cache requests for badges (including builds badge)
|
||||||
|
|
||||||
|
v 8.5.3
|
||||||
|
- Flush repository caches before renaming projects
|
||||||
|
|
||||||
|
v 8.5.2
|
||||||
|
- Fix sidebar overlapping content when screen width was below 1200px
|
||||||
|
- Don't repeat labels listed on Labels tab
|
||||||
|
- Bring the "branded appearance" feature from EE to CE
|
||||||
|
- Fix error 500 when commenting on a commit
|
||||||
|
- Show days remaining instead of elapsed time for Milestone
|
||||||
|
- Fix broken icons on installations with relative URL (Artem Sidorenko)
|
||||||
|
- Fix issue where tag list wasn't refreshed after deleting a tag
|
||||||
|
- Fix import from gitlab.com (KazSawada)
|
||||||
|
- Improve implementation to check read access to forks and add pagination
|
||||||
|
- Don't show any "2FA required" message if it's not actually required
|
||||||
|
- Fix help keyboard shortcut on relative URL setups (Artem Sidorenko)
|
||||||
|
- Update Rails to 4.2.5.2
|
||||||
|
- Fix permissions for deprecated CI build status badge
|
||||||
|
- Don't show "Welcome to GitLab" when the search didn't return any projects
|
||||||
|
- Add Todos documentation
|
||||||
|
|
||||||
|
v 8.5.1
|
||||||
|
- Fix group projects styles
|
||||||
|
- Show Crowd login tab when sign in is disabled and Crowd is enabled (Peter Hudec)
|
||||||
|
- Fix a set of small UI glitches in project, profile, and wiki pages
|
||||||
|
- Restrict permissions on public/uploads
|
||||||
|
- Fix the merge request side-by-side view after loading diff results
|
||||||
|
- Fix the look of tooltip for the "Revert" button
|
||||||
|
- Add when the Builds & Runners API changes got introduced
|
||||||
|
- Fix error 500 on some merged merge requests
|
||||||
|
- Fix an issue causing the content of the issuable sidebar to disappear
|
||||||
|
- Fix error 500 when trying to mark an already done todo as "done"
|
||||||
|
- Fix an issue where MRs weren't sortable
|
||||||
|
- Issues can now be dragged & dropped into empty milestone lists. This is also
|
||||||
|
possible with MRs
|
||||||
|
- Changed padding & background color for highlighted notes
|
||||||
|
- Re-add the newrelic_rpm gem which was removed without any deprecation or warning (Stan Hu)
|
||||||
|
- Update sentry-raven gem to 0.15.6
|
||||||
|
|
||||||
|
v 8.5.0
|
||||||
|
- Fix duplicate "me" in tooltip of the "thumbsup" awards Emoji (Stan Hu)
|
||||||
|
- Cache various Repository methods to improve performance (Yorick Peterse)
|
||||||
|
- Fix duplicated branch creation/deletion Web hooks/service notifications when using Web UI (Stan Hu)
|
||||||
|
- Ensure rake tasks that don't need a DB connection can be run without one
|
||||||
|
- Update New Relic gem to 3.14.1.311 (Stan Hu)
|
||||||
|
- Add "visibility" flag to GET /projects api endpoint
|
||||||
|
- Add an option to supply root email through an environmental variable (Koichiro Mikami)
|
||||||
|
- Ignore binary files in code search to prevent Error 500 (Stan Hu)
|
||||||
|
- Render sanitized SVG images (Stan Hu)
|
||||||
|
- Support download access by PRIVATE-TOKEN header (Stan Hu)
|
||||||
|
- Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push
|
||||||
|
- Add option to include the sender name in body of Notify email (Jason Lee)
|
||||||
|
- New UI for pagination
|
||||||
|
- Don't prevent sign out when 2FA enforcement is enabled and user hasn't yet
|
||||||
|
set it up
|
||||||
|
- API: Added "merge_requests/:merge_request_id/closes_issues" (Gal Schlezinger)
|
||||||
|
- Fix diff comments loaded by AJAX to load comment with diff in discussion tab
|
||||||
|
- Fix relative links in other markup formats (Ben Boeckel)
|
||||||
|
- Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel)
|
||||||
|
- Fix label links for a merge request pointing to issues list
|
||||||
|
- Don't vendor minified JS
|
||||||
|
- Increase project import timeout to 15 minutes
|
||||||
|
- Be more permissive with email address validation: it only has to contain a single '@'
|
||||||
|
- Display 404 error on group not found
|
||||||
|
- Track project import failure
|
||||||
|
- Support Two-factor Authentication for LDAP users
|
||||||
|
- Display database type and version in Administration dashboard
|
||||||
|
- Allow limited Markdown in Broadcast Messages
|
||||||
|
- Fix visibility level text in admin area (Zeger-Jan van de Weg)
|
||||||
|
- Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg)
|
||||||
|
- Update the ExternalIssue regex pattern (Blake Hitchcock)
|
||||||
|
- Remember user's inline/side-by-side diff view preference in a cookie (Kirill Katsnelson)
|
||||||
|
- Optimized performance of finding issues to be closed by a merge request
|
||||||
|
- Add `avatar_url`, `description`, `git_ssh_url`, `git_http_url`, `path_with_namespace`
|
||||||
|
and `default_branch` in `project` in push, issue, merge-request and note webhooks data (Kirill Zaitsev)
|
||||||
|
- Deprecate the `ssh_url` in favor of `git_ssh_url` and `http_url` in favor of `git_http_url`
|
||||||
|
in `project` for push, issue, merge-request and note webhooks data (Kirill Zaitsev)
|
||||||
|
- Deprecate the `repository` key in push, issue, merge-request and note webhooks data, use `project` instead (Kirill Zaitsev)
|
||||||
|
- API: Expose MergeRequest#merge_status (Andrei Dziahel)
|
||||||
|
- Revert "Add IP check against DNSBLs at account sign-up"
|
||||||
|
- Actually use the `skip_merges` option in Repository#commits (Tony Chu)
|
||||||
|
- Fix API to keep request parameters in Link header (Michael Potthoff)
|
||||||
|
- Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead
|
||||||
|
- Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead
|
||||||
|
- Prevent parse error when name of project ends with .atom and prevent path issues
|
||||||
|
- Discover branches for commit statuses ref-less when doing merge when succeeded
|
||||||
|
- Mark inline difference between old and new paths when a file is renamed
|
||||||
|
- Support Akismet spam checking for creation of issues via API (Stan Hu)
|
||||||
|
- API: Allow to set or update a merge-request's milestone (Kirill Skachkov)
|
||||||
|
- Improve UI consistency between projects and groups lists
|
||||||
|
- Add sort dropdown to dashboard projects page
|
||||||
|
- Fixed logo animation on Safari (Roman Rott)
|
||||||
|
- Fix Merge When Succeeded when multiple stages
|
||||||
|
- Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg)
|
||||||
|
- In seach autocomplete show only groups and projects you are member of
|
||||||
|
- Don't process cross-reference notes from forks
|
||||||
|
- Fix: init.d script not working on OS X
|
||||||
|
- Faster snippet search
|
||||||
|
- Added API to download build artifacts
|
||||||
|
- Title for milestones should be unique (Zeger-Jan van de Weg)
|
||||||
|
- Validate correctness of maximum attachment size application setting
|
||||||
|
- Replaces "Create merge request" link with one to the "Merge Request" when one exists
|
||||||
|
- Fix CI builds badge, add a new link to builds badge, deprecate the old one
|
||||||
|
- Fix broken link to project in build notification emails
|
||||||
|
- Ability to see and sort on vote count from Issues and MR lists
|
||||||
|
- Fix builds scheduler when first build in stage was allowed to fail
|
||||||
|
- User project limit is reached notice is hidden if the projects limit is zero
|
||||||
|
- Add API support for managing runners and project's runners
|
||||||
|
- Allow SAML users to login with no previous account without having to allow
|
||||||
|
all Omniauth providers to do so.
|
||||||
|
- Allow existing users to auto link their SAML credentials by logging in via SAML
|
||||||
|
- Make it possible to erase a build (trace, artifacts) using UI and API
|
||||||
|
- Ability to revert changes from a Merge Request or Commit
|
||||||
|
- Emoji comment on diffs are not award emoji
|
||||||
|
- Add label description (Nuttanart Pornprasitsakul)
|
||||||
|
- Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul)
|
||||||
|
- Add Todos
|
||||||
|
|
||||||
|
v 8.4.4
|
||||||
|
- Update omniauth-saml gem to 1.4.2
|
||||||
|
- Prevent long-running backup tasks from timing out the database connection
|
||||||
|
- Add a Project setting to allow guests to view build logs (defaults to true)
|
||||||
|
- Sort project milestones by due date including issue editor (Oliver Rogers / Orih)
|
||||||
|
|
||||||
v 8.4.3
|
v 8.4.3
|
||||||
- Increase lfs_objects size column to 8-byte integer to allow files larger
|
- Increase lfs_objects size column to 8-byte integer to allow files larger
|
||||||
than 2.1GB
|
than 2.1GB
|
||||||
|
@ -22,12 +180,14 @@ v 8.4.2
|
||||||
track them in Performance Monitoring.
|
track them in Performance Monitoring.
|
||||||
- Increase contrast between highlighted code comments and inline diff marker
|
- Increase contrast between highlighted code comments and inline diff marker
|
||||||
- Fix method undefined when using external commit status in builds
|
- Fix method undefined when using external commit status in builds
|
||||||
|
- Fix highlighting in blame view.
|
||||||
|
|
||||||
v 8.4.1
|
v 8.4.1
|
||||||
- Apply security updates for Rails (4.2.5.1), rails-html-sanitizer (1.0.3),
|
- Apply security updates for Rails (4.2.5.1), rails-html-sanitizer (1.0.3),
|
||||||
and Nokogiri (1.6.7.2)
|
and Nokogiri (1.6.7.2)
|
||||||
- Fix redirect loop during import
|
- Fix redirect loop during import
|
||||||
- Fix diff highlighting for all syntax themes
|
- Fix diff highlighting for all syntax themes
|
||||||
|
- Delete project and associations in a background worker
|
||||||
|
|
||||||
v 8.4.0
|
v 8.4.0
|
||||||
- Allow LDAP users to change their email if it was not set by the LDAP server
|
- Allow LDAP users to change their email if it was not set by the LDAP server
|
||||||
|
@ -71,7 +231,7 @@ v 8.4.0
|
||||||
- Show 'All' tab by default in the builds page
|
- Show 'All' tab by default in the builds page
|
||||||
- Add Open Graph and Twitter Card data to all pages
|
- Add Open Graph and Twitter Card data to all pages
|
||||||
- Fix API project lookups when querying with a namespace with dots (Stan Hu)
|
- Fix API project lookups when querying with a namespace with dots (Stan Hu)
|
||||||
- Enable forcing Two-Factor authentication sitewide, with optional grace period
|
- Enable forcing Two-factor authentication sitewide, with optional grace period
|
||||||
- Import GitHub Pull Requests into GitLab
|
- Import GitHub Pull Requests into GitLab
|
||||||
- Change single user API endpoint to return more detailed data (Michael Potthoff)
|
- Change single user API endpoint to return more detailed data (Michael Potthoff)
|
||||||
- Update version check images to use SVG
|
- Update version check images to use SVG
|
||||||
|
@ -149,6 +309,7 @@ v 8.3.0
|
||||||
- Handle and report SSL errors in Web hook test (Stan Hu)
|
- Handle and report SSL errors in Web hook test (Stan Hu)
|
||||||
- Bump Redis requirement to 2.8 for Sidekiq 4 (Stan Hu)
|
- Bump Redis requirement to 2.8 for Sidekiq 4 (Stan Hu)
|
||||||
- Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera)
|
- Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera)
|
||||||
|
- WIP identifier on merge requests no longer requires trailing space
|
||||||
- Add rake tasks for git repository maintainance (Zeger-Jan van de Weg)
|
- Add rake tasks for git repository maintainance (Zeger-Jan van de Weg)
|
||||||
- Fix 500 error when update group member permission
|
- Fix 500 error when update group member permission
|
||||||
- Fix: As an admin, cannot add oneself as a member to a group/project
|
- Fix: As an admin, cannot add oneself as a member to a group/project
|
||||||
|
@ -331,6 +492,7 @@ v 8.1.0
|
||||||
- Improved performance of the trending projects page
|
- Improved performance of the trending projects page
|
||||||
- Remove CI migration task
|
- Remove CI migration task
|
||||||
- Improved performance of finding projects by their namespace
|
- Improved performance of finding projects by their namespace
|
||||||
|
- Add assignee data to Issuables' hook_data (Bram Daams)
|
||||||
- Fix bug where transferring a project would result in stale commit links (Stan Hu)
|
- Fix bug where transferring a project would result in stale commit links (Stan Hu)
|
||||||
- Fix build trace updating
|
- Fix build trace updating
|
||||||
- Include full path of source and target branch names in New Merge Request page (Stan Hu)
|
- Include full path of source and target branch names in New Merge Request page (Stan Hu)
|
||||||
|
|
161
CONTRIBUTING.md
161
CONTRIBUTING.md
|
@ -1,3 +1,29 @@
|
||||||
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||||
|
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
||||||
|
|
||||||
|
- [Contribute to GitLab](#contribute-to-gitlab)
|
||||||
|
- [Contributor license agreement](#contributor-license-agreement)
|
||||||
|
- [Security vulnerability disclosure](#security-vulnerability-disclosure)
|
||||||
|
- [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests)
|
||||||
|
- [Helping others](#helping-others)
|
||||||
|
- [I want to contribute!](#i-want-to-contribute)
|
||||||
|
- [Issue tracker](#issue-tracker)
|
||||||
|
- [Feature proposals](#feature-proposals)
|
||||||
|
- [Issue tracker guidelines](#issue-tracker-guidelines)
|
||||||
|
- [Issue weight](#issue-weight)
|
||||||
|
- [Regression issues](#regression-issues)
|
||||||
|
- [Merge requests](#merge-requests)
|
||||||
|
- [Merge request guidelines](#merge-request-guidelines)
|
||||||
|
- [Merge request description format](#merge-request-description-format)
|
||||||
|
- [Contribution acceptance criteria](#contribution-acceptance-criteria)
|
||||||
|
- [Changes for Stable Releases](#changes-for-stable-releases)
|
||||||
|
- [Definition of done](#definition-of-done)
|
||||||
|
- [Style guides](#style-guides)
|
||||||
|
- [Code of conduct](#code-of-conduct)
|
||||||
|
|
||||||
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
|
||||||
# Contribute to GitLab
|
# Contribute to GitLab
|
||||||
|
|
||||||
Thank you for your interest in contributing to GitLab. This guide details how
|
Thank you for your interest in contributing to GitLab. This guide details how
|
||||||
|
@ -147,7 +173,7 @@ sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true)
|
||||||
sudo gitlab-rake gitlab:env:info)
|
sudo gitlab-rake gitlab:env:info)
|
||||||
|
|
||||||
(For installations from source run and paste the output of:
|
(For installations from source run and paste the output of:
|
||||||
sudo -u git -H bundle exec rake gitlab:env:info)
|
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production)
|
||||||
|
|
||||||
## Possible fixes
|
## Possible fixes
|
||||||
|
|
||||||
|
@ -177,6 +203,26 @@ is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
|
||||||
issues or chunks. You can simply not set the weight of a parent issue and set
|
issues or chunks. You can simply not set the weight of a parent issue and set
|
||||||
weights to children issues.
|
weights to children issues.
|
||||||
|
|
||||||
|
### Regression issues
|
||||||
|
|
||||||
|
Every monthly release has a corresponding issue on the CE issue tracker to keep
|
||||||
|
track of functionality broken by that release and any fixes that need to be
|
||||||
|
included in a patch release (see [8.3 Regressions] as an example).
|
||||||
|
|
||||||
|
As outlined in the issue description, the intended workflow is to post one note
|
||||||
|
with a reference to an issue describing the regression, and then to update that
|
||||||
|
note with a reference to the merge request that fixes it as it becomes available.
|
||||||
|
|
||||||
|
If you're a contributor who doesn't have the required permissions to update
|
||||||
|
other users' notes, please post a new note with a reference to both the issue
|
||||||
|
and the merge request.
|
||||||
|
|
||||||
|
The release manager will [update the notes] in the regression issue as fixes are
|
||||||
|
addressed.
|
||||||
|
|
||||||
|
[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127
|
||||||
|
[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue
|
||||||
|
|
||||||
## Merge requests
|
## Merge requests
|
||||||
|
|
||||||
We welcome merge requests with fixes and improvements to GitLab code, tests,
|
We welcome merge requests with fixes and improvements to GitLab code, tests,
|
||||||
|
@ -214,15 +260,17 @@ request is as follows:
|
||||||
1. Add your changes to the [CHANGELOG](CHANGELOG)
|
1. Add your changes to the [CHANGELOG](CHANGELOG)
|
||||||
1. If you are changing the README, some documentation or other things which
|
1. If you are changing the README, some documentation or other things which
|
||||||
have no effect on the tests, add `[ci skip]` somewhere in the commit message
|
have no effect on the tests, add `[ci skip]` somewhere in the commit message
|
||||||
|
and make sure to read the [documentation styleguide][doc-styleguide]
|
||||||
1. If you have multiple commits please combine them into one commit by
|
1. If you have multiple commits please combine them into one commit by
|
||||||
[squashing them][git-squash]
|
[squashing them][git-squash]
|
||||||
1. Push the commit(s) to your fork
|
1. Push the commit(s) to your fork
|
||||||
1. Submit a merge request (MR) to the master branch
|
1. Submit a merge request (MR) to the master branch
|
||||||
1. The MR title should describe the change you want to make
|
1. The MR title should describe the change you want to make
|
||||||
1. The MR description should give a motive for your change and the method you
|
1. The MR description should give a motive for your change and the method you
|
||||||
used to achieve it
|
used to achieve it, see the [merge request description format]
|
||||||
|
(#merge-request-description-format)
|
||||||
1. If the MR changes the UI it should include before and after screenshots
|
1. If the MR changes the UI it should include before and after screenshots
|
||||||
1. If the MR changes CSS classes please include the list of affected pages
|
1. If the MR changes CSS classes please include the list of affected pages,
|
||||||
`grep css-class ./app -R`
|
`grep css-class ./app -R`
|
||||||
1. Link any relevant [issues][ce-tracker] in the merge request description and
|
1. Link any relevant [issues][ce-tracker] in the merge request description and
|
||||||
leave a comment on them with a link back to the MR
|
leave a comment on them with a link back to the MR
|
||||||
|
@ -255,6 +303,69 @@ For examples of feedback on merge requests please look at already
|
||||||
request feel free to mention one of the Merge Marshalls of the [core team][].
|
request feel free to mention one of the Merge Marshalls of the [core team][].
|
||||||
Please ensure that your merge request meets the contribution acceptance criteria.
|
Please ensure that your merge request meets the contribution acceptance criteria.
|
||||||
|
|
||||||
|
When having your code reviewed and when reviewing merge requests please take the
|
||||||
|
[thoughtbot code review guidelines](https://github.com/thoughtbot/guides/tree/master/code-review)
|
||||||
|
into account.
|
||||||
|
|
||||||
|
### Merge request description format
|
||||||
|
|
||||||
|
Please submit merge requests using the following template in the merge request
|
||||||
|
description area. Copy-paste it to retain the markdown format.
|
||||||
|
|
||||||
|
```
|
||||||
|
## What does this MR do?
|
||||||
|
|
||||||
|
## Are there points in the code the reviewer needs to double check?
|
||||||
|
|
||||||
|
## Why was this MR needed?
|
||||||
|
|
||||||
|
## What are the relevant issue numbers?
|
||||||
|
|
||||||
|
## Screenshots (if relevant)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Contribution acceptance criteria
|
||||||
|
|
||||||
|
1. The change is as small as possible
|
||||||
|
1. Include proper tests and make all tests pass (unless it contains a test
|
||||||
|
exposing a bug in existing code)
|
||||||
|
1. If you suspect a failing CI build is unrelated to your contribution, you may
|
||||||
|
try and restart the failing CI job or ask a developer to fix the
|
||||||
|
aforementioned failing test
|
||||||
|
1. Your MR initially contains a single commit (please use `git rebase -i` to
|
||||||
|
squash commits)
|
||||||
|
1. Your changes can merge without problems (if not please merge `master`, never
|
||||||
|
rebase commits pushed to the remote server)
|
||||||
|
1. Does not break any existing functionality
|
||||||
|
1. Fixes one specific issue or implements one specific feature (do not combine
|
||||||
|
things, send separate merge requests if needed)
|
||||||
|
1. Migrations should do only one thing (e.g., either create a table, move data
|
||||||
|
to a new table or remove an old table) to aid retrying on failure
|
||||||
|
1. Keeps the GitLab code base clean and well structured
|
||||||
|
1. Contains functionality we think other users will benefit from too
|
||||||
|
1. Doesn't add configuration options since they complicate future changes
|
||||||
|
1. Changes after submitting the merge request should be in separate commits
|
||||||
|
(no squashing). If necessary, you will be asked to squash when the review is
|
||||||
|
over, before merging.
|
||||||
|
1. It conforms to the [style guides](#style-guides) and the following:
|
||||||
|
- If your change touches a line that does not follow the style, modify the
|
||||||
|
entire line to follow it. This prevents linting tools from generating warnings.
|
||||||
|
- Don't touch neighbouring lines. As an exception, automatic mass
|
||||||
|
refactoring modifications may leave style non-compliant.
|
||||||
|
|
||||||
|
## Changes for Stable Releases
|
||||||
|
|
||||||
|
Sometimes certain changes have to be added to an existing stable release.
|
||||||
|
Two examples are bug fixes and performance improvements. In these cases the
|
||||||
|
corresponding merge request should be updated to have the following:
|
||||||
|
|
||||||
|
1. A milestone indicating what release the merge request should be merged into.
|
||||||
|
1. The label "Pick into Stable"
|
||||||
|
|
||||||
|
This makes it easier for release managers to keep track of what still has to be
|
||||||
|
merged and where changes have to be merged into.
|
||||||
|
Like all merge requests the target should be master so all bugfixes are in master.
|
||||||
|
|
||||||
## Definition of done
|
## Definition of done
|
||||||
|
|
||||||
If you contribute to GitLab please know that changes involve more than just
|
If you contribute to GitLab please know that changes involve more than just
|
||||||
|
@ -264,7 +375,7 @@ the feature you contribute through all of these steps.
|
||||||
1. Description explaining the relevancy (see following item)
|
1. Description explaining the relevancy (see following item)
|
||||||
1. Working and clean code that is commented where needed
|
1. Working and clean code that is commented where needed
|
||||||
1. Unit and integration tests that pass on the CI server
|
1. Unit and integration tests that pass on the CI server
|
||||||
1. Documented in the /doc directory
|
1. [Documented][doc-styleguide] in the /doc directory
|
||||||
1. Changelog entry added
|
1. Changelog entry added
|
||||||
1. Reviewed and any concerns are addressed
|
1. Reviewed and any concerns are addressed
|
||||||
1. Merged by the project lead
|
1. Merged by the project lead
|
||||||
|
@ -285,43 +396,6 @@ merge request:
|
||||||
1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh
|
1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh
|
||||||
1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
|
1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
|
||||||
|
|
||||||
## Merge request description format
|
|
||||||
|
|
||||||
1. What does this MR do?
|
|
||||||
1. Are there points in the code the reviewer needs to double check?
|
|
||||||
1. Why was this MR needed?
|
|
||||||
1. What are the relevant issue numbers?
|
|
||||||
1. Screenshots (if relevant)
|
|
||||||
|
|
||||||
## Contribution acceptance criteria
|
|
||||||
|
|
||||||
1. The change is as small as possible (see the above paragraph for details)
|
|
||||||
1. Include proper tests and make all tests pass (unless it contains a test
|
|
||||||
exposing a bug in existing code)
|
|
||||||
1. If you suspect a failing CI build is unrelated to your contribution, you may
|
|
||||||
try and restart the failing CI job or ask a developer to fix the
|
|
||||||
aforementioned failing test
|
|
||||||
1. Your MR initially contains a single commit (please use `git rebase -i` to
|
|
||||||
squash commits)
|
|
||||||
1. Your changes can merge without problems (if not please merge `master`, never
|
|
||||||
rebase commits pushed to the remote server)
|
|
||||||
1. Does not break any existing functionality
|
|
||||||
1. Fixes one specific issue or implements one specific feature (do not combine
|
|
||||||
things, send separate merge requests if needed)
|
|
||||||
1. Migrations should do only one thing (eg: either create a table, move data to
|
|
||||||
a new table or remove an old table) to aid retrying on failure
|
|
||||||
1. Keeps the GitLab code base clean and well structured
|
|
||||||
1. Contains functionality we think other users will benefit from too
|
|
||||||
1. Doesn't add configuration options since they complicate future changes
|
|
||||||
1. Changes after submitting the merge request should be in separate commits
|
|
||||||
(no squashing). If necessary, you will be asked to squash when the review is
|
|
||||||
over, before merging.
|
|
||||||
1. It conforms to the following style guides:
|
|
||||||
* If your change touches a line that does not follow the style, modify the
|
|
||||||
entire line to follow it. This prevents linting tools from generating warnings.
|
|
||||||
* Don't touch neighbouring lines. As an exception, automatic mass
|
|
||||||
refactoring modifications may leave style non-compliant.
|
|
||||||
|
|
||||||
## Style guides
|
## Style guides
|
||||||
|
|
||||||
1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
|
1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
|
||||||
|
@ -336,7 +410,7 @@ merge request:
|
||||||
contributors to enhance security
|
contributors to enhance security
|
||||||
1. [Database Migrations](doc/development/migration_style_guide.md)
|
1. [Database Migrations](doc/development/migration_style_guide.md)
|
||||||
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
|
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
|
||||||
1. [Documentation styleguide](doc/development/doc_styleguide.md)
|
1. [Documentation styleguide][doc-styleguide]
|
||||||
1. Interface text should be written subjectively instead of objectively. It
|
1. Interface text should be written subjectively instead of objectively. It
|
||||||
should be the GitLab core team addressing a person. It should be written in
|
should be the GitLab core team addressing a person. It should be written in
|
||||||
present time and never use past tense (has been/was). For example instead
|
present time and never use past tense (has been/was). For example instead
|
||||||
|
@ -377,7 +451,7 @@ reported by emailing `contact@gitlab.com`.
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][], version 1.1.0,
|
This Code of Conduct is adapted from the [Contributor Covenant][], version 1.1.0,
|
||||||
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
|
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
|
||||||
|
|
||||||
[core team]: https://about.gitlab.com/core-team/
|
[core-team]: https://about.gitlab.com/core-team/
|
||||||
[getting help page]: https://about.gitlab.com/getting-help/
|
[getting help page]: https://about.gitlab.com/getting-help/
|
||||||
[Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
|
[Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
|
||||||
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up-for-grabs
|
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up-for-grabs
|
||||||
|
@ -398,3 +472,4 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
|
||||||
[Contributor Covenant]: http://contributor-covenant.org
|
[Contributor Covenant]: http://contributor-covenant.org
|
||||||
[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
|
[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
|
||||||
[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
|
[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
|
||||||
|
[doc-styleguide]: doc/development/doc_styleguide.md "Documentation styleguide"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.6.2
|
0.6.4
|
||||||
|
|
29
Gemfile
29
Gemfile
|
@ -1,6 +1,6 @@
|
||||||
source "https://rubygems.org"
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gem 'rails', '4.2.5.1'
|
gem 'rails', '4.2.5.2'
|
||||||
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
|
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
|
||||||
|
|
||||||
# Responders respond_to and respond_with
|
# Responders respond_to and respond_with
|
||||||
|
@ -21,7 +21,7 @@ gem "pg", '~> 0.18.2', group: :postgres
|
||||||
gem 'devise', '~> 3.5.4'
|
gem 'devise', '~> 3.5.4'
|
||||||
gem 'devise-async', '~> 0.9.0'
|
gem 'devise-async', '~> 0.9.0'
|
||||||
gem 'doorkeeper', '~> 2.2.0'
|
gem 'doorkeeper', '~> 2.2.0'
|
||||||
gem 'omniauth', '~> 1.2.2'
|
gem 'omniauth', '~> 1.3.1'
|
||||||
gem 'omniauth-azure-oauth2', '~> 0.0.6'
|
gem 'omniauth-azure-oauth2', '~> 0.0.6'
|
||||||
gem 'omniauth-bitbucket', '~> 0.0.2'
|
gem 'omniauth-bitbucket', '~> 0.0.2'
|
||||||
gem 'omniauth-cas3', '~> 1.1.2'
|
gem 'omniauth-cas3', '~> 1.1.2'
|
||||||
|
@ -30,14 +30,15 @@ gem 'omniauth-github', '~> 1.1.1'
|
||||||
gem 'omniauth-gitlab', '~> 1.0.0'
|
gem 'omniauth-gitlab', '~> 1.0.0'
|
||||||
gem 'omniauth-google-oauth2', '~> 0.2.0'
|
gem 'omniauth-google-oauth2', '~> 0.2.0'
|
||||||
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
|
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
|
||||||
gem 'omniauth-saml', '~> 1.4.0'
|
gem 'omniauth-saml', '~> 1.4.2'
|
||||||
gem 'omniauth-shibboleth', '~> 1.2.0'
|
gem 'omniauth-shibboleth', '~> 1.2.0'
|
||||||
gem 'omniauth-twitter', '~> 1.2.0'
|
gem 'omniauth-twitter', '~> 1.2.0'
|
||||||
gem 'omniauth_crowd', '~> 2.2.0'
|
gem 'omniauth_crowd', '~> 2.2.0'
|
||||||
gem 'rack-oauth2', '~> 1.2.1'
|
gem 'rack-oauth2', '~> 1.2.1'
|
||||||
|
|
||||||
# reCAPTCHA protection
|
# Spam and anti-bot protection
|
||||||
gem 'recaptcha', require: 'recaptcha/rails'
|
gem 'recaptcha', require: 'recaptcha/rails'
|
||||||
|
gem 'akismet', '~> 2.0'
|
||||||
|
|
||||||
# Two-factor authentication
|
# Two-factor authentication
|
||||||
gem 'devise-two-factor', '~> 2.0.0'
|
gem 'devise-two-factor', '~> 2.0.0'
|
||||||
|
@ -49,7 +50,7 @@ gem "browser", '~> 1.0.0'
|
||||||
|
|
||||||
# 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.2.22'
|
gem "gitlab_git", '~> 8.2'
|
||||||
|
|
||||||
# LDAP Auth
|
# LDAP Auth
|
||||||
# GitLab fork with several improvements to original library. For full list of changes
|
# GitLab fork with several improvements to original library. For full list of changes
|
||||||
|
@ -104,7 +105,7 @@ gem 'rouge', '~> 1.10.1'
|
||||||
|
|
||||||
# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
|
# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
|
||||||
# and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM
|
# and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM
|
||||||
gem 'nokogiri', '1.6.7.2'
|
gem 'nokogiri', '~> 1.6.7', '>= 1.6.7.2'
|
||||||
|
|
||||||
# Diffs
|
# Diffs
|
||||||
gem 'diffy', '~> 3.0.3'
|
gem 'diffy', '~> 3.0.3'
|
||||||
|
@ -179,6 +180,9 @@ gem "underscore-rails", "~> 1.8.0"
|
||||||
gem "sanitize", '~> 2.0'
|
gem "sanitize", '~> 2.0'
|
||||||
gem 'babosa', '~> 1.0.2'
|
gem 'babosa', '~> 1.0.2'
|
||||||
|
|
||||||
|
# Sanitizes SVG input
|
||||||
|
gem "loofah", "~> 2.0.3"
|
||||||
|
|
||||||
# Protect against bruteforcing
|
# Protect against bruteforcing
|
||||||
gem "rack-attack", '~> 4.3.1'
|
gem "rack-attack", '~> 4.3.1'
|
||||||
|
|
||||||
|
@ -200,7 +204,7 @@ gem 'jquery-turbolinks', '~> 2.1.0'
|
||||||
gem 'addressable', '~> 2.3.8'
|
gem 'addressable', '~> 2.3.8'
|
||||||
gem 'bootstrap-sass', '~> 3.3.0'
|
gem 'bootstrap-sass', '~> 3.3.0'
|
||||||
gem 'font-awesome-rails', '~> 4.2'
|
gem 'font-awesome-rails', '~> 4.2'
|
||||||
gem 'gitlab_emoji', '~> 0.2.0'
|
gem 'gitlab_emoji', '~> 0.3.0'
|
||||||
gem 'gon', '~> 6.0.1'
|
gem 'gon', '~> 6.0.1'
|
||||||
gem 'jquery-atwho-rails', '~> 1.3.2'
|
gem 'jquery-atwho-rails', '~> 1.3.2'
|
||||||
gem 'jquery-rails', '~> 4.0.0'
|
gem 'jquery-rails', '~> 4.0.0'
|
||||||
|
@ -213,6 +217,9 @@ gem 'select2-rails', '~> 3.5.9'
|
||||||
gem 'virtus', '~> 1.0.1'
|
gem 'virtus', '~> 1.0.1'
|
||||||
gem 'net-ssh', '~> 3.0.1'
|
gem 'net-ssh', '~> 3.0.1'
|
||||||
|
|
||||||
|
# Sentry integration
|
||||||
|
gem 'sentry-raven', '~> 0.15'
|
||||||
|
|
||||||
# Metrics
|
# Metrics
|
||||||
group :metrics do
|
group :metrics do
|
||||||
gem 'allocations', '~> 1.0', require: false, platform: :mri
|
gem 'allocations', '~> 1.0', require: false, platform: :mri
|
||||||
|
@ -294,15 +301,11 @@ end
|
||||||
|
|
||||||
group :production do
|
group :production do
|
||||||
gem "gitlab_meta", '7.0'
|
gem "gitlab_meta", '7.0'
|
||||||
|
|
||||||
# Sentry integration
|
|
||||||
gem 'sentry-raven'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
gem "newrelic_rpm", '~> 3.9.4.245'
|
gem "newrelic_rpm", '~> 3.14'
|
||||||
gem 'newrelic-grape'
|
|
||||||
|
|
||||||
gem 'octokit', '~> 3.7.0'
|
gem 'octokit', '~> 3.8.0'
|
||||||
|
|
||||||
gem "mail_room", "~> 0.6.1"
|
gem "mail_room", "~> 0.6.1"
|
||||||
|
|
||||||
|
|
115
Gemfile.lock
115
Gemfile.lock
|
@ -4,41 +4,41 @@ GEM
|
||||||
CFPropertyList (2.3.2)
|
CFPropertyList (2.3.2)
|
||||||
RedCloth (4.2.9)
|
RedCloth (4.2.9)
|
||||||
ace-rails-ap (2.0.1)
|
ace-rails-ap (2.0.1)
|
||||||
actionmailer (4.2.5.1)
|
actionmailer (4.2.5.2)
|
||||||
actionpack (= 4.2.5.1)
|
actionpack (= 4.2.5.2)
|
||||||
actionview (= 4.2.5.1)
|
actionview (= 4.2.5.2)
|
||||||
activejob (= 4.2.5.1)
|
activejob (= 4.2.5.2)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||||
actionpack (4.2.5.1)
|
actionpack (4.2.5.2)
|
||||||
actionview (= 4.2.5.1)
|
actionview (= 4.2.5.2)
|
||||||
activesupport (= 4.2.5.1)
|
activesupport (= 4.2.5.2)
|
||||||
rack (~> 1.6)
|
rack (~> 1.6)
|
||||||
rack-test (~> 0.6.2)
|
rack-test (~> 0.6.2)
|
||||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
actionview (4.2.5.1)
|
actionview (4.2.5.2)
|
||||||
activesupport (= 4.2.5.1)
|
activesupport (= 4.2.5.2)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubis (~> 2.7.0)
|
erubis (~> 2.7.0)
|
||||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
activejob (4.2.5.1)
|
activejob (4.2.5.2)
|
||||||
activesupport (= 4.2.5.1)
|
activesupport (= 4.2.5.2)
|
||||||
globalid (>= 0.3.0)
|
globalid (>= 0.3.0)
|
||||||
activemodel (4.2.5.1)
|
activemodel (4.2.5.2)
|
||||||
activesupport (= 4.2.5.1)
|
activesupport (= 4.2.5.2)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
activerecord (4.2.5.1)
|
activerecord (4.2.5.2)
|
||||||
activemodel (= 4.2.5.1)
|
activemodel (= 4.2.5.2)
|
||||||
activesupport (= 4.2.5.1)
|
activesupport (= 4.2.5.2)
|
||||||
arel (~> 6.0)
|
arel (~> 6.0)
|
||||||
activerecord-deprecated_finders (1.0.4)
|
activerecord-deprecated_finders (1.0.4)
|
||||||
activerecord-session_store (0.1.2)
|
activerecord-session_store (0.1.2)
|
||||||
actionpack (>= 4.0.0, < 5)
|
actionpack (>= 4.0.0, < 5)
|
||||||
activerecord (>= 4.0.0, < 5)
|
activerecord (>= 4.0.0, < 5)
|
||||||
railties (>= 4.0.0, < 5)
|
railties (>= 4.0.0, < 5)
|
||||||
activesupport (4.2.5.1)
|
activesupport (4.2.5.2)
|
||||||
i18n (~> 0.7)
|
i18n (~> 0.7)
|
||||||
json (~> 1.7, >= 1.7.7)
|
json (~> 1.7, >= 1.7.7)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
|
@ -49,7 +49,8 @@ GEM
|
||||||
addressable (2.3.8)
|
addressable (2.3.8)
|
||||||
after_commit_queue (1.3.0)
|
after_commit_queue (1.3.0)
|
||||||
activerecord (>= 3.0)
|
activerecord (>= 3.0)
|
||||||
allocations (1.0.3)
|
akismet (2.0.0)
|
||||||
|
allocations (1.0.4)
|
||||||
annotate (2.6.10)
|
annotate (2.6.10)
|
||||||
activerecord (>= 3.2, <= 4.3)
|
activerecord (>= 3.2, <= 4.3)
|
||||||
rake (~> 10.4)
|
rake (~> 10.4)
|
||||||
|
@ -335,11 +336,11 @@ GEM
|
||||||
ruby-progressbar (~> 1.4)
|
ruby-progressbar (~> 1.4)
|
||||||
gemnasium-gitlab-service (0.2.6)
|
gemnasium-gitlab-service (0.2.6)
|
||||||
rugged (~> 0.21)
|
rugged (~> 0.21)
|
||||||
gemojione (2.1.1)
|
gemojione (2.2.1)
|
||||||
json
|
json
|
||||||
get_process_mem (0.2.0)
|
get_process_mem (0.2.0)
|
||||||
gherkin-ruby (0.3.2)
|
gherkin-ruby (0.3.2)
|
||||||
github-linguist (4.7.3)
|
github-linguist (4.7.5)
|
||||||
charlock_holmes (~> 0.7.3)
|
charlock_holmes (~> 0.7.3)
|
||||||
escape_utils (~> 1.1.0)
|
escape_utils (~> 1.1.0)
|
||||||
mime-types (>= 1.19)
|
mime-types (>= 1.19)
|
||||||
|
@ -354,13 +355,13 @@ GEM
|
||||||
diff-lcs (~> 1.1)
|
diff-lcs (~> 1.1)
|
||||||
mime-types (~> 1.15)
|
mime-types (~> 1.15)
|
||||||
posix-spawn (~> 0.3)
|
posix-spawn (~> 0.3)
|
||||||
gitlab_emoji (0.2.0)
|
gitlab_emoji (0.3.1)
|
||||||
gemojione (~> 2.1)
|
gemojione (~> 2.2, >= 2.2.1)
|
||||||
gitlab_git (7.2.24)
|
gitlab_git (8.2.0)
|
||||||
activesupport (~> 4.0)
|
activesupport (~> 4.0)
|
||||||
charlock_holmes (~> 0.7.3)
|
charlock_holmes (~> 0.7.3)
|
||||||
github-linguist (~> 4.7.0)
|
github-linguist (~> 4.7.0)
|
||||||
rugged (~> 0.23.3)
|
rugged (~> 0.24.0b13)
|
||||||
gitlab_meta (7.0)
|
gitlab_meta (7.0)
|
||||||
gitlab_omniauth-ldap (1.2.1)
|
gitlab_omniauth-ldap (1.2.1)
|
||||||
net-ldap (~> 0.9)
|
net-ldap (~> 0.9)
|
||||||
|
@ -478,10 +479,7 @@ GEM
|
||||||
net-ldap (0.12.1)
|
net-ldap (0.12.1)
|
||||||
net-ssh (3.0.1)
|
net-ssh (3.0.1)
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
newrelic-grape (2.1.0)
|
newrelic_rpm (3.14.1.311)
|
||||||
grape
|
|
||||||
newrelic_rpm
|
|
||||||
newrelic_rpm (3.9.4.245)
|
|
||||||
nokogiri (1.6.7.2)
|
nokogiri (1.6.7.2)
|
||||||
mini_portile2 (~> 2.0.0.rc2)
|
mini_portile2 (~> 2.0.0.rc2)
|
||||||
nprogress-rails (0.1.6.7)
|
nprogress-rails (0.1.6.7)
|
||||||
|
@ -492,11 +490,11 @@ GEM
|
||||||
multi_json (~> 1.3)
|
multi_json (~> 1.3)
|
||||||
multi_xml (~> 0.5)
|
multi_xml (~> 0.5)
|
||||||
rack (~> 1.2)
|
rack (~> 1.2)
|
||||||
octokit (3.7.1)
|
octokit (3.8.0)
|
||||||
sawyer (~> 0.6.0, >= 0.5.3)
|
sawyer (~> 0.6.0, >= 0.5.3)
|
||||||
omniauth (1.2.2)
|
omniauth (1.3.1)
|
||||||
hashie (>= 1.2, < 4)
|
hashie (>= 1.2, < 4)
|
||||||
rack (~> 1.0)
|
rack (>= 1.0, < 3)
|
||||||
omniauth-azure-oauth2 (0.0.6)
|
omniauth-azure-oauth2 (0.0.6)
|
||||||
jwt (~> 1.0)
|
jwt (~> 1.0)
|
||||||
omniauth (~> 1.0)
|
omniauth (~> 1.0)
|
||||||
|
@ -534,9 +532,9 @@ GEM
|
||||||
omniauth-oauth2 (1.3.1)
|
omniauth-oauth2 (1.3.1)
|
||||||
oauth2 (~> 1.0)
|
oauth2 (~> 1.0)
|
||||||
omniauth (~> 1.2)
|
omniauth (~> 1.2)
|
||||||
omniauth-saml (1.4.1)
|
omniauth-saml (1.4.2)
|
||||||
omniauth (~> 1.1)
|
omniauth (~> 1.1)
|
||||||
ruby-saml (~> 1.0.0)
|
ruby-saml (~> 1.1, >= 1.1.1)
|
||||||
omniauth-shibboleth (1.2.1)
|
omniauth-shibboleth (1.2.1)
|
||||||
omniauth (>= 1.0.0)
|
omniauth (>= 1.0.0)
|
||||||
omniauth-twitter (1.2.1)
|
omniauth-twitter (1.2.1)
|
||||||
|
@ -588,16 +586,16 @@ GEM
|
||||||
rack
|
rack
|
||||||
rack-test (0.6.3)
|
rack-test (0.6.3)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
rails (4.2.5.1)
|
rails (4.2.5.2)
|
||||||
actionmailer (= 4.2.5.1)
|
actionmailer (= 4.2.5.2)
|
||||||
actionpack (= 4.2.5.1)
|
actionpack (= 4.2.5.2)
|
||||||
actionview (= 4.2.5.1)
|
actionview (= 4.2.5.2)
|
||||||
activejob (= 4.2.5.1)
|
activejob (= 4.2.5.2)
|
||||||
activemodel (= 4.2.5.1)
|
activemodel (= 4.2.5.2)
|
||||||
activerecord (= 4.2.5.1)
|
activerecord (= 4.2.5.2)
|
||||||
activesupport (= 4.2.5.1)
|
activesupport (= 4.2.5.2)
|
||||||
bundler (>= 1.3.0, < 2.0)
|
bundler (>= 1.3.0, < 2.0)
|
||||||
railties (= 4.2.5.1)
|
railties (= 4.2.5.2)
|
||||||
sprockets-rails
|
sprockets-rails
|
||||||
rails-deprecated_sanitizer (1.0.3)
|
rails-deprecated_sanitizer (1.0.3)
|
||||||
activesupport (>= 4.2.0.alpha)
|
activesupport (>= 4.2.0.alpha)
|
||||||
|
@ -607,9 +605,9 @@ GEM
|
||||||
rails-deprecated_sanitizer (>= 1.0.1)
|
rails-deprecated_sanitizer (>= 1.0.1)
|
||||||
rails-html-sanitizer (1.0.3)
|
rails-html-sanitizer (1.0.3)
|
||||||
loofah (~> 2.0)
|
loofah (~> 2.0)
|
||||||
railties (4.2.5.1)
|
railties (4.2.5.2)
|
||||||
actionpack (= 4.2.5.1)
|
actionpack (= 4.2.5.2)
|
||||||
activesupport (= 4.2.5.1)
|
activesupport (= 4.2.5.2)
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
rainbow (2.0.0)
|
rainbow (2.0.0)
|
||||||
|
@ -692,7 +690,7 @@ GEM
|
||||||
ruby-fogbugz (0.2.1)
|
ruby-fogbugz (0.2.1)
|
||||||
crack (~> 0.4)
|
crack (~> 0.4)
|
||||||
ruby-progressbar (1.7.5)
|
ruby-progressbar (1.7.5)
|
||||||
ruby-saml (1.0.0)
|
ruby-saml (1.1.1)
|
||||||
nokogiri (>= 1.5.10)
|
nokogiri (>= 1.5.10)
|
||||||
uuid (~> 2.3)
|
uuid (~> 2.3)
|
||||||
ruby2ruby (2.2.0)
|
ruby2ruby (2.2.0)
|
||||||
|
@ -703,7 +701,7 @@ GEM
|
||||||
rubyntlm (0.5.2)
|
rubyntlm (0.5.2)
|
||||||
rubypants (0.2.0)
|
rubypants (0.2.0)
|
||||||
rufus-scheduler (3.1.10)
|
rufus-scheduler (3.1.10)
|
||||||
rugged (0.23.3)
|
rugged (0.24.0b13)
|
||||||
safe_yaml (1.0.4)
|
safe_yaml (1.0.4)
|
||||||
sanitize (2.1.0)
|
sanitize (2.1.0)
|
||||||
nokogiri (>= 1.4.4)
|
nokogiri (>= 1.4.4)
|
||||||
|
@ -725,7 +723,7 @@ GEM
|
||||||
activesupport (>= 3.1, < 4.3)
|
activesupport (>= 3.1, < 4.3)
|
||||||
select2-rails (3.5.9.3)
|
select2-rails (3.5.9.3)
|
||||||
thor (~> 0.14)
|
thor (~> 0.14)
|
||||||
sentry-raven (0.15.4)
|
sentry-raven (0.15.6)
|
||||||
faraday (>= 0.7.6)
|
faraday (>= 0.7.6)
|
||||||
settingslogic (2.0.9)
|
settingslogic (2.0.9)
|
||||||
sexp_processor (4.6.0)
|
sexp_processor (4.6.0)
|
||||||
|
@ -884,6 +882,7 @@ DEPENDENCIES
|
||||||
acts-as-taggable-on (~> 3.4)
|
acts-as-taggable-on (~> 3.4)
|
||||||
addressable (~> 2.3.8)
|
addressable (~> 2.3.8)
|
||||||
after_commit_queue
|
after_commit_queue
|
||||||
|
akismet (~> 2.0)
|
||||||
allocations (~> 1.0)
|
allocations (~> 1.0)
|
||||||
annotate (~> 2.6.0)
|
annotate (~> 2.6.0)
|
||||||
asana (~> 0.4.0)
|
asana (~> 0.4.0)
|
||||||
|
@ -933,8 +932,8 @@ DEPENDENCIES
|
||||||
github-linguist (~> 4.7.0)
|
github-linguist (~> 4.7.0)
|
||||||
github-markup (~> 1.3.1)
|
github-markup (~> 1.3.1)
|
||||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||||
gitlab_emoji (~> 0.2.0)
|
gitlab_emoji (~> 0.3.0)
|
||||||
gitlab_git (~> 7.2.22)
|
gitlab_git (~> 8.2)
|
||||||
gitlab_meta (= 7.0)
|
gitlab_meta (= 7.0)
|
||||||
gitlab_omniauth-ldap (~> 1.2.1)
|
gitlab_omniauth-ldap (~> 1.2.1)
|
||||||
gollum-lib (~> 4.1.0)
|
gollum-lib (~> 4.1.0)
|
||||||
|
@ -953,6 +952,7 @@ DEPENDENCIES
|
||||||
jquery-ui-rails (~> 5.0.0)
|
jquery-ui-rails (~> 5.0.0)
|
||||||
kaminari (~> 0.16.3)
|
kaminari (~> 0.16.3)
|
||||||
letter_opener (~> 1.1.2)
|
letter_opener (~> 1.1.2)
|
||||||
|
loofah (~> 2.0.3)
|
||||||
mail_room (~> 0.6.1)
|
mail_room (~> 0.6.1)
|
||||||
method_source (~> 0.8)
|
method_source (~> 0.8)
|
||||||
minitest (~> 5.7.0)
|
minitest (~> 5.7.0)
|
||||||
|
@ -960,13 +960,12 @@ DEPENDENCIES
|
||||||
mysql2 (~> 0.3.16)
|
mysql2 (~> 0.3.16)
|
||||||
nested_form (~> 0.3.2)
|
nested_form (~> 0.3.2)
|
||||||
net-ssh (~> 3.0.1)
|
net-ssh (~> 3.0.1)
|
||||||
newrelic-grape
|
newrelic_rpm (~> 3.14)
|
||||||
newrelic_rpm (~> 3.9.4.245)
|
nokogiri (~> 1.6.7, >= 1.6.7.2)
|
||||||
nokogiri (= 1.6.7.2)
|
|
||||||
nprogress-rails (~> 0.1.6.7)
|
nprogress-rails (~> 0.1.6.7)
|
||||||
oauth2 (~> 1.0.0)
|
oauth2 (~> 1.0.0)
|
||||||
octokit (~> 3.7.0)
|
octokit (~> 3.8.0)
|
||||||
omniauth (~> 1.2.2)
|
omniauth (~> 1.3.1)
|
||||||
omniauth-azure-oauth2 (~> 0.0.6)
|
omniauth-azure-oauth2 (~> 0.0.6)
|
||||||
omniauth-bitbucket (~> 0.0.2)
|
omniauth-bitbucket (~> 0.0.2)
|
||||||
omniauth-cas3 (~> 1.1.2)
|
omniauth-cas3 (~> 1.1.2)
|
||||||
|
@ -975,7 +974,7 @@ DEPENDENCIES
|
||||||
omniauth-gitlab (~> 1.0.0)
|
omniauth-gitlab (~> 1.0.0)
|
||||||
omniauth-google-oauth2 (~> 0.2.0)
|
omniauth-google-oauth2 (~> 0.2.0)
|
||||||
omniauth-kerberos (~> 0.3.0)
|
omniauth-kerberos (~> 0.3.0)
|
||||||
omniauth-saml (~> 1.4.0)
|
omniauth-saml (~> 1.4.2)
|
||||||
omniauth-shibboleth (~> 1.2.0)
|
omniauth-shibboleth (~> 1.2.0)
|
||||||
omniauth-twitter (~> 1.2.0)
|
omniauth-twitter (~> 1.2.0)
|
||||||
omniauth_crowd (~> 2.2.0)
|
omniauth_crowd (~> 2.2.0)
|
||||||
|
@ -988,7 +987,7 @@ DEPENDENCIES
|
||||||
rack-attack (~> 4.3.1)
|
rack-attack (~> 4.3.1)
|
||||||
rack-cors (~> 0.4.0)
|
rack-cors (~> 0.4.0)
|
||||||
rack-oauth2 (~> 1.2.1)
|
rack-oauth2 (~> 1.2.1)
|
||||||
rails (= 4.2.5.1)
|
rails (= 4.2.5.2)
|
||||||
rails-deprecated_sanitizer (~> 1.0.3)
|
rails-deprecated_sanitizer (~> 1.0.3)
|
||||||
raphael-rails (~> 2.1.2)
|
raphael-rails (~> 2.1.2)
|
||||||
rblineprof
|
rblineprof
|
||||||
|
@ -1010,7 +1009,7 @@ DEPENDENCIES
|
||||||
sdoc (~> 0.3.20)
|
sdoc (~> 0.3.20)
|
||||||
seed-fu (~> 2.3.5)
|
seed-fu (~> 2.3.5)
|
||||||
select2-rails (~> 3.5.9)
|
select2-rails (~> 3.5.9)
|
||||||
sentry-raven
|
sentry-raven (~> 0.15)
|
||||||
settingslogic (~> 2.0.9)
|
settingslogic (~> 2.0.9)
|
||||||
sham_rack
|
sham_rack
|
||||||
shoulda-matchers (~> 2.8.0)
|
shoulda-matchers (~> 2.8.0)
|
||||||
|
|
|
@ -68,7 +68,7 @@ GitLab is a Ruby on Rails application that runs on the following software:
|
||||||
|
|
||||||
- Ubuntu/Debian/CentOS/RHEL
|
- Ubuntu/Debian/CentOS/RHEL
|
||||||
- Ruby (MRI) 2.1
|
- Ruby (MRI) 2.1
|
||||||
- Git 1.7.10+
|
- Git 2.7.4+
|
||||||
- Redis 2.8+
|
- Redis 2.8+
|
||||||
- MySQL or PostgreSQL
|
- MySQL or PostgreSQL
|
||||||
|
|
||||||
|
|
3
Rakefile
3
Rakefile
|
@ -4,4 +4,7 @@
|
||||||
|
|
||||||
require File.expand_path('../config/application', __FILE__)
|
require File.expand_path('../config/application', __FILE__)
|
||||||
|
|
||||||
|
relative_url_conf = File.expand_path('../config/initializers/relative_url', __FILE__)
|
||||||
|
require relative_url_conf if File.exist?("#{relative_url_conf}.rb")
|
||||||
|
|
||||||
Gitlab::Application.load_tasks
|
Gitlab::Application.load_tasks
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
8.4.3
|
8.5.8
|
Binary file not shown.
Before Width: | Height: | Size: 813 KiB After Width: | Height: | Size: 257 KiB |
BIN
app/assets/images/emoji@2x.png
Normal file
BIN
app/assets/images/emoji@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 674 KiB |
|
@ -12,19 +12,6 @@ class @Admin
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
$('.js-toggle-colors-container').toggle()
|
$('.js-toggle-colors-container').toggle()
|
||||||
|
|
||||||
$('input#broadcast_message_color').on 'input', ->
|
|
||||||
previewColor = $(@).val()
|
|
||||||
$('div.broadcast-message-preview').css('background-color', previewColor)
|
|
||||||
|
|
||||||
$('input#broadcast_message_font').on 'input', ->
|
|
||||||
previewColor = $(@).val()
|
|
||||||
$('div.broadcast-message-preview').css('color', previewColor)
|
|
||||||
|
|
||||||
$('textarea#broadcast_message_message').on 'input', ->
|
|
||||||
previewMessage = $(@).val()
|
|
||||||
previewMessage = "Your message here" if previewMessage.trim() == ''
|
|
||||||
$('div.broadcast-message-preview span').text(previewMessage)
|
|
||||||
|
|
||||||
$('.log-tabs a').click (e) ->
|
$('.log-tabs a').click (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
$(this).tab('show')
|
$(this).tab('show')
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
callback(namespaces)
|
callback(namespaces)
|
||||||
|
|
||||||
# Return projects list. Filtered by query
|
# Return projects list. Filtered by query
|
||||||
projects: (query, callback) ->
|
projects: (query, order, callback) ->
|
||||||
url = Api.buildUrl(Api.projects_path)
|
url = Api.buildUrl(Api.projects_path)
|
||||||
|
|
||||||
$.ajax(
|
$.ajax(
|
||||||
|
@ -55,6 +55,7 @@
|
||||||
data:
|
data:
|
||||||
private_token: gon.api_token
|
private_token: gon.api_token
|
||||||
search: query
|
search: query
|
||||||
|
order_by: order
|
||||||
per_page: 20
|
per_page: 20
|
||||||
dataType: "json"
|
dataType: "json"
|
||||||
).done (projects) ->
|
).done (projects) ->
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
# the compiled file.
|
# the compiled file.
|
||||||
#
|
#
|
||||||
#= require jquery
|
#= require jquery
|
||||||
#= require jquery-ui
|
#= require jquery-ui/autocomplete
|
||||||
|
#= require jquery-ui/datepicker
|
||||||
|
#= require jquery-ui/effect-highlight
|
||||||
|
#= require jquery-ui/sortable
|
||||||
#= require jquery_ujs
|
#= require jquery_ujs
|
||||||
#= require jquery.cookie
|
#= require jquery.cookie
|
||||||
#= require jquery.endless-scroll
|
#= require jquery.endless-scroll
|
||||||
|
@ -21,9 +24,9 @@
|
||||||
#= require bootstrap
|
#= require bootstrap
|
||||||
#= require select2
|
#= require select2
|
||||||
#= require raphael
|
#= require raphael
|
||||||
#= require g.raphael-min
|
#= require g.raphael
|
||||||
#= require g.bar-min
|
#= require g.bar
|
||||||
#= require chart-lib.min
|
#= require Chart
|
||||||
#= require branch-graph
|
#= require branch-graph
|
||||||
#= require ace/ace
|
#= require ace/ace
|
||||||
#= require ace/ext-searchbox
|
#= require ace/ext-searchbox
|
||||||
|
@ -38,9 +41,9 @@
|
||||||
#= require shortcuts_dashboard_navigation
|
#= require shortcuts_dashboard_navigation
|
||||||
#= require shortcuts_issuable
|
#= require shortcuts_issuable
|
||||||
#= require shortcuts_network
|
#= require shortcuts_network
|
||||||
#= require jquery.nicescroll.min
|
#= require jquery.nicescroll
|
||||||
#= require_tree .
|
#= require_tree .
|
||||||
#= require fuzzaldrin-plus.min
|
#= require fuzzaldrin-plus
|
||||||
|
|
||||||
window.slugify = (text) ->
|
window.slugify = (text) ->
|
||||||
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
|
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
|
||||||
|
@ -203,4 +206,94 @@ $ ->
|
||||||
form = btn.closest("form")
|
form = btn.closest("form")
|
||||||
new ConfirmDangerModal(form, text)
|
new ConfirmDangerModal(form, text)
|
||||||
|
|
||||||
|
$('input[type="search"]').each ->
|
||||||
|
$this = $(this)
|
||||||
|
$this.attr 'value', $this.val()
|
||||||
|
return
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.off 'keyup', 'input[type="search"]'
|
||||||
|
.on 'keyup', 'input[type="search"]' , (e) ->
|
||||||
|
$this = $(this)
|
||||||
|
$this.attr 'value', $this.val()
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.off 'breakpoint:change'
|
||||||
|
.on 'breakpoint:change', (e, breakpoint) ->
|
||||||
|
if breakpoint is 'sm' or breakpoint is 'xs'
|
||||||
|
$gutterIcon = $('.gutter-toggle').find('i')
|
||||||
|
if $gutterIcon.hasClass('fa-angle-double-right')
|
||||||
|
$gutterIcon.closest('a').trigger('click')
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.off 'click', 'aside .gutter-toggle'
|
||||||
|
.on 'click', 'aside .gutter-toggle', (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
$this = $(this)
|
||||||
|
$thisIcon = $this.find 'i'
|
||||||
|
if $thisIcon.hasClass('fa-angle-double-right')
|
||||||
|
$thisIcon
|
||||||
|
.removeClass('fa-angle-double-right')
|
||||||
|
.addClass('fa-angle-double-left')
|
||||||
|
$this
|
||||||
|
.closest('aside')
|
||||||
|
.removeClass('right-sidebar-expanded')
|
||||||
|
.addClass('right-sidebar-collapsed')
|
||||||
|
$('.page-with-sidebar')
|
||||||
|
.removeClass('right-sidebar-expanded')
|
||||||
|
.addClass('right-sidebar-collapsed')
|
||||||
|
else
|
||||||
|
$thisIcon
|
||||||
|
.removeClass('fa-angle-double-left')
|
||||||
|
.addClass('fa-angle-double-right')
|
||||||
|
$this
|
||||||
|
.closest('aside')
|
||||||
|
.removeClass('right-sidebar-collapsed')
|
||||||
|
.addClass('right-sidebar-expanded')
|
||||||
|
$('.page-with-sidebar')
|
||||||
|
.removeClass('right-sidebar-collapsed')
|
||||||
|
.addClass('right-sidebar-expanded')
|
||||||
|
$.cookie("collapsed_gutter",
|
||||||
|
$('.right-sidebar')
|
||||||
|
.hasClass('right-sidebar-collapsed'), { path: '/' })
|
||||||
|
|
||||||
|
bootstrapBreakpoint = undefined;
|
||||||
|
checkBootstrapBreakpoints = ->
|
||||||
|
if $('.device-xs').is(':visible')
|
||||||
|
bootstrapBreakpoint = "xs"
|
||||||
|
else if $('.device-sm').is(':visible')
|
||||||
|
bootstrapBreakpoint = "sm"
|
||||||
|
else if $('.device-md').is(':visible')
|
||||||
|
bootstrapBreakpoint = "md"
|
||||||
|
else if $('.device-lg').is(':visible')
|
||||||
|
bootstrapBreakpoint = "lg"
|
||||||
|
|
||||||
|
setBootstrapBreakpoints = ->
|
||||||
|
if $('.device-xs').length
|
||||||
|
return
|
||||||
|
|
||||||
|
$("body")
|
||||||
|
.append('<div class="device-xs visible-xs"></div>'+
|
||||||
|
'<div class="device-sm visible-sm"></div>'+
|
||||||
|
'<div class="device-md visible-md"></div>'+
|
||||||
|
'<div class="device-lg visible-lg"></div>')
|
||||||
|
checkBootstrapBreakpoints()
|
||||||
|
|
||||||
|
fitSidebarForSize = ->
|
||||||
|
oldBootstrapBreakpoint = bootstrapBreakpoint
|
||||||
|
checkBootstrapBreakpoints()
|
||||||
|
if bootstrapBreakpoint != oldBootstrapBreakpoint
|
||||||
|
$(document).trigger('breakpoint:change', [bootstrapBreakpoint])
|
||||||
|
|
||||||
|
checkInitialSidebarSize = ->
|
||||||
|
if bootstrapBreakpoint is "xs" or "sm"
|
||||||
|
$(document).trigger('breakpoint:change', [bootstrapBreakpoint])
|
||||||
|
|
||||||
|
$(window)
|
||||||
|
.off "resize"
|
||||||
|
.on "resize", (e) ->
|
||||||
|
fitSidebarForSize()
|
||||||
|
|
||||||
|
setBootstrapBreakpoints()
|
||||||
|
checkInitialSidebarSize()
|
||||||
new Aside()
|
new Aside()
|
||||||
|
|
|
@ -4,6 +4,7 @@ class @AwardsHandler
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
$(".emoji-menu").show()
|
$(".emoji-menu").show()
|
||||||
|
$("#emoji_search").focus()
|
||||||
|
|
||||||
$("html").on 'click', (event) ->
|
$("html").on 'click', (event) ->
|
||||||
if !$(event.target).closest(".emoji-menu").length
|
if !$(event.target).closest(".emoji-menu").length
|
||||||
|
@ -48,10 +49,11 @@ class @AwardsHandler
|
||||||
counter.text(parseInt(counter.text()) - 1)
|
counter.text(parseInt(counter.text()) - 1)
|
||||||
emojiIcon.removeClass("active")
|
emojiIcon.removeClass("active")
|
||||||
@removeMeFromAuthorList(emoji)
|
@removeMeFromAuthorList(emoji)
|
||||||
else if emoji =="thumbsup" || emoji == "thumbsdown"
|
else if emoji == "thumbsup" || emoji == "thumbsdown"
|
||||||
emojiIcon.tooltip("destroy")
|
emojiIcon.tooltip("destroy")
|
||||||
counter.text(0)
|
counter.text(0)
|
||||||
emojiIcon.removeClass("active")
|
emojiIcon.removeClass("active")
|
||||||
|
@removeMeFromAuthorList(emoji)
|
||||||
else
|
else
|
||||||
emojiIcon.tooltip("destroy")
|
emojiIcon.tooltip("destroy")
|
||||||
emojiIcon.remove()
|
emojiIcon.remove()
|
||||||
|
|
22
app/assets/javascripts/broadcast_message.js.coffee
Normal file
22
app/assets/javascripts/broadcast_message.js.coffee
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
$ ->
|
||||||
|
$('input#broadcast_message_color').on 'input', ->
|
||||||
|
previewColor = $(@).val()
|
||||||
|
$('div.broadcast-message-preview').css('background-color', previewColor)
|
||||||
|
|
||||||
|
$('input#broadcast_message_font').on 'input', ->
|
||||||
|
previewColor = $(@).val()
|
||||||
|
$('div.broadcast-message-preview').css('color', previewColor)
|
||||||
|
|
||||||
|
previewPath = $('textarea#broadcast_message_message').data('preview-path')
|
||||||
|
|
||||||
|
$('textarea#broadcast_message_message').on 'input', ->
|
||||||
|
message = $(@).val()
|
||||||
|
|
||||||
|
if message == ''
|
||||||
|
$('.js-broadcast-message-preview').text("Your message here")
|
||||||
|
else
|
||||||
|
$.ajax(
|
||||||
|
url: previewPath
|
||||||
|
type: "POST"
|
||||||
|
data: { broadcast_message: { message: message } }
|
||||||
|
)
|
|
@ -1,3 +1,31 @@
|
||||||
class @Dashboard
|
@Dashboard =
|
||||||
constructor: ->
|
init: ->
|
||||||
new ProjectsList()
|
$(".projects-list-filter").off('keyup')
|
||||||
|
this.initSearch()
|
||||||
|
|
||||||
|
initSearch: ->
|
||||||
|
@timer = null
|
||||||
|
$(".projects-list-filter").on('keyup', ->
|
||||||
|
clearTimeout(@timer)
|
||||||
|
@timer = setTimeout(Dashboard.filterResults, 500)
|
||||||
|
)
|
||||||
|
|
||||||
|
filterResults: =>
|
||||||
|
$('.projects-list-holder').fadeTo(250, 0.5)
|
||||||
|
|
||||||
|
form = null
|
||||||
|
form = $("form#project-filter-form")
|
||||||
|
search = $(".projects-list-filter").val()
|
||||||
|
project_filter_url = form.attr('action') + '?' + form.serialize()
|
||||||
|
|
||||||
|
$.ajax
|
||||||
|
type: "GET"
|
||||||
|
url: form.attr('action')
|
||||||
|
data: form.serialize()
|
||||||
|
complete: ->
|
||||||
|
$('.projects-list-holder').fadeTo(250, 1)
|
||||||
|
success: (data) ->
|
||||||
|
$('.projects-list-holder').replaceWith(data.html)
|
||||||
|
# Change url so if user reload a page - search results are saved
|
||||||
|
history.replaceState {page: project_filter_url}, document.title, project_filter_url
|
||||||
|
dataType: "json"
|
||||||
|
|
|
@ -16,6 +16,8 @@ class Dispatcher
|
||||||
shortcut_handler = null
|
shortcut_handler = null
|
||||||
|
|
||||||
switch page
|
switch page
|
||||||
|
when 'explore:projects:index', 'explore:projects:starred', 'explore:projects:trending'
|
||||||
|
Dashboard.init()
|
||||||
when 'projects:issues:index'
|
when 'projects:issues:index'
|
||||||
Issues.init()
|
Issues.init()
|
||||||
shortcut_handler = new ShortcutsNavigation()
|
shortcut_handler = new ShortcutsNavigation()
|
||||||
|
@ -58,7 +60,7 @@ class Dispatcher
|
||||||
shortcut_handler = new ShortcutsNavigation()
|
shortcut_handler = new ShortcutsNavigation()
|
||||||
MergeRequests.init()
|
MergeRequests.init()
|
||||||
when 'dashboard:show', 'root:show'
|
when 'dashboard:show', 'root:show'
|
||||||
new Dashboard()
|
Dashboard.init()
|
||||||
when 'dashboard:activity'
|
when 'dashboard:activity'
|
||||||
new Activities()
|
new Activities()
|
||||||
when 'dashboard:projects:starred'
|
when 'dashboard:projects:starred'
|
||||||
|
@ -86,6 +88,7 @@ class Dispatcher
|
||||||
when 'groups:new', 'groups:edit', 'admin:groups:edit', 'admin:groups:new'
|
when 'groups:new', 'groups:edit', 'admin:groups:edit', 'admin:groups:new'
|
||||||
new GroupAvatar()
|
new GroupAvatar()
|
||||||
when 'projects:tree:show'
|
when 'projects:tree:show'
|
||||||
|
shortcut_handler = new ShortcutsNavigation()
|
||||||
new TreeView()
|
new TreeView()
|
||||||
when 'projects:find_file:show'
|
when 'projects:find_file:show'
|
||||||
shortcut_handler = true
|
shortcut_handler = true
|
||||||
|
|
|
@ -65,8 +65,7 @@ class @DropzoneInput
|
||||||
return
|
return
|
||||||
|
|
||||||
success: (header, response) ->
|
success: (header, response) ->
|
||||||
child = $(dropzone[0]).children("textarea")
|
pasteText response.link.markdown
|
||||||
$(child).val $(child).val() + response.link.markdown + "\n"
|
|
||||||
return
|
return
|
||||||
|
|
||||||
error: (temp, errorMessage) ->
|
error: (temp, errorMessage) ->
|
||||||
|
@ -128,6 +127,7 @@ class @DropzoneInput
|
||||||
beforeSelection = $(child).val().substring 0, caretStart
|
beforeSelection = $(child).val().substring 0, caretStart
|
||||||
afterSelection = $(child).val().substring caretEnd, textEnd
|
afterSelection = $(child).val().substring caretEnd, textEnd
|
||||||
$(child).val beforeSelection + text + afterSelection
|
$(child).val beforeSelection + text + afterSelection
|
||||||
|
child.get(0).setSelectionRange caretStart + text.length, caretEnd + text.length
|
||||||
form_textarea.trigger "input"
|
form_textarea.trigger "input"
|
||||||
|
|
||||||
getFilename = (e) ->
|
getFilename = (e) ->
|
||||||
|
|
|
@ -10,20 +10,10 @@ class @IssuableContext
|
||||||
$(".issuable-sidebar .inline-update").on "change", ".js-assignee", ->
|
$(".issuable-sidebar .inline-update").on "change", ".js-assignee", ->
|
||||||
$(this).submit()
|
$(this).submit()
|
||||||
|
|
||||||
$('.issuable-details').waitForImages ->
|
$(document).on "click",".edit-link", (e) ->
|
||||||
$('.issuable-affix').on 'affix.bs.affix', ->
|
|
||||||
$(@).width($(@).outerWidth())
|
|
||||||
.on 'affixed-top.bs.affix affixed-bottom.bs.affix', ->
|
|
||||||
$(@).width('')
|
|
||||||
|
|
||||||
$('.issuable-affix').affix offset:
|
|
||||||
top: ->
|
|
||||||
@top = ($('.issuable-affix').offset().top - 70)
|
|
||||||
bottom: ->
|
|
||||||
@bottom = $('.footer').outerHeight(true)
|
|
||||||
|
|
||||||
$(".edit-link").click (e) ->
|
|
||||||
block = $(@).parents('.block')
|
block = $(@).parents('.block')
|
||||||
block.find('.selectbox').show()
|
block.find('.selectbox').show()
|
||||||
block.find('.value').hide()
|
block.find('.value').hide()
|
||||||
block.find('.js-select2').select2("open")
|
block.find('.js-select2').select2("open")
|
||||||
|
|
||||||
|
$(".right-sidebar").niceScroll()
|
||||||
|
|
|
@ -50,6 +50,7 @@ class @Issue
|
||||||
new Flash(issueFailMessage, 'alert')
|
new Flash(issueFailMessage, 'alert')
|
||||||
success: (data, textStatus, jqXHR) ->
|
success: (data, textStatus, jqXHR) ->
|
||||||
if data.saved
|
if data.saved
|
||||||
|
$(document).trigger('issuable:change');
|
||||||
if isClose
|
if isClose
|
||||||
$('a.btn-close').addClass('hidden')
|
$('a.btn-close').addClass('hidden')
|
||||||
$('a.btn-reopen').removeClass('hidden')
|
$('a.btn-reopen').removeClass('hidden')
|
||||||
|
|
|
@ -42,3 +42,9 @@ work = ->
|
||||||
|
|
||||||
$(document).on('page:fetch', start)
|
$(document).on('page:fetch', start)
|
||||||
$(document).on('page:change', stop)
|
$(document).on('page:change', stop)
|
||||||
|
|
||||||
|
$ ->
|
||||||
|
# Make logo clickable as part of a workaround for Safari visited
|
||||||
|
# link behaviour (See !2690).
|
||||||
|
$('#logo').on 'click', ->
|
||||||
|
$('#js-shortcuts-home').get(0).click()
|
||||||
|
|
|
@ -146,6 +146,7 @@ class @MergeRequestTabs
|
||||||
success: (data) =>
|
success: (data) =>
|
||||||
document.querySelector("div#diffs").innerHTML = data.html
|
document.querySelector("div#diffs").innerHTML = data.html
|
||||||
$('div#diffs .js-syntax-highlight').syntaxHighlight()
|
$('div#diffs .js-syntax-highlight').syntaxHighlight()
|
||||||
|
@expandViewContainer() if @diffViewType() is 'parallel'
|
||||||
@diffsLoaded = true
|
@diffsLoaded = true
|
||||||
@scrollToElement("#diffs")
|
@scrollToElement("#diffs")
|
||||||
|
|
||||||
|
@ -177,3 +178,10 @@ class @MergeRequestTabs
|
||||||
options = $.extend({}, defaults, options)
|
options = $.extend({}, defaults, options)
|
||||||
|
|
||||||
$.ajax(options)
|
$.ajax(options)
|
||||||
|
|
||||||
|
# Returns diff view type
|
||||||
|
diffViewType: ->
|
||||||
|
$('.inline-parallel-buttons a.active').data('view-type')
|
||||||
|
|
||||||
|
expandViewContainer: ->
|
||||||
|
$('.container-fluid').removeClass('container-limited')
|
||||||
|
|
|
@ -62,14 +62,24 @@ class @Milestone
|
||||||
dataType: "json"
|
dataType: "json"
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
|
oldMouseStart = $.ui.sortable.prototype._mouseStart
|
||||||
|
$.ui.sortable.prototype._mouseStart = (event, overrideHandle, noActivation) ->
|
||||||
|
this._trigger "beforeStart", event, this._uiHash()
|
||||||
|
oldMouseStart.apply this, [event, overrideHandle, noActivation]
|
||||||
|
|
||||||
@bindIssuesSorting()
|
@bindIssuesSorting()
|
||||||
@bindMergeRequestSorting()
|
@bindMergeRequestSorting()
|
||||||
|
@bindTabsSwitching
|
||||||
|
|
||||||
bindIssuesSorting: ->
|
bindIssuesSorting: ->
|
||||||
$("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable(
|
$("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable(
|
||||||
connectWith: ".issues-sortable-list",
|
connectWith: ".issues-sortable-list",
|
||||||
dropOnEmpty: true,
|
dropOnEmpty: true,
|
||||||
items: "li:not(.ui-sort-disabled)",
|
items: "li:not(.ui-sort-disabled)",
|
||||||
|
beforeStart: (event, ui) ->
|
||||||
|
$(".issues-sortable-list").css "min-height", ui.item.outerHeight()
|
||||||
|
stop: (event, ui) ->
|
||||||
|
$(".issues-sortable-list").css "min-height", "0px"
|
||||||
update: (event, ui) ->
|
update: (event, ui) ->
|
||||||
data = $(this).sortable("serialize")
|
data = $(this).sortable("serialize")
|
||||||
Milestone.sortIssues(data)
|
Milestone.sortIssues(data)
|
||||||
|
@ -95,10 +105,22 @@ class @Milestone
|
||||||
).disableSelection()
|
).disableSelection()
|
||||||
|
|
||||||
bindMergeRequestSorting: ->
|
bindMergeRequestSorting: ->
|
||||||
|
$('a[data-toggle="tab"]').on 'show.bs.tab', (e) ->
|
||||||
|
currentTabClass = $(e.target).data('show')
|
||||||
|
previousTabClass = $(e.relatedTarget).data('show')
|
||||||
|
|
||||||
|
$(previousTabClass).hide()
|
||||||
|
$(currentTabClass).removeClass('hidden')
|
||||||
|
$(currentTabClass).show()
|
||||||
|
|
||||||
$("#merge_requests-list-unassigned, #merge_requests-list-ongoing, #merge_requests-list-closed").sortable(
|
$("#merge_requests-list-unassigned, #merge_requests-list-ongoing, #merge_requests-list-closed").sortable(
|
||||||
connectWith: ".merge_requests-sortable-list",
|
connectWith: ".merge_requests-sortable-list",
|
||||||
dropOnEmpty: true,
|
dropOnEmpty: true,
|
||||||
items: "li:not(.ui-sort-disabled)",
|
items: "li:not(.ui-sort-disabled)",
|
||||||
|
beforeStart: (event, ui) ->
|
||||||
|
$(".merge_requests-sortable-list").css "min-height", ui.item.outerHeight()
|
||||||
|
stop: (event, ui) ->
|
||||||
|
$(".merge_requests-sortable-list").css "min-height", "0px"
|
||||||
update: (event, ui) ->
|
update: (event, ui) ->
|
||||||
data = $(this).sortable("serialize")
|
data = $(this).sortable("serialize")
|
||||||
Milestone.sortMergeRequests(data)
|
Milestone.sortMergeRequests(data)
|
||||||
|
|
|
@ -15,6 +15,8 @@ class @Notes
|
||||||
@last_fetched_at = last_fetched_at
|
@last_fetched_at = last_fetched_at
|
||||||
@view = view
|
@view = view
|
||||||
@noteable_url = document.URL
|
@noteable_url = document.URL
|
||||||
|
@notesCountBadge ||= $(".issuable-details").find(".notes-tab .badge")
|
||||||
|
|
||||||
@initRefresh()
|
@initRefresh()
|
||||||
@setupMainTargetNoteForm()
|
@setupMainTargetNoteForm()
|
||||||
@cleanBinding()
|
@cleanBinding()
|
||||||
|
@ -62,6 +64,9 @@ class @Notes
|
||||||
# fetch notes when tab becomes visible
|
# fetch notes when tab becomes visible
|
||||||
$(document).on "visibilitychange", @visibilityChange
|
$(document).on "visibilitychange", @visibilityChange
|
||||||
|
|
||||||
|
# when issue status changes, we need to refresh data
|
||||||
|
$(document).on "issuable:change", @refresh
|
||||||
|
|
||||||
cleanBinding: ->
|
cleanBinding: ->
|
||||||
$(document).off "ajax:success", ".js-main-target-form"
|
$(document).off "ajax:success", ".js-main-target-form"
|
||||||
$(document).off "ajax:success", ".js-discussion-note-form"
|
$(document).off "ajax:success", ".js-discussion-note-form"
|
||||||
|
@ -89,7 +94,7 @@ class @Notes
|
||||||
, 15000
|
, 15000
|
||||||
|
|
||||||
refresh: ->
|
refresh: ->
|
||||||
unless document.hidden or (@noteable_url != document.URL)
|
if not document.hidden and document.URL.indexOf(@noteable_url) is 0
|
||||||
@getContent()
|
@getContent()
|
||||||
|
|
||||||
getContent: ->
|
getContent: ->
|
||||||
|
@ -101,7 +106,10 @@ class @Notes
|
||||||
notes = data.notes
|
notes = data.notes
|
||||||
@last_fetched_at = data.last_fetched_at
|
@last_fetched_at = data.last_fetched_at
|
||||||
$.each notes, (i, note) =>
|
$.each notes, (i, note) =>
|
||||||
@renderNote(note)
|
if note.discussion_with_diff_html?
|
||||||
|
@renderDiscussionNote(note)
|
||||||
|
else
|
||||||
|
@renderNote(note)
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
@ -116,19 +124,22 @@ class @Notes
|
||||||
flash.pinTo('.header-content')
|
flash.pinTo('.header-content')
|
||||||
return
|
return
|
||||||
|
|
||||||
# render note if it not present in loaded list
|
|
||||||
# or skip if rendered
|
|
||||||
if @isNewNote(note) && !note.award
|
|
||||||
@note_ids.push(note.id)
|
|
||||||
$('ul.main-notes-list').
|
|
||||||
append(note.html).
|
|
||||||
syntaxHighlight()
|
|
||||||
@initTaskList()
|
|
||||||
|
|
||||||
if note.award
|
if note.award
|
||||||
awards_handler.addAwardToEmojiBar(note.note)
|
awards_handler.addAwardToEmojiBar(note.note)
|
||||||
awards_handler.scrollToAwards()
|
awards_handler.scrollToAwards()
|
||||||
|
|
||||||
|
# render note if it not present in loaded list
|
||||||
|
# or skip if rendered
|
||||||
|
else if @isNewNote(note)
|
||||||
|
@note_ids.push(note.id)
|
||||||
|
|
||||||
|
$('ul.main-notes-list')
|
||||||
|
.append(note.html)
|
||||||
|
.syntaxHighlight()
|
||||||
|
@initTaskList()
|
||||||
|
@updateNotesCount(1)
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
Check if note does not exists on page
|
Check if note does not exists on page
|
||||||
###
|
###
|
||||||
|
@ -144,34 +155,39 @@ class @Notes
|
||||||
Note: for rendering inline notes use renderDiscussionNote
|
Note: for rendering inline notes use renderDiscussionNote
|
||||||
###
|
###
|
||||||
renderDiscussionNote: (note) ->
|
renderDiscussionNote: (note) ->
|
||||||
|
return unless @isNewNote(note)
|
||||||
|
|
||||||
@note_ids.push(note.id)
|
@note_ids.push(note.id)
|
||||||
form = $("form[rel='" + note.discussion_id + "']")
|
form = $("#new-discussion-note-form-#{note.discussion_id}")
|
||||||
row = form.closest("tr")
|
row = form.closest("tr")
|
||||||
note_html = $(note.html)
|
note_html = $(note.html)
|
||||||
note_html.syntaxHighlight()
|
note_html.syntaxHighlight()
|
||||||
|
|
||||||
# is this the first note of discussion?
|
# is this the first note of discussion?
|
||||||
if row.is(".js-temp-notes-holder")
|
discussionContainer = $(".notes[data-discussion-id='" + note.discussion_id + "']")
|
||||||
|
if discussionContainer.length is 0
|
||||||
# insert the note and the reply button after the temp row
|
# insert the note and the reply button after the temp row
|
||||||
row.after note.discussion_html
|
row.after note.discussion_html
|
||||||
|
|
||||||
# remove the note (will be added again below)
|
# remove the note (will be added again below)
|
||||||
row.next().find(".note").remove()
|
row.next().find(".note").remove()
|
||||||
|
|
||||||
|
# Before that, the container didn't exist
|
||||||
|
discussionContainer = $(".notes[data-discussion-id='" + note.discussion_id + "']")
|
||||||
|
|
||||||
# Add note to 'Changes' page discussions
|
# Add note to 'Changes' page discussions
|
||||||
$(".notes[rel='" + note.discussion_id + "']").append note_html
|
discussionContainer.append note_html
|
||||||
|
|
||||||
# Init discussion on 'Discussion' page if it is merge request page
|
# Init discussion on 'Discussion' page if it is merge request page
|
||||||
if $('body').attr('data-page').indexOf('projects:merge_request') == 0
|
if $('body').attr('data-page').indexOf('projects:merge_request') is 0
|
||||||
discussion_html = $(note.discussion_with_diff_html)
|
$('ul.main-notes-list')
|
||||||
discussion_html.syntaxHighlight()
|
.append(note.discussion_with_diff_html)
|
||||||
$('ul.main-notes-list').append(discussion_html)
|
.syntaxHighlight()
|
||||||
else
|
else
|
||||||
# append new note to all matching discussions
|
# append new note to all matching discussions
|
||||||
$(".notes[rel='" + note.discussion_id + "']").append note_html
|
discussionContainer.append note_html
|
||||||
|
|
||||||
# cleanup after successfully creating a diff/discussion note
|
@updateNotesCount(1)
|
||||||
@removeDiscussionNoteForm(form)
|
|
||||||
|
|
||||||
###
|
###
|
||||||
Called in response the main target form has been successfully submitted.
|
Called in response the main target form has been successfully submitted.
|
||||||
|
@ -278,6 +294,9 @@ class @Notes
|
||||||
addDiscussionNote: (xhr, note, status) =>
|
addDiscussionNote: (xhr, note, status) =>
|
||||||
@renderDiscussionNote(note)
|
@renderDiscussionNote(note)
|
||||||
|
|
||||||
|
# cleanup after successfully creating a diff/discussion note
|
||||||
|
@removeDiscussionNoteForm($("#new-discussion-note-form-#{note.discussion_id}"))
|
||||||
|
|
||||||
###
|
###
|
||||||
Called in response to the edit note form being submitted
|
Called in response to the edit note form being submitted
|
||||||
|
|
||||||
|
@ -320,6 +339,7 @@ class @Notes
|
||||||
form.show()
|
form.show()
|
||||||
textarea = form.find("textarea")
|
textarea = form.find("textarea")
|
||||||
textarea.focus()
|
textarea.focus()
|
||||||
|
autosize(textarea)
|
||||||
|
|
||||||
# HACK (rspeicher/DouweM): Work around a Chrome 43 bug(?).
|
# HACK (rspeicher/DouweM): Work around a Chrome 43 bug(?).
|
||||||
# The textarea has the correct value, Chrome just won't show it unless we
|
# The textarea has the correct value, Chrome just won't show it unless we
|
||||||
|
@ -348,30 +368,32 @@ class @Notes
|
||||||
Removes the actual note from view.
|
Removes the actual note from view.
|
||||||
Removes the whole discussion if the last note is being removed.
|
Removes the whole discussion if the last note is being removed.
|
||||||
###
|
###
|
||||||
removeNote: ->
|
removeNote: (e) =>
|
||||||
note = $(this).closest(".note")
|
noteId = $(e.currentTarget)
|
||||||
note_id = note.attr('id')
|
.closest(".note")
|
||||||
|
.attr("id")
|
||||||
|
|
||||||
$('.note[id="' + note_id + '"]').each ->
|
# A same note appears in the "Discussion" and in the "Changes" tab, we have
|
||||||
note = $(this)
|
# to remove all. Using $(".note[id='noteId']") ensure we get all the notes,
|
||||||
|
# where $("#noteId") would return only one.
|
||||||
|
$(".note[id='#{noteId}']").each (i, el) =>
|
||||||
|
note = $(el)
|
||||||
notes = note.closest(".notes")
|
notes = note.closest(".notes")
|
||||||
count = notes.closest(".issuable-details").find(".notes-tab .badge")
|
|
||||||
|
|
||||||
# check if this is the last note for this line
|
# check if this is the last note for this line
|
||||||
if notes.find(".note").length is 1
|
if notes.find(".note").length is 1
|
||||||
|
|
||||||
# for discussions
|
# "Discussions" tab
|
||||||
notes.closest(".discussion").remove()
|
notes.closest(".timeline-entry").remove()
|
||||||
|
|
||||||
# for diff lines
|
# "Changes" tab / commit view
|
||||||
notes.closest("tr").remove()
|
notes.closest("tr").remove()
|
||||||
|
|
||||||
# update notes count
|
|
||||||
oldNum = parseInt(count.text())
|
|
||||||
count.text(oldNum - 1)
|
|
||||||
|
|
||||||
note.remove()
|
note.remove()
|
||||||
|
|
||||||
|
# Decrement the "Discussions" counter only once
|
||||||
|
@updateNotesCount(-1)
|
||||||
|
|
||||||
###
|
###
|
||||||
Called in response to clicking the delete attachment link
|
Called in response to clicking the delete attachment link
|
||||||
|
|
||||||
|
@ -411,7 +433,7 @@ class @Notes
|
||||||
###
|
###
|
||||||
setupDiscussionNoteForm: (dataHolder, form) =>
|
setupDiscussionNoteForm: (dataHolder, form) =>
|
||||||
# setup note target
|
# setup note target
|
||||||
form.attr "rel", dataHolder.data("discussionId")
|
form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}"
|
||||||
form.find("#line_type").val dataHolder.data("lineType")
|
form.find("#line_type").val dataHolder.data("lineType")
|
||||||
form.find("#note_commit_id").val dataHolder.data("commitId")
|
form.find("#note_commit_id").val dataHolder.data("commitId")
|
||||||
form.find("#note_line_code").val dataHolder.data("lineCode")
|
form.find("#note_line_code").val dataHolder.data("lineCode")
|
||||||
|
@ -541,3 +563,6 @@ class @Notes
|
||||||
|
|
||||||
updateTaskList: ->
|
updateTaskList: ->
|
||||||
$('form', this).submit()
|
$('form', this).submit()
|
||||||
|
|
||||||
|
updateNotesCount: (updateCount) ->
|
||||||
|
@notesCountBadge.text(parseInt(@notesCountBadge.text()) + updateCount)
|
||||||
|
|
|
@ -50,3 +50,19 @@ class @Project
|
||||||
$('#notifications-button').empty().append("<i class='fa fa-bell'></i>" + label + "<i class='fa fa-angle-down'></i>")
|
$('#notifications-button').empty().append("<i class='fa fa-bell'></i>" + label + "<i class='fa fa-angle-down'></i>")
|
||||||
$(@).parents('ul').find('li.active').removeClass 'active'
|
$(@).parents('ul').find('li.active').removeClass 'active'
|
||||||
$(@).parent().addClass 'active'
|
$(@).parent().addClass 'active'
|
||||||
|
|
||||||
|
@projectSelectDropdown()
|
||||||
|
|
||||||
|
projectSelectDropdown: ->
|
||||||
|
new ProjectSelect()
|
||||||
|
|
||||||
|
$('.project-item-select').on 'click', (e) =>
|
||||||
|
@changeProject $(e.currentTarget).val()
|
||||||
|
|
||||||
|
$('.js-projects-dropdown-toggle').on 'click', (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
$('.js-projects-dropdown').select2('open')
|
||||||
|
|
||||||
|
changeProject: (url) ->
|
||||||
|
window.location = url
|
||||||
|
|
|
@ -3,6 +3,7 @@ class @ProjectSelect
|
||||||
$('.ajax-project-select').each (i, select) ->
|
$('.ajax-project-select').each (i, select) ->
|
||||||
@groupId = $(select).data('group-id')
|
@groupId = $(select).data('group-id')
|
||||||
@includeGroups = $(select).data('include-groups')
|
@includeGroups = $(select).data('include-groups')
|
||||||
|
@orderBy = $(select).data('order-by') || 'id'
|
||||||
|
|
||||||
placeholder = "Search for project"
|
placeholder = "Search for project"
|
||||||
placeholder += " or group" if @includeGroups
|
placeholder += " or group" if @includeGroups
|
||||||
|
@ -28,7 +29,7 @@ class @ProjectSelect
|
||||||
if @groupId
|
if @groupId
|
||||||
Api.groupProjects @groupId, query.term, projectsCallback
|
Api.groupProjects @groupId, query.term, projectsCallback
|
||||||
else
|
else
|
||||||
Api.projects query.term, projectsCallback
|
Api.projects query.term, @orderBy, projectsCallback
|
||||||
|
|
||||||
id: (project) ->
|
id: (project) ->
|
||||||
project.web_url
|
project.web_url
|
||||||
|
|
|
@ -2,23 +2,31 @@ class @ProjectsList
|
||||||
constructor: ->
|
constructor: ->
|
||||||
$(".projects-list .js-expand").on 'click', (e) ->
|
$(".projects-list .js-expand").on 'click', (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
list = $(this).closest('.projects-list')
|
$projectsList = $(this).closest('.projects-list')
|
||||||
list.find("li").show()
|
ProjectsList.showPagination($projectsList)
|
||||||
list.find("li.bottom").hide()
|
$projectsList.find('li.bottom').hide()
|
||||||
|
|
||||||
$(".projects-list-filter").keyup ->
|
$("#filter_projects").on 'keyup', ->
|
||||||
terms = $(this).val()
|
ProjectsList.filter_results($("#filter_projects"))
|
||||||
uiBox = $('div.projects-list-holder')
|
|
||||||
if terms == "" || terms == undefined
|
|
||||||
uiBox.find("ul.projects-list li").show()
|
|
||||||
else
|
|
||||||
uiBox.find("ul.projects-list li").each (index) ->
|
|
||||||
name = $(this).find("span.filter-title").text()
|
|
||||||
|
|
||||||
if name.toLowerCase().search(terms.toLowerCase()) == -1
|
@showPagination: ($projectsList) ->
|
||||||
$(this).hide()
|
$projectsList.find('li').show()
|
||||||
else
|
$('.gl-pagination').show()
|
||||||
$(this).show()
|
|
||||||
uiBox.find("ul.projects-list li.bottom").hide()
|
|
||||||
|
|
||||||
|
@filter_results: ($element) ->
|
||||||
|
terms = $element.val()
|
||||||
|
filterSelector = $element.data('filter-selector') || 'span.filter-title'
|
||||||
|
$projectsList = $('.projects-list')
|
||||||
|
|
||||||
|
if not terms
|
||||||
|
ProjectsList.showPagination($projectsList)
|
||||||
|
else
|
||||||
|
$projectsList.find('li').each (index) ->
|
||||||
|
$this = $(this)
|
||||||
|
name = $this.find(filterSelector).text()
|
||||||
|
|
||||||
|
if name.toLowerCase().indexOf(terms.toLowerCase()) == -1
|
||||||
|
$this.hide()
|
||||||
|
else
|
||||||
|
$this.show()
|
||||||
|
$('.gl-pagination').hide()
|
||||||
|
|
|
@ -13,8 +13,10 @@ class @Shortcuts
|
||||||
if $('#modal-shortcuts').length > 0
|
if $('#modal-shortcuts').length > 0
|
||||||
$('#modal-shortcuts').modal('show')
|
$('#modal-shortcuts').modal('show')
|
||||||
else
|
else
|
||||||
|
url = '/help/shortcuts'
|
||||||
|
url = gon.relative_url_root + url if gon.relative_url_root?
|
||||||
$.ajax(
|
$.ajax(
|
||||||
url: '/help/shortcuts',
|
url: url,
|
||||||
dataType: 'script',
|
dataType: 'script',
|
||||||
success: (e) ->
|
success: (e) ->
|
||||||
if location and location.length > 0
|
if location and location.length > 0
|
||||||
|
|
|
@ -5,23 +5,42 @@ class @ShortcutsIssuable extends ShortcutsNavigation
|
||||||
constructor: (isMergeRequest) ->
|
constructor: (isMergeRequest) ->
|
||||||
super()
|
super()
|
||||||
Mousetrap.bind('a', ->
|
Mousetrap.bind('a', ->
|
||||||
$('.js-assignee').select2('open')
|
$('.block.assignee .edit-link').trigger('click')
|
||||||
return false
|
return false
|
||||||
)
|
)
|
||||||
Mousetrap.bind('m', ->
|
Mousetrap.bind('m', ->
|
||||||
$('.js-milestone').select2('open')
|
$('.block.milestone .edit-link').trigger('click')
|
||||||
return false
|
return false
|
||||||
)
|
)
|
||||||
Mousetrap.bind('r', =>
|
Mousetrap.bind('r', =>
|
||||||
@replyWithSelectedText()
|
@replyWithSelectedText()
|
||||||
return false
|
return false
|
||||||
)
|
)
|
||||||
|
Mousetrap.bind('j', =>
|
||||||
|
@prevIssue()
|
||||||
|
return false
|
||||||
|
)
|
||||||
|
Mousetrap.bind('k', =>
|
||||||
|
@nextIssue()
|
||||||
|
return false
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if isMergeRequest
|
if isMergeRequest
|
||||||
@enabledHelp.push('.hidden-shortcut.merge_requests')
|
@enabledHelp.push('.hidden-shortcut.merge_requests')
|
||||||
else
|
else
|
||||||
@enabledHelp.push('.hidden-shortcut.issues')
|
@enabledHelp.push('.hidden-shortcut.issues')
|
||||||
|
|
||||||
|
prevIssue: ->
|
||||||
|
$prevBtn = $('.prev-btn')
|
||||||
|
if not $prevBtn.hasClass('disabled')
|
||||||
|
Turbolinks.visit($prevBtn.attr('href'))
|
||||||
|
|
||||||
|
nextIssue: ->
|
||||||
|
$nextBtn = $('.next-btn')
|
||||||
|
if not $nextBtn.hasClass('disabled')
|
||||||
|
Turbolinks.visit($nextBtn.attr('href'))
|
||||||
|
|
||||||
replyWithSelectedText: ->
|
replyWithSelectedText: ->
|
||||||
if window.getSelection
|
if window.getSelection
|
||||||
selected = window.getSelection().toString()
|
selected = window.getSelection().toString()
|
||||||
|
|
|
@ -8,4 +8,10 @@ $(document).on("click", '.toggle-nav-collapse', (e) ->
|
||||||
$('.sidebar-wrapper').toggleClass("sidebar-collapsed sidebar-expanded")
|
$('.sidebar-wrapper').toggleClass("sidebar-collapsed sidebar-expanded")
|
||||||
$('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
|
$('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
|
||||||
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
|
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
|
||||||
|
|
||||||
|
setTimeout ( ->
|
||||||
|
niceScrollBars = $('.nicescroll').niceScroll();
|
||||||
|
niceScrollBars.updateScrollBar();
|
||||||
|
), 300
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
class @Wikis
|
class @Wikis
|
||||||
constructor: ->
|
constructor: ->
|
||||||
$('.build-new-wiki').bind 'click', (e) =>
|
$('.new-wiki-page').on 'submit', (e) =>
|
||||||
$('[data-error~=slug]').addClass('hidden')
|
$('[data-error~=slug]').addClass('hidden')
|
||||||
field = $('#new_wiki_path')
|
field = $('#new_wiki_path')
|
||||||
slug = @slugify(field.val())
|
slug = @slugify(field.val())
|
||||||
|
@ -10,6 +10,7 @@ class @Wikis
|
||||||
if (slug.length > 0)
|
if (slug.length > 0)
|
||||||
path = field.attr('data-wikis-path')
|
path = field.attr('data-wikis-path')
|
||||||
location.href = path + '/' + slug
|
location.href = path + '/' + slug
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
dasherize: (value) ->
|
dasherize: (value) ->
|
||||||
value.replace(/[_\s]+/g, '-')
|
value.replace(/[_\s]+/g, '-')
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
&.s26 { width: 26px; height: 26px; margin-right: 8px; }
|
&.s26 { width: 26px; height: 26px; margin-right: 8px; }
|
||||||
&.s32 { width: 32px; height: 32px; margin-right: 10px; }
|
&.s32 { width: 32px; height: 32px; margin-right: 10px; }
|
||||||
&.s36 { width: 36px; height: 36px; margin-right: 10px; }
|
&.s36 { width: 36px; height: 36px; margin-right: 10px; }
|
||||||
|
&.s40 { width: 40px; height: 40px; margin-right: 10px; }
|
||||||
&.s46 { width: 46px; height: 46px; margin-right: 15px; }
|
&.s46 { width: 46px; height: 46px; margin-right: 15px; }
|
||||||
&.s48 { width: 48px; height: 48px; margin-right: 10px; }
|
&.s48 { width: 48px; height: 48px; margin-right: 10px; }
|
||||||
&.s60 { width: 60px; height: 60px; margin-right: 12px; }
|
&.s60 { width: 60px; height: 60px; margin-right: 12px; }
|
||||||
|
@ -40,7 +41,8 @@
|
||||||
&.s16 { font-size: 12px; line-height: 1.33; }
|
&.s16 { font-size: 12px; line-height: 1.33; }
|
||||||
&.s24 { font-size: 14px; line-height: 1.8; }
|
&.s24 { font-size: 14px; line-height: 1.8; }
|
||||||
&.s26 { font-size: 20px; line-height: 1.33; }
|
&.s26 { font-size: 20px; line-height: 1.33; }
|
||||||
&.s32 { font-size: 22px; line-height: 32px; }
|
&.s32 { font-size: 20px; line-height: 32px; }
|
||||||
|
&.s40 { font-size: 16px; line-height: 40px; }
|
||||||
&.s60 { font-size: 32px; line-height: 60px; }
|
&.s60 { font-size: 32px; line-height: 60px; }
|
||||||
&.s90 { font-size: 36px; line-height: 90px; }
|
&.s90 { font-size: 36px; line-height: 90px; }
|
||||||
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
|
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
|
||||||
|
|
|
@ -146,6 +146,10 @@
|
||||||
border-bottom: 1px solid $border-color;
|
border-bottom: 1px solid $border-color;
|
||||||
|
|
||||||
&.oneline-block {
|
&.oneline-block {
|
||||||
line-height: 42px;
|
line-height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .controls {
|
||||||
|
float: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
@include border-radius(3px);
|
@include border-radius(3px);
|
||||||
font-size: $gl-font-size;
|
font-size: $gl-font-size;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: $gl-vert-padding $gl-padding;
|
padding: $gl-vert-padding $gl-btn-padding;
|
||||||
|
|
||||||
&:focus,
|
&:focus,
|
||||||
&:active {
|
&:active {
|
||||||
|
@ -82,8 +82,7 @@
|
||||||
&.btn-success,
|
&.btn-success,
|
||||||
&.btn-new,
|
&.btn-new,
|
||||||
&.btn-create,
|
&.btn-create,
|
||||||
&.btn-save,
|
&.btn-save {
|
||||||
&.btn-green {
|
|
||||||
@include btn-green;
|
@include btn-green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +158,6 @@
|
||||||
|
|
||||||
.input-group-btn {
|
.input-group-btn {
|
||||||
.btn {
|
.btn {
|
||||||
@include btn-gray;
|
|
||||||
@include btn-middle;
|
@include btn-middle;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -186,8 +184,4 @@
|
||||||
border: 1px solid #c6cacf !important;
|
border: 1px solid #c6cacf !important;
|
||||||
background-color: #e4e7ed !important;
|
background-color: #e4e7ed !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-green {
|
|
||||||
@include btn-green
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -376,11 +376,11 @@ table {
|
||||||
margin-bottom: $gl-padding;
|
margin-bottom: $gl-padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-project-item-select-holder {
|
.project-item-select-holder {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.new-project-item-select {
|
.project-item-select {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
|
@ -36,6 +36,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filename {
|
||||||
|
&.old {
|
||||||
|
span.idiff {
|
||||||
|
background-color: #f8cbcb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.new {
|
||||||
|
span.idiff {
|
||||||
|
background-color: #a6f3a6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.left-options {
|
.left-options {
|
||||||
margin-top: -3px;
|
margin-top: -3px;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +158,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: $hover;
|
background: $row-hover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,3 +172,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.idiff {
|
||||||
|
&.left {
|
||||||
|
border-top-left-radius: 2px;
|
||||||
|
border-bottom-left-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
border-top-right-radius: 2px;
|
||||||
|
border-bottom-right-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,11 +2,42 @@ textarea {
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type='search'].search-text-input {
|
input {
|
||||||
background-image: image-url("icon-search.png");
|
border-radius: $border-radius-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='search'] {
|
||||||
|
background-color: white;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='search'].search-input {
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 10px;
|
background-position: 10px;
|
||||||
padding-left: 25px;
|
background-size: 16px;
|
||||||
|
background-position-x: 30%;
|
||||||
|
padding-left: 10px;
|
||||||
|
background-color: $gray-light;
|
||||||
|
|
||||||
|
&.search-input[value=""] {
|
||||||
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAFu0lEQVRIia1WTahkVxH+quqce7vf6zdvJpHoIlkYJ2SiJiIokmQjgoGgIAaEIYuYXWICgojiwkmC4taFwhjcyIDusogEIwwiSSCKPwsdwzAg0SjJ9Izzk5n3+nXfe8+pqizOvd395scfsJqi6dPnnDr11Vc/NJ1OwUTosqJLCmYCHCAC2mSHs+ojZv6AO46Y+20AhIneJsafhPhXVZSXDk7qi+aOLhtQNuBmQtcarAKjTXpn2+l3u2yPunvZSABRucjcAV/eMZuM48/Go/g1d19kc4wq+e8MZjWkbI/P5t2P3RFFbv7SQdyBlBUx8N8OTuqjMcof+N94yMPrY2DMm/ytnb32J0QrY+6AqsHM4Q64O9SKDmerKDD3Oy/tNL9vk342CC8RuU6n0ymCMHb22scu7zQngtASOjUHE1BX4UUAv4b7Ow6qiXCXuz/UdvogAAweDY943/b4cAz0ZlYHXeMsnT07RVb7wMUr8ykI4H5HVkMd5Rcb4/jNURVOL5qErAaAUUdCCIJ5kx5q2nw8m39ImEAAsjpE6PStB0YfMcd1wqqG3Xn7A3PfZyyKnNjaqD4fmE/fCNKshirIyY1xvI+Av6g5QIAIIWX7cJPssboSiBBEeKmsZne0Sb8kzAUWNYyq8NvbDo0fZ6beqxuLmqOOMr/lwOh+YXpXtbjERGja9JyZ9+HxpXKb9Gj5oywRESbj+Cj1ENG1QViTGBl1FbC1We1tbVRfHWIoQkhqH9xbpE92XUbb6VJZ1R4crjRz1JWcDMJvLdoMcyAEhjuwHo8Bfndg3mbszhOY+adVlMtD3po51OwzIQiEaams7oeJhxRw1FFOVpFRRUYIhMBAFRnjOsC8IFHHUA4TQQhgAqpAiIFfGbxkIqj54ayGbL7UoOqHCniAEKHLNr26l+D9wQJzeUwMAnfHvEnLECzZRwRV++d60ptjW9VLZeolEJG6GwCCE0CFVNB+Ay0NEqoQYG4YYFu7B8IEVRt3uRzy/osIoLV9QZimWXGHUMFdmI6M64DUF2Je88R9VZqCSP+QlcF5k+4tCzSsXaqjINuK6UyE0+s/mk6/qFq8oAIL9pqMLhkGsNrOyoOIlszust3aJv0U9+kFdwjTGwWl1YdF+KWlQSZ0Se/psj8yGVdg5tJyfH96EBWmLtoEMwMzMFt031NzGWLLzKhC+KV7H5ZeeaMOPxemma2x68puc0LN3+/u6LJiePS6MKHvn4wu6cPzJj0hsioeMfDrEvjv5r6W9gBvjKJujuKzQ0URIZj75NylvT+mbHfXQa4rwAMaVRTMm/SFyzvNy0yF6+4AM+1ubcSnqkAIUjQKl1RKSbE5jt+vovx1MBqF0WW7/d1Z80ab9BtmuJ3Xk5cJKds9TZt/uLPXvtiTrQ+dIwqfAejUvM1os6FNikXKUHfQ+ekUsXT5u85enJ0CaBSkkGEo1syUQ+DfMdE/4GA1uzupf9zdbzhOmLsF4efHVXjaHHAzmDtGdQRd/Nc5wAEJjNki3XfhyvwVNz80xANrht3LsENY9cBBdN1L9GUyyvFRFZ42t75sBvCQRykbRlU4tT2pPxoCvzx09d4GmPs200M6wKdWSDGK8mppYSWdhAlt0qeaLv+IadXU9/Evq4FAZ8ej+LmtcTxaRX4NWI0Uag5Vg1p5MYg8BnlhXIdPHDow+vTWZvVMVttXDLqkTzZdPj6Qii6cP1cSvIdl3iQkNYyi9HH0I22y+93tY3DcQkTZgQtM+POoCr8x97eylkmtrgKuztrvXJ21x/aNKuqIkZ/fntRfCdcTfhUTAIhRzoDojJD0aSNLLwMzmpT7+JaLtyf1MwDo6qz9djFaUq3t9MlFmy/c1OCSceY9fMsVaL9mvH9ocXdkdWxv1scAePG0THAhMOaLdOw/Gvxfxb1w4eCapyIENUcV5M3/u8FitAxZ25P6GAHT3UX39Srw+QOb1ZffA98Dl2Wy1BYkAAAAAElFTkSuQmCC');
|
||||||
|
}
|
||||||
|
|
||||||
|
&.search-input::-webkit-input-placeholder {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.search-input:-moz-placeholder { /* Firefox 18- */
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.search-input::-moz-placeholder { /* Firefox 19+ */
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.search-input:-ms-input-placeholder {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type='text'].danger {
|
input[type='text'].danger {
|
||||||
|
@ -74,6 +105,7 @@ label {
|
||||||
|
|
||||||
.form-control {
|
.form-control {
|
||||||
@include box-shadow(none);
|
@include box-shadow(none);
|
||||||
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control-inline {
|
.form-control-inline {
|
||||||
|
|
|
@ -73,7 +73,6 @@ header {
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
line-height: $header-height;
|
line-height: $header-height;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
@ -88,6 +87,22 @@ header {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown-toggle-caret {
|
||||||
|
position: relative;
|
||||||
|
top: -2px;
|
||||||
|
width: 12px;
|
||||||
|
line-height: 12px;
|
||||||
|
margin-left: 5px;
|
||||||
|
font-size: 10px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-item-select {
|
||||||
|
right: auto;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-collapse {
|
.navbar-collapse {
|
||||||
|
@ -108,16 +123,10 @@ header {
|
||||||
|
|
||||||
.search-input {
|
.search-input {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
background-image: image-url("icon-search.png");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 195px;
|
|
||||||
@include input-big;
|
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
@include box-shadow(none);
|
@include box-shadow(none);
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: #DDD;
|
|
||||||
background-color: #FFF;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,9 +141,13 @@ header {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: $screen-md-max) {
|
@media (max-width: $screen-md-max) {
|
||||||
.header-collapsed, .header-expanded {
|
.header-collapsed {
|
||||||
@include collapsed-header;
|
margin-left: $sidebar_collapsed_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-expanded {
|
||||||
|
margin-left: $sidebar_width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(min-width: $screen-md-max) {
|
@media(min-width: $screen-md-max) {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
padding: 0 $gl-padding;
|
padding: 0 $gl-btn-padding;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
font-size: $gl-font-size;
|
font-size: $gl-font-size;
|
||||||
|
|
|
@ -48,8 +48,19 @@
|
||||||
|
|
||||||
.ui-state-hover,
|
.ui-state-hover,
|
||||||
.ui-state-focus {
|
.ui-state-focus {
|
||||||
border: 1px solid $hover;
|
border: 1px solid $row-hover;
|
||||||
background: $hover;
|
background: $row-hover;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-sortable-handle {
|
||||||
|
cursor: move;
|
||||||
|
cursor: -webkit-grab;
|
||||||
|
cursor: -moz-grab;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
cursor: -webkit-grabbing;
|
||||||
|
cursor: -moz-grabbing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
&.smoke { background-color: $background-color; }
|
&.smoke { background-color: $background-color; }
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: $hover;
|
background: $row-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
|
@ -109,7 +109,6 @@ ul.content-list {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
padding: $gl-padding 0;
|
|
||||||
border-color: $table-border-color;
|
border-color: $table-border-color;
|
||||||
color: $gl-gray;
|
color: $gl-gray;
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
aside {
|
aside:not(.right-sidebar){
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,3 +37,102 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top-area {
|
||||||
|
@include clearfix;
|
||||||
|
|
||||||
|
border-bottom: 1px solid #EEE;
|
||||||
|
|
||||||
|
.nav-text {
|
||||||
|
padding-top: 16px;
|
||||||
|
padding-bottom: 11px;
|
||||||
|
display: inline-block;
|
||||||
|
width: 50%;
|
||||||
|
line-height: 28px;
|
||||||
|
|
||||||
|
/* Small devices (phones, tablets, 768px and lower) */
|
||||||
|
@media (max-width: $screen-sm-min) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links {
|
||||||
|
display: inline-block;
|
||||||
|
width: 50%;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
border-bottom: none;
|
||||||
|
|
||||||
|
/* Small devices (phones, tablets, 768px and lower) */
|
||||||
|
@media (max-width: $screen-sm-min) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-controls {
|
||||||
|
width: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
float: right;
|
||||||
|
text-align: right;
|
||||||
|
padding: 11px 0;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
|
||||||
|
> .dropdown {
|
||||||
|
margin-right: $gl-padding-top;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .btn {
|
||||||
|
margin-right: $gl-padding-top;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .btn-grouped {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> form {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
height: 34px;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
margin-right: $gl-padding-top;
|
||||||
|
|
||||||
|
/* Medium devices (desktops, 992px and up) */
|
||||||
|
@media (min-width: $screen-md-min) { width: 200px; }
|
||||||
|
|
||||||
|
/* Large devices (large desktops, 1200px and up) */
|
||||||
|
@media (min-width: $screen-lg-min) { width: 250px; }
|
||||||
|
|
||||||
|
&.input-short {
|
||||||
|
/* Medium devices (desktops, 992px and up) */
|
||||||
|
@media (min-width: $screen-md-min) { width: 170px; }
|
||||||
|
|
||||||
|
/* Large devices (large desktops, 1200px and up) */
|
||||||
|
@media (min-width: $screen-lg-min) { width: 210px; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide on extra small devices (phones) */
|
||||||
|
@media (max-width: $screen-xs-max) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Small devices (tablets, 768px and lower) */
|
||||||
|
@media (max-width: $screen-sm-max) {
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,35 +1,11 @@
|
||||||
.gl-pagination {
|
.gl-pagination {
|
||||||
|
text-align: center;
|
||||||
border-top: 1px solid $border-color;
|
border-top: 1px solid $border-color;
|
||||||
background-color: $background-color;
|
margin: 0;
|
||||||
margin: -$gl-padding;
|
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
li.first,
|
|
||||||
li.last,
|
|
||||||
li.next,
|
|
||||||
li.prev {
|
|
||||||
> a {
|
|
||||||
color: $link-color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
li > a,
|
|
||||||
li > span {
|
|
||||||
border: none;
|
|
||||||
margin: 0;
|
|
||||||
@include border-radius(0 !important);
|
|
||||||
padding: 13px 19px;
|
|
||||||
border-right: 1px solid $border-color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,13 @@
|
||||||
margin-bottom: $gl-padding;
|
margin-bottom: $gl-padding;
|
||||||
|
|
||||||
.panel-heading {
|
.panel-heading {
|
||||||
padding: 7px $gl-padding;
|
padding: $gl-vert-padding $gl-padding;
|
||||||
|
line-height: 36px;
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
margin-top: -2px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-body {
|
.panel-body {
|
||||||
|
@ -14,7 +20,3 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-blank .panel .panel-heading {
|
|
||||||
line-height: 42px !important;
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,6 +12,23 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
transition-duration: .3s;
|
transition-duration: .3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gitlab-text-container-link {
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logo {
|
||||||
|
z-index: 2;
|
||||||
|
position: absolute;
|
||||||
|
width: 58px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right-sidebar-expanded {
|
||||||
|
padding-right: $gutter_width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-wrapper {
|
.sidebar-wrapper {
|
||||||
|
@ -70,7 +87,7 @@
|
||||||
width: 158px;
|
width: 158px;
|
||||||
float: left;
|
float: left;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-left: 14px;
|
margin-left: 50px;
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
line-height: 41px;
|
line-height: 41px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
@ -181,6 +198,10 @@
|
||||||
@mixin expanded-sidebar {
|
@mixin expanded-sidebar {
|
||||||
padding-left: $sidebar_width;
|
padding-left: $sidebar_width;
|
||||||
|
|
||||||
|
&.right-sidebar-collapsed {
|
||||||
|
padding-right: $sidebar_collapsed_width;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-wrapper {
|
.sidebar-wrapper {
|
||||||
width: $sidebar_width;
|
width: $sidebar_width;
|
||||||
|
|
||||||
|
@ -203,6 +224,10 @@
|
||||||
@mixin collapsed-sidebar {
|
@mixin collapsed-sidebar {
|
||||||
padding-left: $sidebar_collapsed_width;
|
padding-left: $sidebar_collapsed_width;
|
||||||
|
|
||||||
|
&.right-sidebar-collapsed {
|
||||||
|
padding-right: $sidebar_collapsed_width;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-wrapper {
|
.sidebar-wrapper {
|
||||||
width: $sidebar_collapsed_width;
|
width: $sidebar_collapsed_width;
|
||||||
|
|
||||||
|
@ -266,26 +291,10 @@
|
||||||
background: #f2f6f7;
|
background: #f2f6f7;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: $screen-md-max) {
|
.page-sidebar-collapsed {
|
||||||
.page-sidebar-collapsed {
|
@include collapsed-sidebar;
|
||||||
@include collapsed-sidebar;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-sidebar-expanded {
|
|
||||||
@include collapsed-sidebar;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapse-nav {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(min-width: $screen-md-max) {
|
.page-sidebar-expanded {
|
||||||
.page-sidebar-collapsed {
|
@include expanded-sidebar;
|
||||||
@include collapsed-sidebar;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-sidebar-expanded {
|
|
||||||
@include expanded-sidebar;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
.timeline-entry {
|
.timeline-entry {
|
||||||
padding: $gl-padding 0;
|
padding: $gl-padding $gl-btn-padding;
|
||||||
border-color: $table-border-color;
|
border-color: $table-border-color;
|
||||||
color: $gl-gray;
|
color: $gl-gray;
|
||||||
border-bottom: 1px solid $border-white-light;
|
border-bottom: 1px solid $border-white-light;
|
||||||
|
|
||||||
&:target {
|
&:target {
|
||||||
background: $hover;
|
background: $row-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
|
|
|
@ -114,22 +114,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.container-blank .panel .panel-heading {
|
|
||||||
font-size: 17px;
|
|
||||||
line-height: 38px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel {
|
.panel {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
|
||||||
.panel-heading {
|
|
||||||
.panel-head-actions {
|
|
||||||
position: relative;
|
|
||||||
top: -5px;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-body {
|
.panel-body {
|
||||||
form, pre {
|
form, pre {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
|
@ -22,9 +22,9 @@ $brand-info: $gl-info;
|
||||||
$brand-warning: $gl-warning;
|
$brand-warning: $gl-warning;
|
||||||
$brand-danger: $gl-danger;
|
$brand-danger: $gl-danger;
|
||||||
|
|
||||||
$border-radius-base: 2px !default;
|
$border-radius-base: 3px !default;
|
||||||
$border-radius-large: 2px !default;
|
$border-radius-large: 3px !default;
|
||||||
$border-radius-small: 2px !default;
|
$border-radius-small: 3px !default;
|
||||||
|
|
||||||
|
|
||||||
//== Scaffolding
|
//== Scaffolding
|
||||||
|
@ -66,20 +66,20 @@ $legend-color: $text-color;
|
||||||
//##
|
//##
|
||||||
|
|
||||||
$pagination-color: $gl-gray;
|
$pagination-color: $gl-gray;
|
||||||
$pagination-bg: $background-color;
|
$pagination-bg: #fff;
|
||||||
$pagination-border: transparent;
|
$pagination-border: $border-color;
|
||||||
|
|
||||||
$pagination-hover-color: #fff;
|
$pagination-hover-color: $gl-gray;
|
||||||
$pagination-hover-bg: $brand-info;
|
$pagination-hover-bg: $row-hover;
|
||||||
$pagination-hover-border: transparent;
|
$pagination-hover-border: $border-color;
|
||||||
|
|
||||||
$pagination-active-color: #fff;
|
$pagination-active-color: $blue-dark;
|
||||||
$pagination-active-bg: $brand-info;
|
$pagination-active-bg: #fff;
|
||||||
$pagination-active-border: transparent;
|
$pagination-active-border: $border-color;
|
||||||
|
|
||||||
$pagination-disabled-color: #fff;
|
$pagination-disabled-color: #cdcdcd;
|
||||||
$pagination-disabled-bg: lighten($brand-info, 15%);
|
$pagination-disabled-bg: $background-color;
|
||||||
$pagination-disabled-border: transparent;
|
$pagination-disabled-border: $border-color;
|
||||||
|
|
||||||
|
|
||||||
//== Form states and alerts
|
//== Form states and alerts
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
|
|
||||||
ul, ol {
|
ul, ol {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 6px 0 6px 18px !important;
|
margin: 6px 0 6px 28px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
$hover: #faf9f9;
|
$row-hover: #f4f8fe;
|
||||||
$gl-text-color: #54565B;
|
$gl-text-color: #54565B;
|
||||||
$gl-text-green: #4A2;
|
$gl-text-green: #4A2;
|
||||||
$gl-text-red: #D12F19;
|
$gl-text-red: #D12F19;
|
||||||
|
@ -12,6 +12,9 @@ $gl-font-size: 15px;
|
||||||
$list-font-size: 15px;
|
$list-font-size: 15px;
|
||||||
$sidebar_collapsed_width: 62px;
|
$sidebar_collapsed_width: 62px;
|
||||||
$sidebar_width: 230px;
|
$sidebar_width: 230px;
|
||||||
|
$gutter_collapsed_width: 62px;
|
||||||
|
$gutter_width: 290px;
|
||||||
|
$gutter_inner_width: 258px;
|
||||||
$avatar_radius: 50%;
|
$avatar_radius: 50%;
|
||||||
$code_font_size: 13px;
|
$code_font_size: 13px;
|
||||||
$code_line_height: 1.5;
|
$code_line_height: 1.5;
|
||||||
|
@ -22,10 +25,12 @@ $header-height: 58px;
|
||||||
$fixed-layout-width: 1280px;
|
$fixed-layout-width: 1280px;
|
||||||
$gl-gray: #5a5a5a;
|
$gl-gray: #5a5a5a;
|
||||||
$gl-padding: 16px;
|
$gl-padding: 16px;
|
||||||
|
$gl-btn-padding: 10px;
|
||||||
$gl-vert-padding: 6px;
|
$gl-vert-padding: 6px;
|
||||||
$gl-padding-top:10px;
|
$gl-padding-top:10px;
|
||||||
$gl-avatar-size: 46px;
|
$gl-avatar-size: 40px;
|
||||||
$secondary-text: #7f8fa4;
|
$secondary-text: #7f8fa4;
|
||||||
|
$error-exclamation-point: #E62958;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Color schema
|
* Color schema
|
||||||
|
@ -35,11 +40,12 @@ $white-light: #FFFFFF;
|
||||||
$white-normal: #ededed;
|
$white-normal: #ededed;
|
||||||
$white-dark: #ededed;
|
$white-dark: #ededed;
|
||||||
|
|
||||||
$gray-light: #f7f7f7;
|
$gray-light: #faf9f9;
|
||||||
$gray-normal: #ededed;
|
$gray-normal: #f5f5f5;
|
||||||
$gray-dark: #ededed;
|
$gray-dark: #ededed;
|
||||||
|
$gray-darkest: #c9c9c9;
|
||||||
|
|
||||||
$green-light: #31AF64;
|
$green-light: #38ae67;
|
||||||
$green-normal: #2FAA60;
|
$green-normal: #2FAA60;
|
||||||
$green-dark: #2CA05B;
|
$green-dark: #2CA05B;
|
||||||
|
|
||||||
|
@ -51,7 +57,7 @@ $blue-medium-light: #3498CB;
|
||||||
$blue-medium: #2F8EBF;
|
$blue-medium: #2F8EBF;
|
||||||
$blue-medium-dark: #2D86B4;
|
$blue-medium-dark: #2D86B4;
|
||||||
|
|
||||||
$orange-light: #FC6443;
|
$orange-light: rgba(252, 109, 38, 0.80);
|
||||||
$orange-normal: #E75E40;
|
$orange-normal: #E75E40;
|
||||||
$orange-dark: #CE5237;
|
$orange-dark: #CE5237;
|
||||||
|
|
||||||
|
@ -63,8 +69,8 @@ $border-white-light: #F1F2F4;
|
||||||
$border-white-normal: #D6DAE2;
|
$border-white-normal: #D6DAE2;
|
||||||
$border-white-dark: #C6CACF;
|
$border-white-dark: #C6CACF;
|
||||||
|
|
||||||
$border-gray-light: #d1d1d1;
|
$border-gray-light: rgba(0, 0, 0, 0.06);
|
||||||
$border-gray-normal: #D6DAE2;
|
$border-gray-normal: rgba(0, 0, 0, 0.10);;
|
||||||
$border-gray-dark: #C6CACF;
|
$border-gray-dark: #C6CACF;
|
||||||
|
|
||||||
$border-green-light: #2FAA60;
|
$border-green-light: #2FAA60;
|
||||||
|
@ -75,7 +81,7 @@ $border-blue-light: #2D9FD8;
|
||||||
$border-blue-normal: #2897CE;
|
$border-blue-normal: #2897CE;
|
||||||
$border-blue-dark: #258DC1;
|
$border-blue-dark: #258DC1;
|
||||||
|
|
||||||
$border-orange-light: #ED5C3D;
|
$border-orange-light: #fc6d26;
|
||||||
$border-orange-normal: #CE5237;
|
$border-orange-normal: #CE5237;
|
||||||
$border-orange-dark: #C14E35;
|
$border-orange-dark: #C14E35;
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,16 @@
|
||||||
@extend .alert-warning;
|
@extend .alert-warning;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
> div, p {
|
||||||
|
display: inline;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.broadcast-message-preview {
|
.broadcast-message-preview {
|
||||||
|
|
11
app/assets/stylesheets/pages/appearances.scss
Normal file
11
app/assets/stylesheets/pages/appearances.scss
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.appearance-logo-preview {
|
||||||
|
max-width: 400px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.appearance-light-logo-preview {
|
||||||
|
background-color: $background-color;
|
||||||
|
max-width: 72px;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
|
@ -40,10 +40,6 @@
|
||||||
.avatar {
|
.avatar {
|
||||||
@include border-radius(50%);
|
@include border-radius(50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.identicon {
|
|
||||||
line-height: 46px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dash-project-access-icon {
|
.dash-project-access-icon {
|
||||||
|
|
|
@ -12,6 +12,14 @@
|
||||||
.identifier {
|
.identifier {
|
||||||
color: #5c5d5e;
|
color: #5c5d5e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.issue_created_ago, .author_link {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-meta {
|
||||||
|
margin-left: 65px
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-page-description {
|
.detail-page-description {
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-family: $monospace_font;
|
font-family: $monospace_font;
|
||||||
border: none;
|
border: none;
|
||||||
|
border-collapse: separate;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
.line_holder td {
|
.line_holder td {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
.event-item {
|
.event-item {
|
||||||
font-size: $gl-font-size;
|
font-size: $gl-font-size;
|
||||||
padding: $gl-padding 0 $gl-padding ($gl-avatar-size + 15px);
|
padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top);
|
||||||
border-bottom: 1px solid $table-border-color;
|
border-bottom: 1px solid $table-border-color;
|
||||||
color: #7f8fa4;
|
color: #7f8fa4;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
.event-title,
|
.event-title,
|
||||||
.event-item-timestamp {
|
.event-item-timestamp {
|
||||||
line-height: 44px;
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
margin-left: -($gl-avatar-size + 15px);
|
margin-left: -($gl-avatar-size + $gl-padding-top);
|
||||||
}
|
}
|
||||||
|
|
||||||
.event-title {
|
.event-title {
|
||||||
|
@ -41,7 +41,6 @@
|
||||||
margin-right: 174px;
|
margin-right: 174px;
|
||||||
|
|
||||||
.event-note {
|
.event-note {
|
||||||
margin-top: 5px;
|
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
||||||
.md {
|
.md {
|
||||||
|
@ -98,8 +97,6 @@
|
||||||
&:last-child { border:none }
|
&:last-child { border:none }
|
||||||
|
|
||||||
.event_commits {
|
.event_commits {
|
||||||
margin-top: 9px;
|
|
||||||
|
|
||||||
li {
|
li {
|
||||||
&.commit {
|
&.commit {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|
|
@ -6,11 +6,3 @@
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.explore-trending-block {
|
|
||||||
.lead {
|
|
||||||
line-height: 32px;
|
|
||||||
font-size: 18px;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
.member-search-form {
|
.member-search-form {
|
||||||
float: left;
|
float: left;
|
||||||
|
|
||||||
|
input[type='search'] {
|
||||||
|
width: 225px;
|
||||||
|
vertical-align: bottom;
|
||||||
|
|
||||||
|
@media (max-width: $screen-xs-max) {
|
||||||
|
width: 100px;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.milestone-row {
|
.milestone-row {
|
||||||
|
@ -11,3 +21,21 @@
|
||||||
height: 42px;
|
height: 42px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group-row {
|
||||||
|
&.no-description {
|
||||||
|
.group-name {
|
||||||
|
line-height: 44px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats {
|
||||||
|
float: right;
|
||||||
|
line-height: 44px;
|
||||||
|
color: $gl-gray;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,21 +29,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-issuable-filter {
|
|
||||||
.controls {
|
|
||||||
float: right;
|
|
||||||
margin-top: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-links {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.issuable-details {
|
.issuable-details {
|
||||||
section {
|
section {
|
||||||
border-right: 1px solid $border-white-light;
|
|
||||||
|
|
||||||
.issuable-discussion {
|
.issuable-discussion {
|
||||||
margin-right: 1px;
|
margin-right: 1px;
|
||||||
}
|
}
|
||||||
|
@ -73,11 +60,41 @@
|
||||||
.block {
|
.block {
|
||||||
@include clearfix;
|
@include clearfix;
|
||||||
padding: $gl-padding 0;
|
padding: $gl-padding 0;
|
||||||
border-bottom: 1px solid #F0F0F0;
|
border-bottom: 1px solid $border-gray-light;
|
||||||
|
// This prevents the mess when resizing the sidebar
|
||||||
|
// of elements repositioning themselves..
|
||||||
|
width: $gutter_inner_width;
|
||||||
|
// --
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-top: 7px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container span {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issuable-count {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.gutter-toggle {
|
||||||
|
margin-left: 20px;
|
||||||
|
padding-left: 10px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $gray-darkest;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
@ -133,3 +150,105 @@
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.right-sidebar {
|
||||||
|
position: fixed;
|
||||||
|
top: 58px;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
transition: width .3s;
|
||||||
|
background: $gray-light;
|
||||||
|
padding: 10px 20px;
|
||||||
|
|
||||||
|
&.right-sidebar-expanded {
|
||||||
|
width: $gutter_width;
|
||||||
|
|
||||||
|
hr {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-collapsed-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gutter-toggle {
|
||||||
|
border-left: 1px solid $border-gray-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscribe-button {
|
||||||
|
span {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right-sidebar-collapsed {
|
||||||
|
width: $sidebar_collapsed_width;
|
||||||
|
padding-top: 0;
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin: 0;
|
||||||
|
color: $gray-normal;
|
||||||
|
border-color: $gray-normal;
|
||||||
|
width: 62px;
|
||||||
|
margin-left: -20px
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
width: $sidebar_collapsed_width - 1px;
|
||||||
|
margin-left: -19px;
|
||||||
|
padding: 15px 0 0 0;
|
||||||
|
border-bottom: none;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide-collapsed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gutter-toggle {
|
||||||
|
margin-left: -36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-collapsed-icon {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
color: #999999;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-clipboard {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
background: $gray-normal;
|
||||||
|
border: 1px solid $border-gray-normal;
|
||||||
|
&:hover {
|
||||||
|
background: $gray-dark;
|
||||||
|
border: 1px solid $border-gray-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-page-description {
|
||||||
|
small {
|
||||||
|
color: $gray-darkest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -49,11 +49,6 @@
|
||||||
.issue-search-form {
|
.issue-search-form {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
||||||
.issue_search {
|
|
||||||
border: 1px solid #DDD !important;
|
|
||||||
background-color: #f4f4f4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form.edit-issue {
|
form.edit-issue {
|
||||||
|
@ -70,10 +65,6 @@ form.edit-issue {
|
||||||
width: 3em;
|
width: 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.merge-request-info {
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.merge-request-status {
|
.merge-request-status {
|
||||||
color: $gl-gray;
|
color: $gl-gray;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.manage-labels-list {
|
.label-row {
|
||||||
.label {
|
.label {
|
||||||
padding: 9px;
|
padding: 9px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
|
@ -201,3 +201,39 @@
|
||||||
.mr-source-target {
|
.mr-source-target {
|
||||||
line-height: 31px;
|
line-height: 31px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled-comment-area {
|
||||||
|
padding: 16px 0;
|
||||||
|
|
||||||
|
.disabled-profile {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: $border-gray-dark;
|
||||||
|
border-radius: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled-comment {
|
||||||
|
background: $gray-light;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
height: 200px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid $border-gray-normal;
|
||||||
|
padding-top: 90px;
|
||||||
|
text-align: center;
|
||||||
|
right: 20px;
|
||||||
|
position: absolute;
|
||||||
|
left: 70px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #B2B2B2;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $md-link-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,3 +11,60 @@ li.milestone {
|
||||||
height: 6px;
|
height: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.milestone-content {
|
||||||
|
.issues-count {
|
||||||
|
margin-right: 17px;
|
||||||
|
float: right;
|
||||||
|
width: 105px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-row {
|
||||||
|
.color-label {
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue title
|
||||||
|
span a {
|
||||||
|
color: rgba(0,0,0,0.64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.milestone-summary {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
|
||||||
|
.milestone-stat {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remaining-days {
|
||||||
|
color: $orange-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.issues-sortable-list {
|
||||||
|
.issue-detail {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
.issue-number{
|
||||||
|
color: rgba(0,0,0,0.44);
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.color-label {
|
||||||
|
padding: 6px 10px;
|
||||||
|
margin-right: 7px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.milestone-detail {
|
||||||
|
border-bottom: 1px solid $border-color;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
|
@ -73,31 +73,26 @@
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.visibility-icon {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 5px;
|
||||||
|
font-size: 18px;
|
||||||
|
color: $gray;
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
padding: 0 $gl-padding;
|
padding: 0 $gl-padding;
|
||||||
color: #5c5d5e;
|
color: #5c5d5e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.visibility-level-label {
|
|
||||||
@extend .btn;
|
|
||||||
@extend .btn-gray;
|
|
||||||
|
|
||||||
color: $gray;
|
|
||||||
cursor: default;
|
|
||||||
|
|
||||||
i {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-repo-buttons {
|
.project-repo-buttons {
|
||||||
margin-top: 12px;
|
margin-top: 20px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
|
|
||||||
.count-buttons {
|
.count-buttons {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clone-row {
|
.clone-row {
|
||||||
|
@ -163,7 +158,7 @@
|
||||||
line-height: 13px;
|
line-height: 13px;
|
||||||
padding: $gl-vert-padding $gl-padding;
|
padding: $gl-vert-padding $gl-padding;
|
||||||
letter-spacing: .4px;
|
letter-spacing: .4px;
|
||||||
padding: 10px;
|
padding: 10px 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
touch-action: manipulation;
|
touch-action: manipulation;
|
||||||
|
@ -281,36 +276,6 @@
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-area {
|
|
||||||
border-bottom: 1px solid #EEE;
|
|
||||||
|
|
||||||
ul.nav-links {
|
|
||||||
display: inline-block;
|
|
||||||
width: 50%;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.projects-search-form {
|
|
||||||
width: 50%;
|
|
||||||
display: inline-block;
|
|
||||||
float: right;
|
|
||||||
padding-top: 11px;
|
|
||||||
text-align: right;
|
|
||||||
|
|
||||||
.btn-green {
|
|
||||||
margin-left: 10px;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-max) {
|
|
||||||
.projects-search-form {
|
|
||||||
padding-top: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fork-namespaces {
|
.fork-namespaces {
|
||||||
.fork-thumbnail {
|
.fork-thumbnail {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -386,22 +351,6 @@ pre.light-well {
|
||||||
border-color: #f1f1f1;
|
border-color: #f1f1f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.projects-search-form {
|
|
||||||
padding: $gl-padding 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
|
|
||||||
input {
|
|
||||||
display: inline-block;
|
|
||||||
width: calc(100% - 151px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
width: 135px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.git-empty {
|
.git-empty {
|
||||||
margin: 0 7px 0 7px;
|
margin: 0 7px 0 7px;
|
||||||
|
|
||||||
|
@ -437,12 +386,11 @@ pre.light-well {
|
||||||
@include basic-list;
|
@include basic-list;
|
||||||
|
|
||||||
.project-row {
|
.project-row {
|
||||||
padding: $gl-padding 0;
|
|
||||||
border-color: $table-border-color;
|
border-color: $table-border-color;
|
||||||
|
|
||||||
&.no-description {
|
&.no-description {
|
||||||
.project {
|
.project {
|
||||||
line-height: 44px;
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,12 +403,16 @@ pre.light-well {
|
||||||
.project-controls {
|
.project-controls {
|
||||||
float: right;
|
float: right;
|
||||||
color: $gl-gray;
|
color: $gl-gray;
|
||||||
line-height: 45px;
|
line-height: 40px;
|
||||||
color: #7f8fa4;
|
color: #7f8fa4;
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-description {
|
.project-description {
|
||||||
|
@ -558,3 +510,19 @@ pre.light-well {
|
||||||
width: 101%;
|
width: 101%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cannot-be-merged,
|
||||||
|
.cannot-be-merged:hover {
|
||||||
|
color: #E62958;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.private-forks-notice .private-fork-icon {
|
||||||
|
i:nth-child(1) {
|
||||||
|
color: #2AA056;
|
||||||
|
}
|
||||||
|
|
||||||
|
i:nth-child(2) {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
124
app/assets/stylesheets/pages/todos.scss
Normal file
124
app/assets/stylesheets/pages/todos.scss
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/**
|
||||||
|
* Dashboard Todos
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.navbar-nav {
|
||||||
|
li {
|
||||||
|
.badge.todos-pending-count {
|
||||||
|
background-color: #7f8fa4;
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.todos {
|
||||||
|
.panel {
|
||||||
|
border-top: none;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-item {
|
||||||
|
font-size: $gl-font-size;
|
||||||
|
padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top);
|
||||||
|
border-bottom: 1px solid $table-border-color;
|
||||||
|
color: #7f8fa4;
|
||||||
|
|
||||||
|
&.todo-inline {
|
||||||
|
.avatar {
|
||||||
|
position: relative;
|
||||||
|
top: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-title {
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #4c4e54;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
margin-left: -($gl-avatar-size + $gl-padding-top);
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-title {
|
||||||
|
@include str-truncated(calc(100% - 174px));
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
.author_name {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-body {
|
||||||
|
margin-right: 174px;
|
||||||
|
|
||||||
|
.todo-note {
|
||||||
|
word-wrap: break-word;
|
||||||
|
|
||||||
|
.md {
|
||||||
|
color: #7f8fa4;
|
||||||
|
font-size: $gl-font-size;
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #5c5d5e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
border: none;
|
||||||
|
background: #f9f9f9;
|
||||||
|
border-radius: 0;
|
||||||
|
color: #777;
|
||||||
|
margin: 0 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-image-attach {
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-left: 0px;
|
||||||
|
max-width: 200px;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-note-icon {
|
||||||
|
color: #777;
|
||||||
|
float: left;
|
||||||
|
font-size: $gl-font-size;
|
||||||
|
line-height: 16px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child { border:none }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: $screen-xs-max) {
|
||||||
|
.todo-item {
|
||||||
|
padding-left: $gl-padding;
|
||||||
|
|
||||||
|
.todo-title {
|
||||||
|
white-space: normal;
|
||||||
|
overflow: visible;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-body {
|
||||||
|
margin: 0;
|
||||||
|
border-left: 2px solid #DDD;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
td {
|
td {
|
||||||
background: $hover;
|
background: $row-hover;
|
||||||
}
|
}
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,3 @@
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
padding-right: 7px;
|
padding-right: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wiki-last-edit-by {
|
|
||||||
font-size: 80%;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
57
app/controllers/admin/appearances_controller.rb
Normal file
57
app/controllers/admin/appearances_controller.rb
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
class Admin::AppearancesController < Admin::ApplicationController
|
||||||
|
before_action :set_appearance, except: :create
|
||||||
|
|
||||||
|
def show
|
||||||
|
end
|
||||||
|
|
||||||
|
def preview
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@appearance = Appearance.new(appearance_params)
|
||||||
|
|
||||||
|
if @appearance.save
|
||||||
|
redirect_to admin_appearances_path, notice: 'Appearance was successfully created.'
|
||||||
|
else
|
||||||
|
render action: 'show'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
if @appearance.update(appearance_params)
|
||||||
|
redirect_to admin_appearances_path, notice: 'Appearance was successfully updated.'
|
||||||
|
else
|
||||||
|
render action: 'show'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def logo
|
||||||
|
@appearance.remove_logo!
|
||||||
|
|
||||||
|
@appearance.save
|
||||||
|
|
||||||
|
redirect_to admin_appearances_path, notice: 'Logo was succesfully removed.'
|
||||||
|
end
|
||||||
|
|
||||||
|
def header_logos
|
||||||
|
@appearance.remove_header_logo!
|
||||||
|
@appearance.save
|
||||||
|
|
||||||
|
redirect_to admin_appearances_path, notice: 'Header logo was succesfully removed.'
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_appearance
|
||||||
|
@appearance = Appearance.last || Appearance.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a trusted parameter "white list" through.
|
||||||
|
def appearance_params
|
||||||
|
params.require(:appearance).permit(
|
||||||
|
:title, :description, :logo, :logo_cache, :header_logo, :header_logo_cache,
|
||||||
|
:updated_by
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
|
@ -74,13 +74,14 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
||||||
:metrics_timeout,
|
:metrics_timeout,
|
||||||
:metrics_method_call_threshold,
|
:metrics_method_call_threshold,
|
||||||
:metrics_sample_interval,
|
:metrics_sample_interval,
|
||||||
:ip_blocking_enabled,
|
|
||||||
:dnsbl_servers_list,
|
|
||||||
:recaptcha_enabled,
|
:recaptcha_enabled,
|
||||||
:recaptcha_site_key,
|
:recaptcha_site_key,
|
||||||
:recaptcha_private_key,
|
:recaptcha_private_key,
|
||||||
:sentry_enabled,
|
:sentry_enabled,
|
||||||
:sentry_dsn,
|
:sentry_dsn,
|
||||||
|
:akismet_enabled,
|
||||||
|
:akismet_api_key,
|
||||||
|
:email_author_in_body,
|
||||||
restricted_visibility_levels: [],
|
restricted_visibility_levels: [],
|
||||||
import_sources: []
|
import_sources: []
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
|
||||||
before_action :finder, only: [:edit, :update, :destroy]
|
before_action :finder, only: [:edit, :update, :destroy]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@broadcast_messages = BroadcastMessage.reorder("starts_at ASC").page(params[:page])
|
@broadcast_messages = BroadcastMessage.reorder("ends_at DESC").page(params[:page])
|
||||||
@broadcast_message = BroadcastMessage.new
|
@broadcast_message = BroadcastMessage.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -36,6 +36,10 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def preview
|
||||||
|
@message = broadcast_message_params[:message]
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def finder
|
def finder
|
||||||
|
|
|
@ -53,6 +53,6 @@ class Admin::LabelsController < Admin::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def label_params
|
def label_params
|
||||||
params[:label].permit(:title, :color)
|
params[:label].permit(:title, :description, :color)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
17
app/controllers/admin/spam_logs_controller.rb
Normal file
17
app/controllers/admin/spam_logs_controller.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
class Admin::SpamLogsController < Admin::ApplicationController
|
||||||
|
def index
|
||||||
|
@spam_logs = SpamLog.order(id: :desc).page(params[:page])
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
spam_log = SpamLog.find(params[:id])
|
||||||
|
|
||||||
|
if params[:remove_user]
|
||||||
|
spam_log.remove_user
|
||||||
|
redirect_to admin_spam_logs_path, notice: "User #{spam_log.user.username} was successfully removed."
|
||||||
|
else
|
||||||
|
spam_log.destroy
|
||||||
|
render nothing: true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -25,7 +25,7 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
helper_method :abilities, :can?, :current_application_settings
|
helper_method :abilities, :can?, :current_application_settings
|
||||||
helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?
|
helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?
|
||||||
helper_method :repository
|
helper_method :repository, :can_collaborate_with_project?
|
||||||
|
|
||||||
rescue_from Encoding::CompatibilityError do |exception|
|
rescue_from Encoding::CompatibilityError do |exception|
|
||||||
log_exception(exception)
|
log_exception(exception)
|
||||||
|
@ -60,6 +60,8 @@ class ApplicationController < ActionController::Base
|
||||||
params[:authenticity_token].presence
|
params[:authenticity_token].presence
|
||||||
elsif params[:private_token].presence
|
elsif params[:private_token].presence
|
||||||
params[:private_token].presence
|
params[:private_token].presence
|
||||||
|
elsif request.headers['PRIVATE-TOKEN'].present?
|
||||||
|
request.headers['PRIVATE-TOKEN']
|
||||||
end
|
end
|
||||||
user = user_token && User.find_by_authentication_token(user_token.to_s)
|
user = user_token && User.find_by_authentication_token(user_token.to_s)
|
||||||
|
|
||||||
|
@ -162,7 +164,7 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def git_not_found!
|
def git_not_found!
|
||||||
render html: "errors/git_not_found", layout: "errors", status: 404
|
render "errors/git_not_found.html", layout: "errors", status: 404
|
||||||
end
|
end
|
||||||
|
|
||||||
def method_missing(method_sym, *arguments, &block)
|
def method_missing(method_sym, *arguments, &block)
|
||||||
|
@ -244,6 +246,8 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
def ldap_security_check
|
def ldap_security_check
|
||||||
if current_user && current_user.requires_ldap_check?
|
if current_user && current_user.requires_ldap_check?
|
||||||
|
return unless current_user.try_obtain_ldap_lease
|
||||||
|
|
||||||
unless Gitlab::LDAP::Access.allowed?(current_user)
|
unless Gitlab::LDAP::Access.allowed?(current_user)
|
||||||
sign_out current_user
|
sign_out current_user
|
||||||
flash[:alert] = "Access denied for your LDAP account."
|
flash[:alert] = "Access denied for your LDAP account."
|
||||||
|
@ -275,9 +279,10 @@ class ApplicationController < ActionController::Base
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def view_to_html_string(partial)
|
def view_to_html_string(partial, locals = {})
|
||||||
render_to_string(
|
render_to_string(
|
||||||
partial,
|
partial,
|
||||||
|
locals: locals,
|
||||||
layout: false,
|
layout: false,
|
||||||
formats: [:html]
|
formats: [:html]
|
||||||
)
|
)
|
||||||
|
@ -298,7 +303,8 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_filters_params
|
def set_filters_params
|
||||||
params[:sort] ||= 'id_desc'
|
set_default_sort
|
||||||
|
|
||||||
params[:scope] = 'all' if params[:scope].blank?
|
params[:scope] = 'all' if params[:scope].blank?
|
||||||
params[:state] = 'opened' if params[:state].blank?
|
params[:state] = 'opened' if params[:state].blank?
|
||||||
|
|
||||||
|
@ -405,4 +411,31 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
current_user.nil? && root_path == request.path
|
current_user.nil? && root_path == request.path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def can_collaborate_with_project?(project = nil)
|
||||||
|
project ||= @project
|
||||||
|
|
||||||
|
can?(current_user, :push_code, project) ||
|
||||||
|
(current_user && current_user.already_forked?(project))
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_default_sort
|
||||||
|
key = if is_a_listing_page_for?('issues') || is_a_listing_page_for?('merge_requests')
|
||||||
|
'issuable_sort'
|
||||||
|
end
|
||||||
|
|
||||||
|
cookies[key] = params[:sort] if key && params[:sort].present?
|
||||||
|
params[:sort] = cookies[key] if key
|
||||||
|
params[:sort] ||= 'id_desc'
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_a_listing_page_for?(page_type)
|
||||||
|
controller_name, action_name = params.values_at(:controller, :action)
|
||||||
|
|
||||||
|
(controller_name == "projects/#{page_type}" && action_name == 'index') ||
|
||||||
|
(controller_name == 'groups' && action_name == page_type) ||
|
||||||
|
(controller_name == 'dashboard' && action_name == page_type)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,52 +3,5 @@ module Ci
|
||||||
def self.railtie_helpers_paths
|
def self.railtie_helpers_paths
|
||||||
"app/helpers/ci"
|
"app/helpers/ci"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def authorize_access_project!
|
|
||||||
unless can?(current_user, :read_project, project)
|
|
||||||
return page_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def authorize_manage_builds!
|
|
||||||
unless can?(current_user, :manage_builds, project)
|
|
||||||
return page_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def authenticate_admin!
|
|
||||||
return render_404 unless current_user.is_admin?
|
|
||||||
end
|
|
||||||
|
|
||||||
def authorize_manage_project!
|
|
||||||
unless can?(current_user, :admin_project, project)
|
|
||||||
return page_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def page_404
|
|
||||||
render file: "#{Rails.root}/public/404.html", status: 404, layout: false
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_headers
|
|
||||||
headers['X-Frame-Options'] = 'DENY'
|
|
||||||
headers['X-XSS-Protection'] = '1; mode=block'
|
|
||||||
end
|
|
||||||
|
|
||||||
# JSON for infinite scroll via Pager object
|
|
||||||
def pager_json(partial, count)
|
|
||||||
html = render_to_string(
|
|
||||||
partial,
|
|
||||||
layout: false,
|
|
||||||
formats: [:html]
|
|
||||||
)
|
|
||||||
|
|
||||||
render json: {
|
|
||||||
html: html,
|
|
||||||
count: count
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
module Ci
|
module Ci
|
||||||
class ProjectsController < Ci::ApplicationController
|
class ProjectsController < Ci::ApplicationController
|
||||||
before_action :project, except: [:index]
|
before_action :project
|
||||||
before_action :authenticate_user!, except: [:index, :build, :badge]
|
before_action :authorize_read_project!, except: [:badge]
|
||||||
before_action :authorize_access_project!, except: [:index, :badge]
|
|
||||||
before_action :no_cache, only: [:badge]
|
before_action :no_cache, only: [:badge]
|
||||||
|
skip_before_action :authenticate_user!, only: [:badge]
|
||||||
protect_from_forgery
|
protect_from_forgery
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
@ -13,9 +13,14 @@ module Ci
|
||||||
|
|
||||||
# Project status badge
|
# Project status badge
|
||||||
# Image with build status for sha or ref
|
# Image with build status for sha or ref
|
||||||
|
#
|
||||||
|
# This action in DEPRECATED, this is here only for backwards compatibility
|
||||||
|
# with projects migrated from GitLab CI.
|
||||||
|
#
|
||||||
def badge
|
def badge
|
||||||
image = Ci::ImageForBuildService.new.execute(@project, params)
|
return render_404 unless @project
|
||||||
|
|
||||||
|
image = Ci::ImageForBuildService.new.execute(@project, params)
|
||||||
send_file image.path, filename: image.name, disposition: 'inline', type:"image/svg+xml"
|
send_file image.path, filename: image.name, disposition: 'inline', type:"image/svg+xml"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -13,17 +13,11 @@ module CreatesCommit
|
||||||
result = service.new(@tree_edit_project, current_user, commit_params).execute
|
result = service.new(@tree_edit_project, current_user, commit_params).execute
|
||||||
|
|
||||||
if result[:status] == :success
|
if result[:status] == :success
|
||||||
flash[:notice] = success_notice || "Your changes have been successfully committed."
|
update_flash_notice(success_notice)
|
||||||
|
|
||||||
if create_merge_request?
|
|
||||||
success_path = new_merge_request_path
|
|
||||||
target = different_project? ? "project" : "branch"
|
|
||||||
flash[:notice] << " You can now submit a merge request to get this change into the original #{target}."
|
|
||||||
end
|
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to success_path }
|
format.html { redirect_to final_success_path(success_path) }
|
||||||
format.json { render json: { message: "success", filePath: success_path } }
|
format.json { render json: { message: "success", filePath: final_success_path(success_path) } }
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
flash[:alert] = result[:message]
|
flash[:alert] = result[:message]
|
||||||
|
@ -41,14 +35,32 @@ module CreatesCommit
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorize_edit_tree!
|
def authorize_edit_tree!
|
||||||
return if can?(current_user, :push_code, project)
|
return if can_collaborate_with_project?
|
||||||
return if current_user && current_user.already_forked?(project)
|
|
||||||
|
|
||||||
access_denied!
|
access_denied!
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def update_flash_notice(success_notice)
|
||||||
|
flash[:notice] = success_notice || "Your changes have been successfully committed."
|
||||||
|
|
||||||
|
if create_merge_request?
|
||||||
|
if merge_request_exists?
|
||||||
|
flash[:notice] = nil
|
||||||
|
else
|
||||||
|
target = different_project? ? "project" : "branch"
|
||||||
|
flash[:notice] << " You can now submit a merge request to get this change into the original #{target}."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def final_success_path(success_path)
|
||||||
|
return success_path unless create_merge_request?
|
||||||
|
|
||||||
|
merge_request_exists? ? existing_merge_request_path : new_merge_request_path
|
||||||
|
end
|
||||||
|
|
||||||
def new_merge_request_path
|
def new_merge_request_path
|
||||||
new_namespace_project_merge_request_path(
|
new_namespace_project_merge_request_path(
|
||||||
@mr_source_project.namespace,
|
@mr_source_project.namespace,
|
||||||
|
@ -62,6 +74,19 @@ module CreatesCommit
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def existing_merge_request_path
|
||||||
|
namespace_project_merge_request_path(@mr_target_project.namespace, @mr_target_project, @merge_request)
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_request_exists?
|
||||||
|
return @merge_request if defined?(@merge_request)
|
||||||
|
|
||||||
|
@merge_request = @mr_target_project.merge_requests.opened.find_by(
|
||||||
|
source_branch: @mr_source_branch,
|
||||||
|
target_branch: @mr_target_branch
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def different_project?
|
def different_project?
|
||||||
@mr_source_project != @mr_target_project
|
@mr_source_project != @mr_target_project
|
||||||
end
|
end
|
||||||
|
@ -75,7 +100,7 @@ module CreatesCommit
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_commit_variables
|
def set_commit_variables
|
||||||
@mr_source_branch = @target_branch
|
@mr_source_branch ||= @target_branch
|
||||||
|
|
||||||
if can?(current_user, :push_code, @project)
|
if can?(current_user, :push_code, @project)
|
||||||
# Edit file in this project
|
# Edit file in this project
|
||||||
|
@ -89,7 +114,7 @@ module CreatesCommit
|
||||||
else
|
else
|
||||||
# Merge request to this project
|
# Merge request to this project
|
||||||
@mr_target_project = @project
|
@mr_target_project = @project
|
||||||
@mr_target_branch = @ref
|
@mr_target_branch ||= @ref
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Edit file in fork
|
# Edit file in fork
|
||||||
|
@ -97,7 +122,7 @@ module CreatesCommit
|
||||||
# Merge request from fork to this project
|
# Merge request from fork to this project
|
||||||
@mr_source_project = @tree_edit_project
|
@mr_source_project = @tree_edit_project
|
||||||
@mr_target_project = @project
|
@mr_target_project = @project
|
||||||
@mr_target_branch = @ref
|
@mr_target_branch ||= @ref
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,8 @@ module IssuesAction
|
||||||
@issues = @issues.page(params[:page]).per(ApplicationController::PER_PAGE)
|
@issues = @issues.page(params[:page]).per(ApplicationController::PER_PAGE)
|
||||||
@issues = @issues.preload(:author, :project)
|
@issues = @issues.preload(:author, :project)
|
||||||
|
|
||||||
|
@label = @issuable_finder.labels.first
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.atom { render layout: false }
|
format.atom { render layout: false }
|
||||||
|
|
|
@ -5,5 +5,7 @@ module MergeRequestsAction
|
||||||
@merge_requests = get_merge_requests_collection
|
@merge_requests = get_merge_requests_collection
|
||||||
@merge_requests = @merge_requests.page(params[:page]).per(ApplicationController::PER_PAGE)
|
@merge_requests = @merge_requests.page(params[:page]).per(ApplicationController::PER_PAGE)
|
||||||
@merge_requests = @merge_requests.preload(:author, :target_project)
|
@merge_requests = @merge_requests.preload(:author, :target_project)
|
||||||
|
|
||||||
|
@label = @issuable_finder.labels.first
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,16 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@projects = current_user.authorized_projects.sorted_by_activity.non_archived
|
@projects = current_user.authorized_projects.sorted_by_activity.non_archived
|
||||||
|
@projects = @projects.sort(@sort = params[:sort])
|
||||||
@projects = @projects.includes(:namespace)
|
@projects = @projects.includes(:namespace)
|
||||||
|
|
||||||
|
terms = params[:filter_projects]
|
||||||
|
|
||||||
|
if terms.present?
|
||||||
|
@projects = @projects.search(terms)
|
||||||
|
end
|
||||||
|
|
||||||
|
@projects = @projects.page(params[:page]).per(PER_PAGE)
|
||||||
@last_push = current_user.recent_push
|
@last_push = current_user.recent_push
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
@ -13,6 +22,11 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
||||||
load_events
|
load_events
|
||||||
render layout: false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
format.json do
|
||||||
|
render json: {
|
||||||
|
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -20,6 +34,14 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
||||||
@projects = current_user.starred_projects
|
@projects = current_user.starred_projects
|
||||||
@projects = @projects.includes(:namespace, :forked_from_project, :tags)
|
@projects = @projects.includes(:namespace, :forked_from_project, :tags)
|
||||||
@projects = @projects.sort(@sort = params[:sort])
|
@projects = @projects.sort(@sort = params[:sort])
|
||||||
|
|
||||||
|
terms = params[:filter_projects]
|
||||||
|
|
||||||
|
if terms.present?
|
||||||
|
@projects = @projects.search(terms)
|
||||||
|
end
|
||||||
|
|
||||||
|
@projects = @projects.page(params[:page]).per(PER_PAGE)
|
||||||
@last_push = current_user.recent_push
|
@last_push = current_user.recent_push
|
||||||
@groups = []
|
@groups = []
|
||||||
|
|
||||||
|
@ -27,8 +49,9 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
||||||
format.html
|
format.html
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
load_events
|
render json: {
|
||||||
pager_json("events/_events", @events.count)
|
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -36,7 +59,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_events
|
def load_events
|
||||||
@events = Event.in_projects(@projects.pluck(:id))
|
@events = Event.in_projects(@projects)
|
||||||
@events = @event_filter.apply_filter(@events).with_associations
|
@events = @event_filter.apply_filter(@events).with_associations
|
||||||
@events = @events.limit(20).offset(params[:offset] || 0)
|
@events = @events.limit(20).offset(params[:offset] || 0)
|
||||||
end
|
end
|
||||||
|
|
35
app/controllers/dashboard/todos_controller.rb
Normal file
35
app/controllers/dashboard/todos_controller.rb
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
class Dashboard::TodosController < Dashboard::ApplicationController
|
||||||
|
before_action :find_todos, only: [:index, :destroy_all]
|
||||||
|
|
||||||
|
def index
|
||||||
|
@todos = @todos.page(params[:page]).per(PER_PAGE)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
todo.done!
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to dashboard_todos_path, notice: 'Todo was successfully marked as done.' }
|
||||||
|
format.js { render nothing: true }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_all
|
||||||
|
@todos.each(&:done!)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to dashboard_todos_path, notice: 'All todos were marked as done.' }
|
||||||
|
format.js { render nothing: true }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def todo
|
||||||
|
@todo ||= current_user.todos.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_todos
|
||||||
|
@todos = TodosFinder.new(current_user, params).execute
|
||||||
|
end
|
||||||
|
end
|
|
@ -23,14 +23,14 @@ class DashboardController < Dashboard::ApplicationController
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def load_events
|
def load_events
|
||||||
project_ids =
|
projects =
|
||||||
if params[:filter] == "starred"
|
if params[:filter] == "starred"
|
||||||
current_user.starred_projects
|
current_user.starred_projects
|
||||||
else
|
else
|
||||||
current_user.authorized_projects
|
current_user.authorized_projects
|
||||||
end.pluck(:id)
|
end
|
||||||
|
|
||||||
@events = Event.in_projects(project_ids)
|
@events = Event.in_projects(projects)
|
||||||
@events = @event_filter.apply_filter(@events).with_associations
|
@events = @event_filter.apply_filter(@events).with_associations
|
||||||
@events = @events.limit(20).offset(params[:offset] || 0)
|
@events = @events.limit(20).offset(params[:offset] || 0)
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,19 +6,49 @@ class Explore::ProjectsController < Explore::ApplicationController
|
||||||
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
|
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
|
||||||
@projects = @projects.non_archived
|
@projects = @projects.non_archived
|
||||||
@projects = @projects.search(params[:search]) if params[:search].present?
|
@projects = @projects.search(params[:search]) if params[:search].present?
|
||||||
|
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
|
||||||
@projects = @projects.sort(@sort = params[:sort])
|
@projects = @projects.sort(@sort = params[:sort])
|
||||||
@projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE)
|
@projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.json do
|
||||||
|
render json: {
|
||||||
|
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def trending
|
def trending
|
||||||
@trending_projects = TrendingProjectsFinder.new.execute(current_user)
|
@projects = TrendingProjectsFinder.new.execute(current_user)
|
||||||
@trending_projects = @trending_projects.non_archived
|
@projects = @projects.non_archived
|
||||||
@trending_projects = @trending_projects.page(params[:page]).per(PER_PAGE)
|
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
|
||||||
|
@projects = @projects.page(params[:page]).per(PER_PAGE)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.json do
|
||||||
|
render json: {
|
||||||
|
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def starred
|
def starred
|
||||||
@starred_projects = ProjectsFinder.new.execute(current_user)
|
@projects = ProjectsFinder.new.execute(current_user)
|
||||||
@starred_projects = @starred_projects.reorder('star_count DESC')
|
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
|
||||||
@starred_projects = @starred_projects.page(params[:page]).per(PER_PAGE)
|
@projects = @projects.reorder('star_count DESC')
|
||||||
|
@projects = @projects.page(params[:page]).per(PER_PAGE)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.json do
|
||||||
|
render json: {
|
||||||
|
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,18 +2,19 @@ class GroupsController < Groups::ApplicationController
|
||||||
include IssuesAction
|
include IssuesAction
|
||||||
include MergeRequestsAction
|
include MergeRequestsAction
|
||||||
|
|
||||||
skip_before_action :authenticate_user!, only: [:show, :issues, :merge_requests]
|
|
||||||
respond_to :html
|
respond_to :html
|
||||||
before_action :group, except: [:new, :create]
|
|
||||||
|
skip_before_action :authenticate_user!, only: [:index, :show, :issues, :merge_requests]
|
||||||
|
before_action :group, except: [:index, :new, :create]
|
||||||
|
|
||||||
# Authorize
|
# Authorize
|
||||||
before_action :authorize_read_group!, except: [:show, :new, :create, :autocomplete]
|
before_action :authorize_read_group!, except: [:index, :show, :new, :create, :autocomplete]
|
||||||
before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects]
|
before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects]
|
||||||
before_action :authorize_create_group!, only: [:new, :create]
|
before_action :authorize_create_group!, only: [:new, :create]
|
||||||
|
|
||||||
# Load group projects
|
# Load group projects
|
||||||
before_action :load_projects, except: [:new, :create, :projects, :edit, :update, :autocomplete]
|
before_action :load_projects, except: [:index, :new, :create, :projects, :edit, :update, :autocomplete]
|
||||||
before_action :event_filter, only: :show
|
before_action :event_filter, only: [:show, :events]
|
||||||
|
|
||||||
layout :determine_layout
|
layout :determine_layout
|
||||||
|
|
||||||
|
@ -40,13 +41,16 @@ class GroupsController < Groups::ApplicationController
|
||||||
def show
|
def show
|
||||||
@last_push = current_user.recent_push if current_user
|
@last_push = current_user.recent_push if current_user
|
||||||
@projects = @projects.includes(:namespace)
|
@projects = @projects.includes(:namespace)
|
||||||
|
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
|
||||||
|
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
load_events
|
render json: {
|
||||||
pager_json("events/_events", @events.count)
|
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
format.atom do
|
format.atom do
|
||||||
|
@ -56,6 +60,15 @@ class GroupsController < Groups::ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def events
|
||||||
|
respond_to do |format|
|
||||||
|
format.json do
|
||||||
|
load_events
|
||||||
|
pager_json("events/_events", @events.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -81,16 +94,13 @@ class GroupsController < Groups::ApplicationController
|
||||||
|
|
||||||
def group
|
def group
|
||||||
@group ||= Group.find_by(path: params[:id])
|
@group ||= Group.find_by(path: params[:id])
|
||||||
|
@group || render_404
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_projects
|
def load_projects
|
||||||
@projects ||= ProjectsFinder.new.execute(current_user, group: group).sorted_by_activity.non_archived
|
@projects ||= ProjectsFinder.new.execute(current_user, group: group).sorted_by_activity.non_archived
|
||||||
end
|
end
|
||||||
|
|
||||||
def project_ids
|
|
||||||
@projects.pluck(:id)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Dont allow unauthorized access to group
|
# Dont allow unauthorized access to group
|
||||||
def authorize_read_group!
|
def authorize_read_group!
|
||||||
unless @group and (@projects.present? or can?(current_user, :read_group, @group))
|
unless @group and (@projects.present? or can?(current_user, :read_group, @group))
|
||||||
|
@ -123,7 +133,7 @@ class GroupsController < Groups::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_events
|
def load_events
|
||||||
@events = Event.in_projects(project_ids)
|
@events = Event.in_projects(@projects)
|
||||||
@events = event_filter.apply_filter(@events).with_associations
|
@events = event_filter.apply_filter(@events).with_associations
|
||||||
@events = @events.limit(20).offset(params[:offset] || 0)
|
@events = @events.limit(20).offset(params[:offset] || 0)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
|
include AuthenticatesWithTwoFactor
|
||||||
|
|
||||||
protect_from_forgery except: [:kerberos, :saml, :cas3]
|
protect_from_forgery except: [:kerberos, :saml, :cas3]
|
||||||
|
|
||||||
|
@ -29,14 +30,38 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
|
|
||||||
# Do additional LDAP checks for the user filter and EE features
|
# Do additional LDAP checks for the user filter and EE features
|
||||||
if ldap_user.allowed?
|
if ldap_user.allowed?
|
||||||
log_audit_event(@user, with: :ldap)
|
if @user.two_factor_enabled?
|
||||||
sign_in_and_redirect(@user)
|
prompt_for_two_factor(@user)
|
||||||
|
else
|
||||||
|
log_audit_event(@user, with: :ldap)
|
||||||
|
sign_in_and_redirect(@user)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
flash[:alert] = "Access denied for your LDAP account."
|
flash[:alert] = "Access denied for your LDAP account."
|
||||||
redirect_to new_user_session_path
|
redirect_to new_user_session_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def saml
|
||||||
|
if current_user
|
||||||
|
log_audit_event(current_user, with: :saml)
|
||||||
|
# Update SAML identity if data has changed.
|
||||||
|
identity = current_user.identities.find_by(extern_uid: oauth['uid'], provider: :saml)
|
||||||
|
if identity.nil?
|
||||||
|
current_user.identities.create(extern_uid: oauth['uid'], provider: :saml)
|
||||||
|
redirect_to profile_account_path, notice: 'Authentication method updated'
|
||||||
|
else
|
||||||
|
redirect_to after_sign_in_path_for(current_user)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
saml_user = Gitlab::Saml::User.new(oauth)
|
||||||
|
saml_user.save
|
||||||
|
@user = saml_user.gl_user
|
||||||
|
|
||||||
|
continue_login_process
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def omniauth_error
|
def omniauth_error
|
||||||
@provider = params[:provider]
|
@provider = params[:provider]
|
||||||
@error = params[:error]
|
@error = params[:error]
|
||||||
|
@ -60,25 +85,11 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
log_audit_event(current_user, with: oauth['provider'])
|
log_audit_event(current_user, with: oauth['provider'])
|
||||||
redirect_to profile_account_path, notice: 'Authentication method updated'
|
redirect_to profile_account_path, notice: 'Authentication method updated'
|
||||||
else
|
else
|
||||||
@user = Gitlab::OAuth::User.new(oauth)
|
oauth_user = Gitlab::OAuth::User.new(oauth)
|
||||||
@user.save
|
oauth_user.save
|
||||||
|
@user = oauth_user.gl_user
|
||||||
|
|
||||||
# Only allow properly saved users to login.
|
continue_login_process
|
||||||
if @user.persisted? && @user.valid?
|
|
||||||
log_audit_event(@user.gl_user, with: oauth['provider'])
|
|
||||||
sign_in_and_redirect(@user.gl_user)
|
|
||||||
else
|
|
||||||
error_message =
|
|
||||||
if @user.gl_user.errors.any?
|
|
||||||
@user.gl_user.errors.map do |attribute, message|
|
|
||||||
"#{attribute} #{message}"
|
|
||||||
end.join(", ")
|
|
||||||
else
|
|
||||||
''
|
|
||||||
end
|
|
||||||
|
|
||||||
redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
rescue Gitlab::OAuth::SignupDisabledError
|
rescue Gitlab::OAuth::SignupDisabledError
|
||||||
label = Gitlab::OAuth::Provider.label_for(oauth['provider'])
|
label = Gitlab::OAuth::Provider.label_for(oauth['provider'])
|
||||||
|
@ -99,6 +110,18 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
session[:service_tickets][provider] = ticket
|
session[:service_tickets][provider] = ticket
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def continue_login_process
|
||||||
|
# Only allow properly saved users to login.
|
||||||
|
if @user.persisted? && @user.valid?
|
||||||
|
log_audit_event(@user, with: oauth['provider'])
|
||||||
|
sign_in_and_redirect(@user)
|
||||||
|
else
|
||||||
|
error_message = @user.errors.full_messages.to_sentence
|
||||||
|
|
||||||
|
redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def oauth
|
def oauth
|
||||||
@oauth ||= request.env['omniauth.auth']
|
@oauth ||= request.env['omniauth.auth']
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,11 +12,13 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
|
||||||
|
|
||||||
current_user.save! if current_user.changed?
|
current_user.save! if current_user.changed?
|
||||||
|
|
||||||
if two_factor_grace_period_expired?
|
if two_factor_authentication_required?
|
||||||
flash.now[:alert] = 'You must configure Two-Factor Authentication in your account.'
|
if two_factor_grace_period_expired?
|
||||||
else
|
flash.now[:alert] = 'You must enable Two-factor Authentication for your account.'
|
||||||
grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
|
else
|
||||||
flash.now[:alert] = "You must configure Two-Factor Authentication in your account until #{l(grace_period_deadline)}."
|
grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
|
||||||
|
flash.now[:alert] = "You must enable Two-factor Authentication for your account before #{l(grace_period_deadline)}."
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@qr_code = build_qr_code
|
@qr_code = build_qr_code
|
||||||
|
|
|
@ -28,6 +28,11 @@ class Projects::ApplicationController < ApplicationController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def apply_diff_view_cookie!
|
||||||
|
view = params[:view] || cookies[:diff_view]
|
||||||
|
cookies.permanent[:diff_view] = params[:view] = view if view
|
||||||
|
end
|
||||||
|
|
||||||
def builds_enabled
|
def builds_enabled
|
||||||
return render_404 unless @project.builds_enabled?
|
return render_404 unless @project.builds_enabled?
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class Projects::ArtifactsController < Projects::ApplicationController
|
class Projects::ArtifactsController < Projects::ApplicationController
|
||||||
layout 'project'
|
layout 'project'
|
||||||
before_action :authorize_read_build_artifacts!
|
before_action :authorize_read_build!
|
||||||
|
|
||||||
def download
|
def download
|
||||||
unless artifacts_file.file_storage?
|
unless artifacts_file.file_storage?
|
||||||
|
@ -43,14 +43,4 @@ class Projects::ArtifactsController < Projects::ApplicationController
|
||||||
def artifacts_file
|
def artifacts_file
|
||||||
@artifacts_file ||= build.artifacts_file
|
@artifacts_file ||= build.artifacts_file
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorize_read_build_artifacts!
|
|
||||||
unless can?(current_user, :read_build_artifacts, @project)
|
|
||||||
if current_user.nil?
|
|
||||||
return authenticate_user!
|
|
||||||
else
|
|
||||||
return render_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,15 +2,13 @@ class Projects::AvatarsController < Projects::ApplicationController
|
||||||
before_action :project
|
before_action :project
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@blob = @project.repository.blob_at_branch('master', @project.avatar_in_git)
|
@blob = @repository.blob_at_branch('master', @project.avatar_in_git)
|
||||||
if @blob
|
if @blob
|
||||||
headers['X-Content-Type-Options'] = 'nosniff'
|
headers['X-Content-Type-Options'] = 'nosniff'
|
||||||
send_data(
|
headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob))
|
||||||
@blob.data,
|
headers['Content-Disposition'] = 'inline'
|
||||||
type: @blob.mime_type,
|
headers['Content-Type'] = @blob.content_type
|
||||||
disposition: 'inline',
|
head :ok # 'render nothing: true' messes up the Content-Type
|
||||||
filename: @blob.name
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|
24
app/controllers/projects/badges_controller.rb
Normal file
24
app/controllers/projects/badges_controller.rb
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
class Projects::BadgesController < Projects::ApplicationController
|
||||||
|
before_action :set_no_cache
|
||||||
|
|
||||||
|
def build
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { render_404 }
|
||||||
|
format.svg do
|
||||||
|
image = Ci::ImageForBuildService.new.execute(project, ref: params[:ref])
|
||||||
|
send_file(image.path, filename: image.name, disposition: 'inline', type: 'image/svg+xml')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_no_cache
|
||||||
|
expires_now
|
||||||
|
|
||||||
|
# Add some deprecated headers for older agents
|
||||||
|
#
|
||||||
|
response.headers['Pragma'] = 'no-cache'
|
||||||
|
response.headers['Expires'] = 'Fri, 01 Jan 1990 00:00:00 GMT'
|
||||||
|
end
|
||||||
|
end
|
|
@ -33,6 +33,7 @@ class Projects::BlobController < Projects::ApplicationController
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
|
@last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
|
||||||
|
blob.load_all_data!(@repository)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
@ -51,6 +52,7 @@ class Projects::BlobController < Projects::ApplicationController
|
||||||
|
|
||||||
def preview
|
def preview
|
||||||
@content = params[:content]
|
@content = params[:content]
|
||||||
|
@blob.load_all_data!(@repository)
|
||||||
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
|
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
|
||||||
diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
|
diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
|
||||||
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines)
|
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines)
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
class Projects::BuildsController < Projects::ApplicationController
|
class Projects::BuildsController < Projects::ApplicationController
|
||||||
before_action :build, except: [:index, :cancel_all]
|
before_action :build, except: [:index, :cancel_all]
|
||||||
|
before_action :authorize_read_build!, except: [:cancel, :cancel_all, :retry]
|
||||||
before_action :authorize_manage_builds!, except: [:index, :show, :status]
|
before_action :authorize_update_build!, except: [:index, :show, :status]
|
||||||
|
layout 'project'
|
||||||
layout "project"
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@scope = params[:scope]
|
@scope = params[:scope]
|
||||||
|
@ -23,7 +22,6 @@ class Projects::BuildsController < Projects::ApplicationController
|
||||||
|
|
||||||
def cancel_all
|
def cancel_all
|
||||||
@project.builds.running_or_pending.each(&:cancel)
|
@project.builds.running_or_pending.each(&:cancel)
|
||||||
|
|
||||||
redirect_to namespace_project_builds_path(project.namespace, project)
|
redirect_to namespace_project_builds_path(project.namespace, project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -46,18 +44,22 @@ class Projects::BuildsController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
build = Ci::Build.retry(@build)
|
build = Ci::Build.retry(@build)
|
||||||
|
|
||||||
redirect_to build_path(build)
|
redirect_to build_path(build)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cancel
|
||||||
|
@build.cancel
|
||||||
|
redirect_to build_path(@build)
|
||||||
|
end
|
||||||
|
|
||||||
def status
|
def status
|
||||||
render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
|
render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
|
||||||
end
|
end
|
||||||
|
|
||||||
def cancel
|
def erase
|
||||||
@build.cancel
|
@build.erase(erased_by: current_user)
|
||||||
|
redirect_to namespace_project_build_path(project.namespace, project, @build),
|
||||||
redirect_to build_path(@build)
|
notice: "Build has been sucessfully erased!"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -69,10 +71,4 @@ class Projects::BuildsController < Projects::ApplicationController
|
||||||
def build_path(build)
|
def build_path(build)
|
||||||
namespace_project_build_path(build.project.namespace, build.project, build)
|
namespace_project_build_path(build.project.namespace, build.project, build)
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorize_manage_builds!
|
|
||||||
unless can?(current_user, :manage_builds, project)
|
|
||||||
return render_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
#
|
#
|
||||||
# Not to be confused with CommitsController, plural.
|
# Not to be confused with CommitsController, plural.
|
||||||
class Projects::CommitController < Projects::ApplicationController
|
class Projects::CommitController < Projects::ApplicationController
|
||||||
|
include CreatesCommit
|
||||||
|
|
||||||
# Authorize
|
# Authorize
|
||||||
before_action :require_non_empty_project
|
before_action :require_non_empty_project
|
||||||
before_action :authorize_download_code!, except: [:cancel_builds]
|
before_action :authorize_download_code!, except: [:cancel_builds, :retry_builds]
|
||||||
before_action :authorize_manage_builds!, only: [:cancel_builds]
|
before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds]
|
||||||
|
before_action :authorize_read_commit_status!, only: [:builds]
|
||||||
before_action :commit
|
before_action :commit
|
||||||
before_action :authorize_manage_builds!, only: [:cancel_builds, :retry_builds]
|
|
||||||
before_action :define_show_vars, only: [:show, :builds]
|
before_action :define_show_vars, only: [:show, :builds]
|
||||||
|
before_action :authorize_edit_tree!, only: [:revert]
|
||||||
|
|
||||||
def show
|
def show
|
||||||
return git_not_found! unless @commit
|
apply_diff_view_cookie!
|
||||||
|
|
||||||
@line_notes = commit.notes.inline
|
@line_notes = commit.notes.inline
|
||||||
@note = @project.build_commit_note(commit)
|
@note = @project.build_commit_note(commit)
|
||||||
|
@ -55,8 +58,37 @@ class Projects::CommitController < Projects::ApplicationController
|
||||||
render layout: false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def revert
|
||||||
|
assign_revert_commit_vars
|
||||||
|
|
||||||
|
return render_404 if @target_branch.blank?
|
||||||
|
|
||||||
|
create_commit(Commits::RevertService, success_notice: "The #{revert_type_title} has been successfully reverted.",
|
||||||
|
success_path: successful_revert_path, failure_path: failed_revert_path)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def revert_type_title
|
||||||
|
@commit.merged_merge_request ? 'merge request' : 'commit'
|
||||||
|
end
|
||||||
|
|
||||||
|
def successful_revert_path
|
||||||
|
return referenced_merge_request_url if @commit.merged_merge_request
|
||||||
|
|
||||||
|
namespace_project_commits_url(@project.namespace, @project, @target_branch)
|
||||||
|
end
|
||||||
|
|
||||||
|
def failed_revert_path
|
||||||
|
return referenced_merge_request_url if @commit.merged_merge_request
|
||||||
|
|
||||||
|
namespace_project_commit_url(@project.namespace, @project, params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def referenced_merge_request_url
|
||||||
|
namespace_project_merge_request_url(@project.namespace, @project, @commit.merged_merge_request)
|
||||||
|
end
|
||||||
|
|
||||||
def commit
|
def commit
|
||||||
@commit ||= @project.commit(params[:id])
|
@commit ||= @project.commit(params[:id])
|
||||||
end
|
end
|
||||||
|
@ -66,6 +98,8 @@ class Projects::CommitController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def define_show_vars
|
def define_show_vars
|
||||||
|
return git_not_found! unless commit
|
||||||
|
|
||||||
if params[:w].to_i == 1
|
if params[:w].to_i == 1
|
||||||
@diffs = commit.diffs({ ignore_whitespace_change: true })
|
@diffs = commit.diffs({ ignore_whitespace_change: true })
|
||||||
else
|
else
|
||||||
|
@ -78,9 +112,15 @@ class Projects::CommitController < Projects::ApplicationController
|
||||||
@statuses = ci_commit.statuses if ci_commit
|
@statuses = ci_commit.statuses if ci_commit
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorize_manage_builds!
|
def assign_revert_commit_vars
|
||||||
unless can?(current_user, :manage_builds, project)
|
@commit = project.commit(params[:id])
|
||||||
return render_404
|
@target_branch = params[:target_branch]
|
||||||
end
|
@mr_source_branch = @commit.revert_branch_name
|
||||||
|
@mr_target_branch = @target_branch
|
||||||
|
@commit_params = {
|
||||||
|
commit: @commit,
|
||||||
|
revert_type_title: revert_type_title,
|
||||||
|
create_merge_request: params[:create_merge_request].present? || different_project?
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,6 +21,9 @@ class Projects::CommitsController < Projects::ApplicationController
|
||||||
@note_counts = project.notes.where(commit_id: @commits.map(&:id)).
|
@note_counts = project.notes.where(commit_id: @commits.map(&:id)).
|
||||||
group(:commit_id).count
|
group(:commit_id).count
|
||||||
|
|
||||||
|
@merge_request = @project.merge_requests.opened.
|
||||||
|
find_by(source_project: @project, source_branch: @ref, target_branch: @repository.root_ref)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.json { pager_json("projects/commits/_commits", @commits.size) }
|
format.json { pager_json("projects/commits/_commits", @commits.size) }
|
||||||
|
|
|
@ -4,24 +4,23 @@ class Projects::CompareController < Projects::ApplicationController
|
||||||
# Authorize
|
# Authorize
|
||||||
before_action :require_non_empty_project
|
before_action :require_non_empty_project
|
||||||
before_action :authorize_download_code!
|
before_action :authorize_download_code!
|
||||||
|
before_action :assign_ref_vars, only: [:index, :show]
|
||||||
|
before_action :merge_request, only: [:index, :show]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@ref = Addressable::URI.unescape(params[:to])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
base_ref = Addressable::URI.unescape(params[:from])
|
|
||||||
@ref = head_ref = Addressable::URI.unescape(params[:to])
|
|
||||||
diff_options = { ignore_whitespace_change: true } if params[:w] == '1'
|
diff_options = { ignore_whitespace_change: true } if params[:w] == '1'
|
||||||
|
|
||||||
compare_result = CompareService.new.
|
compare_result = CompareService.new.
|
||||||
execute(@project, head_ref, @project, base_ref, diff_options)
|
execute(@project, @head_ref, @project, @base_ref, diff_options)
|
||||||
|
|
||||||
if compare_result
|
if compare_result
|
||||||
@commits = Commit.decorate(compare_result.commits, @project)
|
@commits = Commit.decorate(compare_result.commits, @project)
|
||||||
@diffs = compare_result.diffs
|
@diffs = compare_result.diffs
|
||||||
@commit = @project.commit(head_ref)
|
@commit = @project.commit(@head_ref)
|
||||||
@base_commit = @project.merge_base_commit(base_ref, head_ref)
|
@base_commit = @project.merge_base_commit(@base_ref, @head_ref)
|
||||||
@diff_refs = [@base_commit, @commit]
|
@diff_refs = [@base_commit, @commit]
|
||||||
@line_notes = []
|
@line_notes = []
|
||||||
end
|
end
|
||||||
|
@ -31,4 +30,16 @@ class Projects::CompareController < Projects::ApplicationController
|
||||||
redirect_to namespace_project_compare_path(@project.namespace, @project,
|
redirect_to namespace_project_compare_path(@project.namespace, @project,
|
||||||
params[:from], params[:to])
|
params[:from], params[:to])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def assign_ref_vars
|
||||||
|
@base_ref = Addressable::URI.unescape(params[:from])
|
||||||
|
@ref = @head_ref = Addressable::URI.unescape(params[:to])
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_request
|
||||||
|
@merge_request ||= @project.merge_requests.opened.
|
||||||
|
find_by(source_project: @project, source_branch: @head_ref, target_branch: @base_ref)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,25 @@ class Projects::ForksController < Projects::ApplicationController
|
||||||
before_action :require_non_empty_project
|
before_action :require_non_empty_project
|
||||||
before_action :authorize_download_code!
|
before_action :authorize_download_code!
|
||||||
|
|
||||||
|
def index
|
||||||
|
base_query = project.forks.includes(:creator)
|
||||||
|
|
||||||
|
@forks = if current_user
|
||||||
|
base_query.where('projects.visibility_level IN (?) OR projects.id IN (?)',
|
||||||
|
Project.public_and_internal_levels,
|
||||||
|
current_user.authorized_projects.pluck(:id))
|
||||||
|
else
|
||||||
|
base_query.where('projects.visibility_level = ?', Project::PUBLIC)
|
||||||
|
end
|
||||||
|
|
||||||
|
@total_forks_count = base_query.size
|
||||||
|
@private_forks_count = @total_forks_count - @forks.size
|
||||||
|
@public_forks_count = @total_forks_count - @private_forks_count
|
||||||
|
|
||||||
|
@sort = params[:sort] || 'id_desc'
|
||||||
|
@forks = @forks.order_by(@sort).page(params[:page]).per(PER_PAGE)
|
||||||
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@namespaces = current_user.manageable_namespaces
|
@namespaces = current_user.manageable_namespaces
|
||||||
@namespaces.delete(@project.namespace)
|
@namespaces.delete(@project.namespace)
|
||||||
|
@ -23,7 +42,7 @@ class Projects::ForksController < Projects::ApplicationController
|
||||||
if continue_params
|
if continue_params
|
||||||
redirect_to continue_params[:to], notice: continue_params[:notice]
|
redirect_to continue_params[:to], notice: continue_params[:notice]
|
||||||
else
|
else
|
||||||
redirect_to namespace_project_path(@forked_project.namespace, @forked_project), notice: "The project was successfully forked."
|
redirect_to namespace_project_path(@forked_project.namespace, @forked_project), notice: "The project '#{@forked_project.name}' was successfully forked."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue