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/initializers/rack_attack.rb
|
||||
config/initializers/smtp_settings.rb
|
||||
config/initializers/relative_url.rb
|
||||
config/resque.yml
|
||||
config/unicorn.rb
|
||||
config/secrets.yml
|
||||
|
|
156
.gitlab-ci.yml
156
.gitlab-ci.yml
|
@ -5,11 +5,16 @@ services:
|
|||
- postgres:latest
|
||||
- redis:latest
|
||||
|
||||
cache:
|
||||
key: "ruby21"
|
||||
paths:
|
||||
- vendor
|
||||
|
||||
variables:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
|
||||
|
||||
before_script:
|
||||
- ./scripts/prepare_build.sh
|
||||
- source ./scripts/prepare_build.sh
|
||||
- ruby -v
|
||||
- which ruby
|
||||
- gem install bundler --no-ri --no-rdoc
|
||||
|
@ -17,7 +22,7 @@ before_script:
|
|||
- touch log/application.log
|
||||
- touch log/test.log
|
||||
- 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:
|
||||
script:
|
||||
|
@ -127,10 +132,155 @@ flay:
|
|||
- mysql
|
||||
|
||||
bundler:audit:
|
||||
script:
|
||||
script:
|
||||
- "bundle exec bundle-audit update"
|
||||
- "bundle exec bundle-audit check"
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
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.
|
||||
|
||||
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
|
||||
- Increase lfs_objects size column to 8-byte integer to allow files larger
|
||||
than 2.1GB
|
||||
|
@ -22,12 +180,14 @@ v 8.4.2
|
|||
track them in Performance Monitoring.
|
||||
- Increase contrast between highlighted code comments and inline diff marker
|
||||
- Fix method undefined when using external commit status in builds
|
||||
- Fix highlighting in blame view.
|
||||
|
||||
v 8.4.1
|
||||
- Apply security updates for Rails (4.2.5.1), rails-html-sanitizer (1.0.3),
|
||||
and Nokogiri (1.6.7.2)
|
||||
- Fix redirect loop during import
|
||||
- Fix diff highlighting for all syntax themes
|
||||
- Delete project and associations in a background worker
|
||||
|
||||
v 8.4.0
|
||||
- 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
|
||||
- Add Open Graph and Twitter Card data to all pages
|
||||
- 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
|
||||
- Change single user API endpoint to return more detailed data (Michael Potthoff)
|
||||
- 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)
|
||||
- Bump Redis requirement to 2.8 for Sidekiq 4 (Stan Hu)
|
||||
- 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)
|
||||
- Fix 500 error when update group member permission
|
||||
- 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
|
||||
- Remove CI migration task
|
||||
- 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 build trace updating
|
||||
- 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
|
||||
|
||||
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)
|
||||
|
||||
(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
|
||||
|
||||
|
@ -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
|
||||
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
|
||||
|
||||
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. 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
|
||||
and make sure to read the [documentation styleguide][doc-styleguide]
|
||||
1. If you have multiple commits please combine them into one commit by
|
||||
[squashing them][git-squash]
|
||||
1. Push the commit(s) to your fork
|
||||
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 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 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`
|
||||
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
|
||||
|
@ -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][].
|
||||
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
|
||||
|
||||
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. Working and clean code that is commented where needed
|
||||
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. Reviewed and any concerns are addressed
|
||||
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. 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
|
||||
|
||||
1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
|
||||
|
@ -336,7 +410,7 @@ merge request:
|
|||
contributors to enhance security
|
||||
1. [Database Migrations](doc/development/migration_style_guide.md)
|
||||
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
|
||||
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
|
||||
|
@ -377,7 +451,7 @@ reported by emailing `contact@gitlab.com`.
|
|||
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/).
|
||||
|
||||
[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/
|
||||
[Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
|
||||
[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
|
||||
[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
|
||||
[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"
|
||||
|
||||
gem 'rails', '4.2.5.1'
|
||||
gem 'rails', '4.2.5.2'
|
||||
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
|
||||
|
||||
# Responders respond_to and respond_with
|
||||
|
@ -21,7 +21,7 @@ gem "pg", '~> 0.18.2', group: :postgres
|
|||
gem 'devise', '~> 3.5.4'
|
||||
gem 'devise-async', '~> 0.9.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-bitbucket', '~> 0.0.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-google-oauth2', '~> 0.2.0'
|
||||
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-twitter', '~> 1.2.0'
|
||||
gem 'omniauth_crowd', '~> 2.2.0'
|
||||
gem 'rack-oauth2', '~> 1.2.1'
|
||||
|
||||
# reCAPTCHA protection
|
||||
# Spam and anti-bot protection
|
||||
gem 'recaptcha', require: 'recaptcha/rails'
|
||||
gem 'akismet', '~> 2.0'
|
||||
|
||||
# Two-factor authentication
|
||||
gem 'devise-two-factor', '~> 2.0.0'
|
||||
|
@ -49,7 +50,7 @@ gem "browser", '~> 1.0.0'
|
|||
|
||||
# Extracting information from a git repository
|
||||
# Provide access to Gitlab::Git library
|
||||
gem "gitlab_git", '~> 7.2.22'
|
||||
gem "gitlab_git", '~> 8.2'
|
||||
|
||||
# LDAP Auth
|
||||
# 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
|
||||
# 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
|
||||
gem 'diffy', '~> 3.0.3'
|
||||
|
@ -179,6 +180,9 @@ gem "underscore-rails", "~> 1.8.0"
|
|||
gem "sanitize", '~> 2.0'
|
||||
gem 'babosa', '~> 1.0.2'
|
||||
|
||||
# Sanitizes SVG input
|
||||
gem "loofah", "~> 2.0.3"
|
||||
|
||||
# Protect against bruteforcing
|
||||
gem "rack-attack", '~> 4.3.1'
|
||||
|
||||
|
@ -200,7 +204,7 @@ gem 'jquery-turbolinks', '~> 2.1.0'
|
|||
gem 'addressable', '~> 2.3.8'
|
||||
gem 'bootstrap-sass', '~> 3.3.0'
|
||||
gem 'font-awesome-rails', '~> 4.2'
|
||||
gem 'gitlab_emoji', '~> 0.2.0'
|
||||
gem 'gitlab_emoji', '~> 0.3.0'
|
||||
gem 'gon', '~> 6.0.1'
|
||||
gem 'jquery-atwho-rails', '~> 1.3.2'
|
||||
gem 'jquery-rails', '~> 4.0.0'
|
||||
|
@ -213,6 +217,9 @@ gem 'select2-rails', '~> 3.5.9'
|
|||
gem 'virtus', '~> 1.0.1'
|
||||
gem 'net-ssh', '~> 3.0.1'
|
||||
|
||||
# Sentry integration
|
||||
gem 'sentry-raven', '~> 0.15'
|
||||
|
||||
# Metrics
|
||||
group :metrics do
|
||||
gem 'allocations', '~> 1.0', require: false, platform: :mri
|
||||
|
@ -294,15 +301,11 @@ end
|
|||
|
||||
group :production do
|
||||
gem "gitlab_meta", '7.0'
|
||||
|
||||
# Sentry integration
|
||||
gem 'sentry-raven'
|
||||
end
|
||||
|
||||
gem "newrelic_rpm", '~> 3.9.4.245'
|
||||
gem 'newrelic-grape'
|
||||
gem "newrelic_rpm", '~> 3.14'
|
||||
|
||||
gem 'octokit', '~> 3.7.0'
|
||||
gem 'octokit', '~> 3.8.0'
|
||||
|
||||
gem "mail_room", "~> 0.6.1"
|
||||
|
||||
|
|
115
Gemfile.lock
115
Gemfile.lock
|
@ -4,41 +4,41 @@ GEM
|
|||
CFPropertyList (2.3.2)
|
||||
RedCloth (4.2.9)
|
||||
ace-rails-ap (2.0.1)
|
||||
actionmailer (4.2.5.1)
|
||||
actionpack (= 4.2.5.1)
|
||||
actionview (= 4.2.5.1)
|
||||
activejob (= 4.2.5.1)
|
||||
actionmailer (4.2.5.2)
|
||||
actionpack (= 4.2.5.2)
|
||||
actionview (= 4.2.5.2)
|
||||
activejob (= 4.2.5.2)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.5.1)
|
||||
actionview (= 4.2.5.1)
|
||||
activesupport (= 4.2.5.1)
|
||||
actionpack (4.2.5.2)
|
||||
actionview (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (4.2.5.1)
|
||||
activesupport (= 4.2.5.1)
|
||||
actionview (4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
activejob (4.2.5.1)
|
||||
activesupport (= 4.2.5.1)
|
||||
activejob (4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
globalid (>= 0.3.0)
|
||||
activemodel (4.2.5.1)
|
||||
activesupport (= 4.2.5.1)
|
||||
activemodel (4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.5.1)
|
||||
activemodel (= 4.2.5.1)
|
||||
activesupport (= 4.2.5.1)
|
||||
activerecord (4.2.5.2)
|
||||
activemodel (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
arel (~> 6.0)
|
||||
activerecord-deprecated_finders (1.0.4)
|
||||
activerecord-session_store (0.1.2)
|
||||
actionpack (>= 4.0.0, < 5)
|
||||
activerecord (>= 4.0.0, < 5)
|
||||
railties (>= 4.0.0, < 5)
|
||||
activesupport (4.2.5.1)
|
||||
activesupport (4.2.5.2)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
|
@ -49,7 +49,8 @@ GEM
|
|||
addressable (2.3.8)
|
||||
after_commit_queue (1.3.0)
|
||||
activerecord (>= 3.0)
|
||||
allocations (1.0.3)
|
||||
akismet (2.0.0)
|
||||
allocations (1.0.4)
|
||||
annotate (2.6.10)
|
||||
activerecord (>= 3.2, <= 4.3)
|
||||
rake (~> 10.4)
|
||||
|
@ -335,11 +336,11 @@ GEM
|
|||
ruby-progressbar (~> 1.4)
|
||||
gemnasium-gitlab-service (0.2.6)
|
||||
rugged (~> 0.21)
|
||||
gemojione (2.1.1)
|
||||
gemojione (2.2.1)
|
||||
json
|
||||
get_process_mem (0.2.0)
|
||||
gherkin-ruby (0.3.2)
|
||||
github-linguist (4.7.3)
|
||||
github-linguist (4.7.5)
|
||||
charlock_holmes (~> 0.7.3)
|
||||
escape_utils (~> 1.1.0)
|
||||
mime-types (>= 1.19)
|
||||
|
@ -354,13 +355,13 @@ GEM
|
|||
diff-lcs (~> 1.1)
|
||||
mime-types (~> 1.15)
|
||||
posix-spawn (~> 0.3)
|
||||
gitlab_emoji (0.2.0)
|
||||
gemojione (~> 2.1)
|
||||
gitlab_git (7.2.24)
|
||||
gitlab_emoji (0.3.1)
|
||||
gemojione (~> 2.2, >= 2.2.1)
|
||||
gitlab_git (8.2.0)
|
||||
activesupport (~> 4.0)
|
||||
charlock_holmes (~> 0.7.3)
|
||||
github-linguist (~> 4.7.0)
|
||||
rugged (~> 0.23.3)
|
||||
rugged (~> 0.24.0b13)
|
||||
gitlab_meta (7.0)
|
||||
gitlab_omniauth-ldap (1.2.1)
|
||||
net-ldap (~> 0.9)
|
||||
|
@ -478,10 +479,7 @@ GEM
|
|||
net-ldap (0.12.1)
|
||||
net-ssh (3.0.1)
|
||||
netrc (0.11.0)
|
||||
newrelic-grape (2.1.0)
|
||||
grape
|
||||
newrelic_rpm
|
||||
newrelic_rpm (3.9.4.245)
|
||||
newrelic_rpm (3.14.1.311)
|
||||
nokogiri (1.6.7.2)
|
||||
mini_portile2 (~> 2.0.0.rc2)
|
||||
nprogress-rails (0.1.6.7)
|
||||
|
@ -492,11 +490,11 @@ GEM
|
|||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (~> 1.2)
|
||||
octokit (3.7.1)
|
||||
octokit (3.8.0)
|
||||
sawyer (~> 0.6.0, >= 0.5.3)
|
||||
omniauth (1.2.2)
|
||||
omniauth (1.3.1)
|
||||
hashie (>= 1.2, < 4)
|
||||
rack (~> 1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
omniauth-azure-oauth2 (0.0.6)
|
||||
jwt (~> 1.0)
|
||||
omniauth (~> 1.0)
|
||||
|
@ -534,9 +532,9 @@ GEM
|
|||
omniauth-oauth2 (1.3.1)
|
||||
oauth2 (~> 1.0)
|
||||
omniauth (~> 1.2)
|
||||
omniauth-saml (1.4.1)
|
||||
omniauth-saml (1.4.2)
|
||||
omniauth (~> 1.1)
|
||||
ruby-saml (~> 1.0.0)
|
||||
ruby-saml (~> 1.1, >= 1.1.1)
|
||||
omniauth-shibboleth (1.2.1)
|
||||
omniauth (>= 1.0.0)
|
||||
omniauth-twitter (1.2.1)
|
||||
|
@ -588,16 +586,16 @@ GEM
|
|||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.2.5.1)
|
||||
actionmailer (= 4.2.5.1)
|
||||
actionpack (= 4.2.5.1)
|
||||
actionview (= 4.2.5.1)
|
||||
activejob (= 4.2.5.1)
|
||||
activemodel (= 4.2.5.1)
|
||||
activerecord (= 4.2.5.1)
|
||||
activesupport (= 4.2.5.1)
|
||||
rails (4.2.5.2)
|
||||
actionmailer (= 4.2.5.2)
|
||||
actionpack (= 4.2.5.2)
|
||||
actionview (= 4.2.5.2)
|
||||
activejob (= 4.2.5.2)
|
||||
activemodel (= 4.2.5.2)
|
||||
activerecord (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.5.1)
|
||||
railties (= 4.2.5.2)
|
||||
sprockets-rails
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
|
@ -607,9 +605,9 @@ GEM
|
|||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
railties (4.2.5.1)
|
||||
actionpack (= 4.2.5.1)
|
||||
activesupport (= 4.2.5.1)
|
||||
railties (4.2.5.2)
|
||||
actionpack (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.0.0)
|
||||
|
@ -692,7 +690,7 @@ GEM
|
|||
ruby-fogbugz (0.2.1)
|
||||
crack (~> 0.4)
|
||||
ruby-progressbar (1.7.5)
|
||||
ruby-saml (1.0.0)
|
||||
ruby-saml (1.1.1)
|
||||
nokogiri (>= 1.5.10)
|
||||
uuid (~> 2.3)
|
||||
ruby2ruby (2.2.0)
|
||||
|
@ -703,7 +701,7 @@ GEM
|
|||
rubyntlm (0.5.2)
|
||||
rubypants (0.2.0)
|
||||
rufus-scheduler (3.1.10)
|
||||
rugged (0.23.3)
|
||||
rugged (0.24.0b13)
|
||||
safe_yaml (1.0.4)
|
||||
sanitize (2.1.0)
|
||||
nokogiri (>= 1.4.4)
|
||||
|
@ -725,7 +723,7 @@ GEM
|
|||
activesupport (>= 3.1, < 4.3)
|
||||
select2-rails (3.5.9.3)
|
||||
thor (~> 0.14)
|
||||
sentry-raven (0.15.4)
|
||||
sentry-raven (0.15.6)
|
||||
faraday (>= 0.7.6)
|
||||
settingslogic (2.0.9)
|
||||
sexp_processor (4.6.0)
|
||||
|
@ -884,6 +882,7 @@ DEPENDENCIES
|
|||
acts-as-taggable-on (~> 3.4)
|
||||
addressable (~> 2.3.8)
|
||||
after_commit_queue
|
||||
akismet (~> 2.0)
|
||||
allocations (~> 1.0)
|
||||
annotate (~> 2.6.0)
|
||||
asana (~> 0.4.0)
|
||||
|
@ -933,8 +932,8 @@ DEPENDENCIES
|
|||
github-linguist (~> 4.7.0)
|
||||
github-markup (~> 1.3.1)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab_emoji (~> 0.2.0)
|
||||
gitlab_git (~> 7.2.22)
|
||||
gitlab_emoji (~> 0.3.0)
|
||||
gitlab_git (~> 8.2)
|
||||
gitlab_meta (= 7.0)
|
||||
gitlab_omniauth-ldap (~> 1.2.1)
|
||||
gollum-lib (~> 4.1.0)
|
||||
|
@ -953,6 +952,7 @@ DEPENDENCIES
|
|||
jquery-ui-rails (~> 5.0.0)
|
||||
kaminari (~> 0.16.3)
|
||||
letter_opener (~> 1.1.2)
|
||||
loofah (~> 2.0.3)
|
||||
mail_room (~> 0.6.1)
|
||||
method_source (~> 0.8)
|
||||
minitest (~> 5.7.0)
|
||||
|
@ -960,13 +960,12 @@ DEPENDENCIES
|
|||
mysql2 (~> 0.3.16)
|
||||
nested_form (~> 0.3.2)
|
||||
net-ssh (~> 3.0.1)
|
||||
newrelic-grape
|
||||
newrelic_rpm (~> 3.9.4.245)
|
||||
nokogiri (= 1.6.7.2)
|
||||
newrelic_rpm (~> 3.14)
|
||||
nokogiri (~> 1.6.7, >= 1.6.7.2)
|
||||
nprogress-rails (~> 0.1.6.7)
|
||||
oauth2 (~> 1.0.0)
|
||||
octokit (~> 3.7.0)
|
||||
omniauth (~> 1.2.2)
|
||||
octokit (~> 3.8.0)
|
||||
omniauth (~> 1.3.1)
|
||||
omniauth-azure-oauth2 (~> 0.0.6)
|
||||
omniauth-bitbucket (~> 0.0.2)
|
||||
omniauth-cas3 (~> 1.1.2)
|
||||
|
@ -975,7 +974,7 @@ DEPENDENCIES
|
|||
omniauth-gitlab (~> 1.0.0)
|
||||
omniauth-google-oauth2 (~> 0.2.0)
|
||||
omniauth-kerberos (~> 0.3.0)
|
||||
omniauth-saml (~> 1.4.0)
|
||||
omniauth-saml (~> 1.4.2)
|
||||
omniauth-shibboleth (~> 1.2.0)
|
||||
omniauth-twitter (~> 1.2.0)
|
||||
omniauth_crowd (~> 2.2.0)
|
||||
|
@ -988,7 +987,7 @@ DEPENDENCIES
|
|||
rack-attack (~> 4.3.1)
|
||||
rack-cors (~> 0.4.0)
|
||||
rack-oauth2 (~> 1.2.1)
|
||||
rails (= 4.2.5.1)
|
||||
rails (= 4.2.5.2)
|
||||
rails-deprecated_sanitizer (~> 1.0.3)
|
||||
raphael-rails (~> 2.1.2)
|
||||
rblineprof
|
||||
|
@ -1010,7 +1009,7 @@ DEPENDENCIES
|
|||
sdoc (~> 0.3.20)
|
||||
seed-fu (~> 2.3.5)
|
||||
select2-rails (~> 3.5.9)
|
||||
sentry-raven
|
||||
sentry-raven (~> 0.15)
|
||||
settingslogic (~> 2.0.9)
|
||||
sham_rack
|
||||
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
|
||||
- Ruby (MRI) 2.1
|
||||
- Git 1.7.10+
|
||||
- Git 2.7.4+
|
||||
- Redis 2.8+
|
||||
- MySQL or PostgreSQL
|
||||
|
||||
|
|
3
Rakefile
3
Rakefile
|
@ -4,4 +4,7 @@
|
|||
|
||||
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
|
||||
|
|
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()
|
||||
$('.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) ->
|
||||
e.preventDefault()
|
||||
$(this).tab('show')
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
callback(namespaces)
|
||||
|
||||
# Return projects list. Filtered by query
|
||||
projects: (query, callback) ->
|
||||
projects: (query, order, callback) ->
|
||||
url = Api.buildUrl(Api.projects_path)
|
||||
|
||||
$.ajax(
|
||||
|
@ -55,6 +55,7 @@
|
|||
data:
|
||||
private_token: gon.api_token
|
||||
search: query
|
||||
order_by: order
|
||||
per_page: 20
|
||||
dataType: "json"
|
||||
).done (projects) ->
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
# the compiled file.
|
||||
#
|
||||
#= 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.cookie
|
||||
#= require jquery.endless-scroll
|
||||
|
@ -21,9 +24,9 @@
|
|||
#= require bootstrap
|
||||
#= require select2
|
||||
#= require raphael
|
||||
#= require g.raphael-min
|
||||
#= require g.bar-min
|
||||
#= require chart-lib.min
|
||||
#= require g.raphael
|
||||
#= require g.bar
|
||||
#= require Chart
|
||||
#= require branch-graph
|
||||
#= require ace/ace
|
||||
#= require ace/ext-searchbox
|
||||
|
@ -38,9 +41,9 @@
|
|||
#= require shortcuts_dashboard_navigation
|
||||
#= require shortcuts_issuable
|
||||
#= require shortcuts_network
|
||||
#= require jquery.nicescroll.min
|
||||
#= require jquery.nicescroll
|
||||
#= require_tree .
|
||||
#= require fuzzaldrin-plus.min
|
||||
#= require fuzzaldrin-plus
|
||||
|
||||
window.slugify = (text) ->
|
||||
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
|
||||
|
@ -203,4 +206,94 @@ $ ->
|
|||
form = btn.closest("form")
|
||||
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()
|
||||
|
|
|
@ -4,6 +4,7 @@ class @AwardsHandler
|
|||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
$(".emoji-menu").show()
|
||||
$("#emoji_search").focus()
|
||||
|
||||
$("html").on 'click', (event) ->
|
||||
if !$(event.target).closest(".emoji-menu").length
|
||||
|
@ -48,10 +49,11 @@ class @AwardsHandler
|
|||
counter.text(parseInt(counter.text()) - 1)
|
||||
emojiIcon.removeClass("active")
|
||||
@removeMeFromAuthorList(emoji)
|
||||
else if emoji =="thumbsup" || emoji == "thumbsdown"
|
||||
else if emoji == "thumbsup" || emoji == "thumbsdown"
|
||||
emojiIcon.tooltip("destroy")
|
||||
counter.text(0)
|
||||
emojiIcon.removeClass("active")
|
||||
@removeMeFromAuthorList(emoji)
|
||||
else
|
||||
emojiIcon.tooltip("destroy")
|
||||
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
|
||||
constructor: ->
|
||||
new ProjectsList()
|
||||
@Dashboard =
|
||||
init: ->
|
||||
$(".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
|
||||
|
||||
switch page
|
||||
when 'explore:projects:index', 'explore:projects:starred', 'explore:projects:trending'
|
||||
Dashboard.init()
|
||||
when 'projects:issues:index'
|
||||
Issues.init()
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
|
@ -58,7 +60,7 @@ class Dispatcher
|
|||
shortcut_handler = new ShortcutsNavigation()
|
||||
MergeRequests.init()
|
||||
when 'dashboard:show', 'root:show'
|
||||
new Dashboard()
|
||||
Dashboard.init()
|
||||
when 'dashboard:activity'
|
||||
new Activities()
|
||||
when 'dashboard:projects:starred'
|
||||
|
@ -86,6 +88,7 @@ class Dispatcher
|
|||
when 'groups:new', 'groups:edit', 'admin:groups:edit', 'admin:groups:new'
|
||||
new GroupAvatar()
|
||||
when 'projects:tree:show'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
new TreeView()
|
||||
when 'projects:find_file:show'
|
||||
shortcut_handler = true
|
||||
|
|
|
@ -65,8 +65,7 @@ class @DropzoneInput
|
|||
return
|
||||
|
||||
success: (header, response) ->
|
||||
child = $(dropzone[0]).children("textarea")
|
||||
$(child).val $(child).val() + response.link.markdown + "\n"
|
||||
pasteText response.link.markdown
|
||||
return
|
||||
|
||||
error: (temp, errorMessage) ->
|
||||
|
@ -128,6 +127,7 @@ class @DropzoneInput
|
|||
beforeSelection = $(child).val().substring 0, caretStart
|
||||
afterSelection = $(child).val().substring caretEnd, textEnd
|
||||
$(child).val beforeSelection + text + afterSelection
|
||||
child.get(0).setSelectionRange caretStart + text.length, caretEnd + text.length
|
||||
form_textarea.trigger "input"
|
||||
|
||||
getFilename = (e) ->
|
||||
|
|
|
@ -10,20 +10,10 @@ class @IssuableContext
|
|||
$(".issuable-sidebar .inline-update").on "change", ".js-assignee", ->
|
||||
$(this).submit()
|
||||
|
||||
$('.issuable-details').waitForImages ->
|
||||
$('.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) ->
|
||||
$(document).on "click",".edit-link", (e) ->
|
||||
block = $(@).parents('.block')
|
||||
block.find('.selectbox').show()
|
||||
block.find('.value').hide()
|
||||
block.find('.js-select2').select2("open")
|
||||
|
||||
$(".right-sidebar").niceScroll()
|
||||
|
|
|
@ -50,6 +50,7 @@ class @Issue
|
|||
new Flash(issueFailMessage, 'alert')
|
||||
success: (data, textStatus, jqXHR) ->
|
||||
if data.saved
|
||||
$(document).trigger('issuable:change');
|
||||
if isClose
|
||||
$('a.btn-close').addClass('hidden')
|
||||
$('a.btn-reopen').removeClass('hidden')
|
||||
|
|
|
@ -42,3 +42,9 @@ work = ->
|
|||
|
||||
$(document).on('page:fetch', start)
|
||||
$(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) =>
|
||||
document.querySelector("div#diffs").innerHTML = data.html
|
||||
$('div#diffs .js-syntax-highlight').syntaxHighlight()
|
||||
@expandViewContainer() if @diffViewType() is 'parallel'
|
||||
@diffsLoaded = true
|
||||
@scrollToElement("#diffs")
|
||||
|
||||
|
@ -177,3 +178,10 @@ class @MergeRequestTabs
|
|||
options = $.extend({}, defaults, 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"
|
||||
|
||||
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()
|
||||
@bindMergeRequestSorting()
|
||||
@bindTabsSwitching
|
||||
|
||||
bindIssuesSorting: ->
|
||||
$("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable(
|
||||
connectWith: ".issues-sortable-list",
|
||||
dropOnEmpty: true,
|
||||
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) ->
|
||||
data = $(this).sortable("serialize")
|
||||
Milestone.sortIssues(data)
|
||||
|
@ -95,10 +105,22 @@ class @Milestone
|
|||
).disableSelection()
|
||||
|
||||
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(
|
||||
connectWith: ".merge_requests-sortable-list",
|
||||
dropOnEmpty: true,
|
||||
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) ->
|
||||
data = $(this).sortable("serialize")
|
||||
Milestone.sortMergeRequests(data)
|
||||
|
|
|
@ -15,6 +15,8 @@ class @Notes
|
|||
@last_fetched_at = last_fetched_at
|
||||
@view = view
|
||||
@noteable_url = document.URL
|
||||
@notesCountBadge ||= $(".issuable-details").find(".notes-tab .badge")
|
||||
|
||||
@initRefresh()
|
||||
@setupMainTargetNoteForm()
|
||||
@cleanBinding()
|
||||
|
@ -62,6 +64,9 @@ class @Notes
|
|||
# fetch notes when tab becomes visible
|
||||
$(document).on "visibilitychange", @visibilityChange
|
||||
|
||||
# when issue status changes, we need to refresh data
|
||||
$(document).on "issuable:change", @refresh
|
||||
|
||||
cleanBinding: ->
|
||||
$(document).off "ajax:success", ".js-main-target-form"
|
||||
$(document).off "ajax:success", ".js-discussion-note-form"
|
||||
|
@ -89,7 +94,7 @@ class @Notes
|
|||
, 15000
|
||||
|
||||
refresh: ->
|
||||
unless document.hidden or (@noteable_url != document.URL)
|
||||
if not document.hidden and document.URL.indexOf(@noteable_url) is 0
|
||||
@getContent()
|
||||
|
||||
getContent: ->
|
||||
|
@ -101,7 +106,10 @@ class @Notes
|
|||
notes = data.notes
|
||||
@last_fetched_at = data.last_fetched_at
|
||||
$.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')
|
||||
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
|
||||
awards_handler.addAwardToEmojiBar(note.note)
|
||||
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
|
||||
###
|
||||
|
@ -144,34 +155,39 @@ class @Notes
|
|||
Note: for rendering inline notes use renderDiscussionNote
|
||||
###
|
||||
renderDiscussionNote: (note) ->
|
||||
return unless @isNewNote(note)
|
||||
|
||||
@note_ids.push(note.id)
|
||||
form = $("form[rel='" + note.discussion_id + "']")
|
||||
form = $("#new-discussion-note-form-#{note.discussion_id}")
|
||||
row = form.closest("tr")
|
||||
note_html = $(note.html)
|
||||
note_html.syntaxHighlight()
|
||||
|
||||
# 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
|
||||
row.after note.discussion_html
|
||||
|
||||
# remove the note (will be added again below)
|
||||
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
|
||||
$(".notes[rel='" + note.discussion_id + "']").append note_html
|
||||
discussionContainer.append note_html
|
||||
|
||||
# Init discussion on 'Discussion' page if it is merge request page
|
||||
if $('body').attr('data-page').indexOf('projects:merge_request') == 0
|
||||
discussion_html = $(note.discussion_with_diff_html)
|
||||
discussion_html.syntaxHighlight()
|
||||
$('ul.main-notes-list').append(discussion_html)
|
||||
if $('body').attr('data-page').indexOf('projects:merge_request') is 0
|
||||
$('ul.main-notes-list')
|
||||
.append(note.discussion_with_diff_html)
|
||||
.syntaxHighlight()
|
||||
else
|
||||
# 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
|
||||
@removeDiscussionNoteForm(form)
|
||||
@updateNotesCount(1)
|
||||
|
||||
###
|
||||
Called in response the main target form has been successfully submitted.
|
||||
|
@ -278,6 +294,9 @@ class @Notes
|
|||
addDiscussionNote: (xhr, note, status) =>
|
||||
@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
|
||||
|
||||
|
@ -320,6 +339,7 @@ class @Notes
|
|||
form.show()
|
||||
textarea = form.find("textarea")
|
||||
textarea.focus()
|
||||
autosize(textarea)
|
||||
|
||||
# HACK (rspeicher/DouweM): Work around a Chrome 43 bug(?).
|
||||
# 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 whole discussion if the last note is being removed.
|
||||
###
|
||||
removeNote: ->
|
||||
note = $(this).closest(".note")
|
||||
note_id = note.attr('id')
|
||||
removeNote: (e) =>
|
||||
noteId = $(e.currentTarget)
|
||||
.closest(".note")
|
||||
.attr("id")
|
||||
|
||||
$('.note[id="' + note_id + '"]').each ->
|
||||
note = $(this)
|
||||
# A same note appears in the "Discussion" and in the "Changes" tab, we have
|
||||
# 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")
|
||||
count = notes.closest(".issuable-details").find(".notes-tab .badge")
|
||||
|
||||
# check if this is the last note for this line
|
||||
if notes.find(".note").length is 1
|
||||
|
||||
# for discussions
|
||||
notes.closest(".discussion").remove()
|
||||
# "Discussions" tab
|
||||
notes.closest(".timeline-entry").remove()
|
||||
|
||||
# for diff lines
|
||||
# "Changes" tab / commit view
|
||||
notes.closest("tr").remove()
|
||||
|
||||
# update notes count
|
||||
oldNum = parseInt(count.text())
|
||||
count.text(oldNum - 1)
|
||||
|
||||
note.remove()
|
||||
|
||||
# Decrement the "Discussions" counter only once
|
||||
@updateNotesCount(-1)
|
||||
|
||||
###
|
||||
Called in response to clicking the delete attachment link
|
||||
|
||||
|
@ -411,7 +433,7 @@ class @Notes
|
|||
###
|
||||
setupDiscussionNoteForm: (dataHolder, form) =>
|
||||
# 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("#note_commit_id").val dataHolder.data("commitId")
|
||||
form.find("#note_line_code").val dataHolder.data("lineCode")
|
||||
|
@ -541,3 +563,6 @@ class @Notes
|
|||
|
||||
updateTaskList: ->
|
||||
$('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>")
|
||||
$(@).parents('ul').find('li.active').removeClass '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) ->
|
||||
@groupId = $(select).data('group-id')
|
||||
@includeGroups = $(select).data('include-groups')
|
||||
@orderBy = $(select).data('order-by') || 'id'
|
||||
|
||||
placeholder = "Search for project"
|
||||
placeholder += " or group" if @includeGroups
|
||||
|
@ -28,7 +29,7 @@ class @ProjectSelect
|
|||
if @groupId
|
||||
Api.groupProjects @groupId, query.term, projectsCallback
|
||||
else
|
||||
Api.projects query.term, projectsCallback
|
||||
Api.projects query.term, @orderBy, projectsCallback
|
||||
|
||||
id: (project) ->
|
||||
project.web_url
|
||||
|
|
|
@ -2,23 +2,31 @@ class @ProjectsList
|
|||
constructor: ->
|
||||
$(".projects-list .js-expand").on 'click', (e) ->
|
||||
e.preventDefault()
|
||||
list = $(this).closest('.projects-list')
|
||||
list.find("li").show()
|
||||
list.find("li.bottom").hide()
|
||||
$projectsList = $(this).closest('.projects-list')
|
||||
ProjectsList.showPagination($projectsList)
|
||||
$projectsList.find('li.bottom').hide()
|
||||
|
||||
$(".projects-list-filter").keyup ->
|
||||
terms = $(this).val()
|
||||
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()
|
||||
$("#filter_projects").on 'keyup', ->
|
||||
ProjectsList.filter_results($("#filter_projects"))
|
||||
|
||||
if name.toLowerCase().search(terms.toLowerCase()) == -1
|
||||
$(this).hide()
|
||||
else
|
||||
$(this).show()
|
||||
uiBox.find("ul.projects-list li.bottom").hide()
|
||||
@showPagination: ($projectsList) ->
|
||||
$projectsList.find('li').show()
|
||||
$('.gl-pagination').show()
|
||||
|
||||
@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
|
||||
$('#modal-shortcuts').modal('show')
|
||||
else
|
||||
url = '/help/shortcuts'
|
||||
url = gon.relative_url_root + url if gon.relative_url_root?
|
||||
$.ajax(
|
||||
url: '/help/shortcuts',
|
||||
url: url,
|
||||
dataType: 'script',
|
||||
success: (e) ->
|
||||
if location and location.length > 0
|
||||
|
|
|
@ -5,23 +5,42 @@ class @ShortcutsIssuable extends ShortcutsNavigation
|
|||
constructor: (isMergeRequest) ->
|
||||
super()
|
||||
Mousetrap.bind('a', ->
|
||||
$('.js-assignee').select2('open')
|
||||
$('.block.assignee .edit-link').trigger('click')
|
||||
return false
|
||||
)
|
||||
Mousetrap.bind('m', ->
|
||||
$('.js-milestone').select2('open')
|
||||
$('.block.milestone .edit-link').trigger('click')
|
||||
return false
|
||||
)
|
||||
Mousetrap.bind('r', =>
|
||||
@replyWithSelectedText()
|
||||
return false
|
||||
)
|
||||
Mousetrap.bind('j', =>
|
||||
@prevIssue()
|
||||
return false
|
||||
)
|
||||
Mousetrap.bind('k', =>
|
||||
@nextIssue()
|
||||
return false
|
||||
)
|
||||
|
||||
|
||||
if isMergeRequest
|
||||
@enabledHelp.push('.hidden-shortcut.merge_requests')
|
||||
else
|
||||
@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: ->
|
||||
if window.getSelection
|
||||
selected = window.getSelection().toString()
|
||||
|
|
|
@ -8,4 +8,10 @@ $(document).on("click", '.toggle-nav-collapse', (e) ->
|
|||
$('.sidebar-wrapper').toggleClass("sidebar-collapsed sidebar-expanded")
|
||||
$('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
|
||||
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
|
||||
|
||||
setTimeout ( ->
|
||||
niceScrollBars = $('.nicescroll').niceScroll();
|
||||
niceScrollBars.updateScrollBar();
|
||||
), 300
|
||||
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
class @Wikis
|
||||
constructor: ->
|
||||
$('.build-new-wiki').bind 'click', (e) =>
|
||||
$('.new-wiki-page').on 'submit', (e) =>
|
||||
$('[data-error~=slug]').addClass('hidden')
|
||||
field = $('#new_wiki_path')
|
||||
slug = @slugify(field.val())
|
||||
|
@ -10,6 +10,7 @@ class @Wikis
|
|||
if (slug.length > 0)
|
||||
path = field.attr('data-wikis-path')
|
||||
location.href = path + '/' + slug
|
||||
e.preventDefault()
|
||||
|
||||
dasherize: (value) ->
|
||||
value.replace(/[_\s]+/g, '-')
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
&.s26 { width: 26px; height: 26px; margin-right: 8px; }
|
||||
&.s32 { width: 32px; height: 32px; 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; }
|
||||
&.s48 { width: 48px; height: 48px; margin-right: 10px; }
|
||||
&.s60 { width: 60px; height: 60px; margin-right: 12px; }
|
||||
|
@ -40,7 +41,8 @@
|
|||
&.s16 { font-size: 12px; line-height: 1.33; }
|
||||
&.s24 { font-size: 14px; line-height: 1.8; }
|
||||
&.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; }
|
||||
&.s90 { font-size: 36px; line-height: 90px; }
|
||||
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
|
||||
|
|
|
@ -146,6 +146,10 @@
|
|||
border-bottom: 1px solid $border-color;
|
||||
|
||||
&.oneline-block {
|
||||
line-height: 42px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
> .controls {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
@include border-radius(3px);
|
||||
font-size: $gl-font-size;
|
||||
font-weight: 500;
|
||||
padding: $gl-vert-padding $gl-padding;
|
||||
padding: $gl-vert-padding $gl-btn-padding;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
|
@ -82,8 +82,7 @@
|
|||
&.btn-success,
|
||||
&.btn-new,
|
||||
&.btn-create,
|
||||
&.btn-save,
|
||||
&.btn-green {
|
||||
&.btn-save {
|
||||
@include btn-green;
|
||||
}
|
||||
|
||||
|
@ -159,7 +158,6 @@
|
|||
|
||||
.input-group-btn {
|
||||
.btn {
|
||||
@include btn-gray;
|
||||
@include btn-middle;
|
||||
|
||||
&:hover {
|
||||
|
@ -186,8 +184,4 @@
|
|||
border: 1px solid #c6cacf !important;
|
||||
background-color: #e4e7ed !important;
|
||||
}
|
||||
|
||||
.btn-green {
|
||||
@include btn-green
|
||||
}
|
||||
}
|
||||
|
|
|
@ -376,11 +376,11 @@ table {
|
|||
margin-bottom: $gl-padding;
|
||||
}
|
||||
|
||||
.new-project-item-select-holder {
|
||||
.project-item-select-holder {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
||||
.new-project-item-select {
|
||||
.project-item-select {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
|
|
@ -36,6 +36,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
.filename {
|
||||
&.old {
|
||||
span.idiff {
|
||||
background-color: #f8cbcb;
|
||||
}
|
||||
}
|
||||
|
||||
&.new {
|
||||
span.idiff {
|
||||
background-color: #a6f3a6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.left-options {
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
@ -144,7 +158,7 @@
|
|||
}
|
||||
|
||||
&: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;
|
||||
}
|
||||
|
||||
input[type='search'].search-text-input {
|
||||
background-image: image-url("icon-search.png");
|
||||
input {
|
||||
border-radius: $border-radius-base;
|
||||
}
|
||||
|
||||
input[type='search'] {
|
||||
background-color: white;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
input[type='search'].search-input {
|
||||
background-repeat: no-repeat;
|
||||
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 {
|
||||
|
@ -74,6 +105,7 @@ label {
|
|||
|
||||
.form-control {
|
||||
@include box-shadow(none);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.form-control-inline {
|
||||
|
|
|
@ -117,4 +117,4 @@ body {
|
|||
&.ui_violet {
|
||||
@include gitlab-theme(#9988CC, $theme-violet, #443366, #332255);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -73,7 +73,6 @@ header {
|
|||
|
||||
.title {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
font-size: 19px;
|
||||
line-height: $header-height;
|
||||
font-weight: normal;
|
||||
|
@ -88,6 +87,22 @@ header {
|
|||
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 {
|
||||
|
@ -108,16 +123,10 @@ header {
|
|||
|
||||
.search-input {
|
||||
width: 220px;
|
||||
background-image: image-url("icon-search.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 195px;
|
||||
@include input-big;
|
||||
|
||||
&:focus {
|
||||
@include box-shadow(none);
|
||||
outline: none;
|
||||
border-color: #DDD;
|
||||
background-color: #FFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,9 +141,13 @@ header {
|
|||
}
|
||||
|
||||
@media (max-width: $screen-md-max) {
|
||||
.header-collapsed, .header-expanded {
|
||||
@include collapsed-header;
|
||||
.header-collapsed {
|
||||
margin-left: $sidebar_collapsed_width;
|
||||
}
|
||||
|
||||
.header-expanded {
|
||||
margin-left: $sidebar_width;
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: $screen-md-max) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
display: block;
|
||||
float: left;
|
||||
padding: 0 $gl-padding;
|
||||
padding: 0 $gl-btn-padding;
|
||||
font-weight: normal;
|
||||
margin-right: 10px;
|
||||
font-size: $gl-font-size;
|
||||
|
|
|
@ -48,8 +48,19 @@
|
|||
|
||||
.ui-state-hover,
|
||||
.ui-state-focus {
|
||||
border: 1px solid $hover;
|
||||
background: $hover;
|
||||
border: 1px solid $row-hover;
|
||||
background: $row-hover;
|
||||
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; }
|
||||
|
||||
&:hover {
|
||||
background: $hover;
|
||||
background: $row-hover;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
|
@ -109,7 +109,6 @@ ul.content-list {
|
|||
padding: 0;
|
||||
|
||||
> li {
|
||||
padding: $gl-padding 0;
|
||||
border-color: $table-border-color;
|
||||
color: $gl-gray;
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
aside {
|
||||
aside:not(.right-sidebar){
|
||||
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 {
|
||||
text-align: center;
|
||||
border-top: 1px solid $border-color;
|
||||
background-color: $background-color;
|
||||
margin: -$gl-padding;
|
||||
margin: 0;
|
||||
margin-top: 0;
|
||||
|
||||
.pagination {
|
||||
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;
|
||||
|
||||
.panel-heading {
|
||||
padding: 7px $gl-padding;
|
||||
padding: $gl-vert-padding $gl-padding;
|
||||
line-height: 36px;
|
||||
|
||||
.controls {
|
||||
margin-top: -2px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
|
@ -14,7 +20,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container-blank .panel .panel-heading {
|
||||
line-height: 42px !important;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,23 @@
|
|||
height: 100%;
|
||||
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 {
|
||||
|
@ -70,7 +87,7 @@
|
|||
width: 158px;
|
||||
float: left;
|
||||
margin: 0;
|
||||
margin-left: 14px;
|
||||
margin-left: 50px;
|
||||
font-size: 19px;
|
||||
line-height: 41px;
|
||||
font-weight: normal;
|
||||
|
@ -181,6 +198,10 @@
|
|||
@mixin expanded-sidebar {
|
||||
padding-left: $sidebar_width;
|
||||
|
||||
&.right-sidebar-collapsed {
|
||||
padding-right: $sidebar_collapsed_width;
|
||||
}
|
||||
|
||||
.sidebar-wrapper {
|
||||
width: $sidebar_width;
|
||||
|
||||
|
@ -203,6 +224,10 @@
|
|||
@mixin collapsed-sidebar {
|
||||
padding-left: $sidebar_collapsed_width;
|
||||
|
||||
&.right-sidebar-collapsed {
|
||||
padding-right: $sidebar_collapsed_width;
|
||||
}
|
||||
|
||||
.sidebar-wrapper {
|
||||
width: $sidebar_collapsed_width;
|
||||
|
||||
|
@ -266,26 +291,10 @@
|
|||
background: #f2f6f7;
|
||||
}
|
||||
|
||||
@media (max-width: $screen-md-max) {
|
||||
.page-sidebar-collapsed {
|
||||
@include collapsed-sidebar;
|
||||
}
|
||||
|
||||
.page-sidebar-expanded {
|
||||
@include collapsed-sidebar;
|
||||
}
|
||||
|
||||
.collapse-nav {
|
||||
display: none;
|
||||
}
|
||||
.page-sidebar-collapsed {
|
||||
@include collapsed-sidebar;
|
||||
}
|
||||
|
||||
@media(min-width: $screen-md-max) {
|
||||
.page-sidebar-collapsed {
|
||||
@include collapsed-sidebar;
|
||||
}
|
||||
|
||||
.page-sidebar-expanded {
|
||||
@include expanded-sidebar;
|
||||
}
|
||||
.page-sidebar-expanded {
|
||||
@include expanded-sidebar;
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
padding: 0;
|
||||
|
||||
.timeline-entry {
|
||||
padding: $gl-padding 0;
|
||||
padding: $gl-padding $gl-btn-padding;
|
||||
border-color: $table-border-color;
|
||||
color: $gl-gray;
|
||||
border-bottom: 1px solid $border-white-light;
|
||||
|
||||
&:target {
|
||||
background: $hover;
|
||||
background: $row-hover;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
|
|
|
@ -114,22 +114,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
.container-blank .panel .panel-heading {
|
||||
font-size: 17px;
|
||||
line-height: 38px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
box-shadow: none;
|
||||
|
||||
.panel-heading {
|
||||
.panel-head-actions {
|
||||
position: relative;
|
||||
top: -5px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
form, pre {
|
||||
margin: 0;
|
||||
|
|
|
@ -22,9 +22,9 @@ $brand-info: $gl-info;
|
|||
$brand-warning: $gl-warning;
|
||||
$brand-danger: $gl-danger;
|
||||
|
||||
$border-radius-base: 2px !default;
|
||||
$border-radius-large: 2px !default;
|
||||
$border-radius-small: 2px !default;
|
||||
$border-radius-base: 3px !default;
|
||||
$border-radius-large: 3px !default;
|
||||
$border-radius-small: 3px !default;
|
||||
|
||||
|
||||
//== Scaffolding
|
||||
|
@ -66,20 +66,20 @@ $legend-color: $text-color;
|
|||
//##
|
||||
|
||||
$pagination-color: $gl-gray;
|
||||
$pagination-bg: $background-color;
|
||||
$pagination-border: transparent;
|
||||
$pagination-bg: #fff;
|
||||
$pagination-border: $border-color;
|
||||
|
||||
$pagination-hover-color: #fff;
|
||||
$pagination-hover-bg: $brand-info;
|
||||
$pagination-hover-border: transparent;
|
||||
$pagination-hover-color: $gl-gray;
|
||||
$pagination-hover-bg: $row-hover;
|
||||
$pagination-hover-border: $border-color;
|
||||
|
||||
$pagination-active-color: #fff;
|
||||
$pagination-active-bg: $brand-info;
|
||||
$pagination-active-border: transparent;
|
||||
$pagination-active-color: $blue-dark;
|
||||
$pagination-active-bg: #fff;
|
||||
$pagination-active-border: $border-color;
|
||||
|
||||
$pagination-disabled-color: #fff;
|
||||
$pagination-disabled-bg: lighten($brand-info, 15%);
|
||||
$pagination-disabled-border: transparent;
|
||||
$pagination-disabled-color: #cdcdcd;
|
||||
$pagination-disabled-bg: $background-color;
|
||||
$pagination-disabled-border: $border-color;
|
||||
|
||||
|
||||
//== Form states and alerts
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
|
||||
ul, ol {
|
||||
padding: 0;
|
||||
margin: 6px 0 6px 18px !important;
|
||||
margin: 6px 0 6px 28px !important;
|
||||
}
|
||||
|
||||
li {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$hover: #faf9f9;
|
||||
$row-hover: #f4f8fe;
|
||||
$gl-text-color: #54565B;
|
||||
$gl-text-green: #4A2;
|
||||
$gl-text-red: #D12F19;
|
||||
|
@ -12,6 +12,9 @@ $gl-font-size: 15px;
|
|||
$list-font-size: 15px;
|
||||
$sidebar_collapsed_width: 62px;
|
||||
$sidebar_width: 230px;
|
||||
$gutter_collapsed_width: 62px;
|
||||
$gutter_width: 290px;
|
||||
$gutter_inner_width: 258px;
|
||||
$avatar_radius: 50%;
|
||||
$code_font_size: 13px;
|
||||
$code_line_height: 1.5;
|
||||
|
@ -22,10 +25,12 @@ $header-height: 58px;
|
|||
$fixed-layout-width: 1280px;
|
||||
$gl-gray: #5a5a5a;
|
||||
$gl-padding: 16px;
|
||||
$gl-btn-padding: 10px;
|
||||
$gl-vert-padding: 6px;
|
||||
$gl-padding-top:10px;
|
||||
$gl-avatar-size: 46px;
|
||||
$gl-avatar-size: 40px;
|
||||
$secondary-text: #7f8fa4;
|
||||
$error-exclamation-point: #E62958;
|
||||
|
||||
/*
|
||||
* Color schema
|
||||
|
@ -35,11 +40,12 @@ $white-light: #FFFFFF;
|
|||
$white-normal: #ededed;
|
||||
$white-dark: #ededed;
|
||||
|
||||
$gray-light: #f7f7f7;
|
||||
$gray-normal: #ededed;
|
||||
$gray-light: #faf9f9;
|
||||
$gray-normal: #f5f5f5;
|
||||
$gray-dark: #ededed;
|
||||
$gray-darkest: #c9c9c9;
|
||||
|
||||
$green-light: #31AF64;
|
||||
$green-light: #38ae67;
|
||||
$green-normal: #2FAA60;
|
||||
$green-dark: #2CA05B;
|
||||
|
||||
|
@ -51,7 +57,7 @@ $blue-medium-light: #3498CB;
|
|||
$blue-medium: #2F8EBF;
|
||||
$blue-medium-dark: #2D86B4;
|
||||
|
||||
$orange-light: #FC6443;
|
||||
$orange-light: rgba(252, 109, 38, 0.80);
|
||||
$orange-normal: #E75E40;
|
||||
$orange-dark: #CE5237;
|
||||
|
||||
|
@ -63,8 +69,8 @@ $border-white-light: #F1F2F4;
|
|||
$border-white-normal: #D6DAE2;
|
||||
$border-white-dark: #C6CACF;
|
||||
|
||||
$border-gray-light: #d1d1d1;
|
||||
$border-gray-normal: #D6DAE2;
|
||||
$border-gray-light: rgba(0, 0, 0, 0.06);
|
||||
$border-gray-normal: rgba(0, 0, 0, 0.10);;
|
||||
$border-gray-dark: #C6CACF;
|
||||
|
||||
$border-green-light: #2FAA60;
|
||||
|
@ -75,7 +81,7 @@ $border-blue-light: #2D9FD8;
|
|||
$border-blue-normal: #2897CE;
|
||||
$border-blue-dark: #258DC1;
|
||||
|
||||
$border-orange-light: #ED5C3D;
|
||||
$border-orange-light: #fc6d26;
|
||||
$border-orange-normal: #CE5237;
|
||||
$border-orange-dark: #C14E35;
|
||||
|
||||
|
|
|
@ -55,6 +55,16 @@
|
|||
@extend .alert-warning;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
|
||||
> div, p {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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 {
|
||||
@include border-radius(50%);
|
||||
}
|
||||
|
||||
.identicon {
|
||||
line-height: 46px;
|
||||
}
|
||||
}
|
||||
|
||||
.dash-project-access-icon {
|
||||
|
|
|
@ -12,6 +12,14 @@
|
|||
.identifier {
|
||||
color: #5c5d5e;
|
||||
}
|
||||
|
||||
.issue_created_ago, .author_link {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.issue-meta {
|
||||
margin-left: 65px
|
||||
}
|
||||
}
|
||||
|
||||
.detail-page-description {
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
width: 100%;
|
||||
font-family: $monospace_font;
|
||||
border: none;
|
||||
border-collapse: separate;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
.line_holder td {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
.event-item {
|
||||
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;
|
||||
color: #7f8fa4;
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
.event-title,
|
||||
.event-item-timestamp {
|
||||
line-height: 44px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
|||
}
|
||||
|
||||
.avatar {
|
||||
margin-left: -($gl-avatar-size + 15px);
|
||||
margin-left: -($gl-avatar-size + $gl-padding-top);
|
||||
}
|
||||
|
||||
.event-title {
|
||||
|
@ -41,7 +41,6 @@
|
|||
margin-right: 174px;
|
||||
|
||||
.event-note {
|
||||
margin-top: 5px;
|
||||
word-wrap: break-word;
|
||||
|
||||
.md {
|
||||
|
@ -98,8 +97,6 @@
|
|||
&:last-child { border:none }
|
||||
|
||||
.event_commits {
|
||||
margin-top: 9px;
|
||||
|
||||
li {
|
||||
&.commit {
|
||||
background: transparent;
|
||||
|
|
|
@ -6,11 +6,3 @@
|
|||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.explore-trending-block {
|
||||
.lead {
|
||||
line-height: 32px;
|
||||
font-size: 18px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
.member-search-form {
|
||||
float: left;
|
||||
|
||||
input[type='search'] {
|
||||
width: 225px;
|
||||
vertical-align: bottom;
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
width: 100px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.milestone-row {
|
||||
|
@ -11,3 +21,21 @@
|
|||
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 {
|
||||
section {
|
||||
border-right: 1px solid $border-white-light;
|
||||
|
||||
.issuable-discussion {
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
@ -73,11 +60,41 @@
|
|||
.block {
|
||||
@include clearfix;
|
||||
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 {
|
||||
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 {
|
||||
|
@ -133,3 +150,105 @@
|
|||
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 {
|
||||
margin: 0;
|
||||
height: 24px;
|
||||
|
||||
.issue_search {
|
||||
border: 1px solid #DDD !important;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
}
|
||||
|
||||
form.edit-issue {
|
||||
|
@ -70,10 +65,6 @@ form.edit-issue {
|
|||
width: 3em;
|
||||
}
|
||||
|
||||
.merge-request-info {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.merge-request-status {
|
||||
color: $gl-gray;
|
||||
font-size: 15px;
|
||||
|
@ -148,4 +139,4 @@ form.edit-issue {
|
|||
.issue-closed-by-widget {
|
||||
color: $secondary-text;
|
||||
margin-left: 52px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.manage-labels-list {
|
||||
.label-row {
|
||||
.label {
|
||||
padding: 9px;
|
||||
font-size: 14px;
|
||||
|
|
|
@ -201,3 +201,39 @@
|
|||
.mr-source-target {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.visibility-icon {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
font-size: 18px;
|
||||
color: $gray;
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 0 $gl-padding;
|
||||
color: #5c5d5e;
|
||||
}
|
||||
}
|
||||
|
||||
.visibility-level-label {
|
||||
@extend .btn;
|
||||
@extend .btn-gray;
|
||||
|
||||
color: $gray;
|
||||
cursor: default;
|
||||
|
||||
i {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.project-repo-buttons {
|
||||
margin-top: 12px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 0px;
|
||||
|
||||
.count-buttons {
|
||||
display: block;
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.clone-row {
|
||||
|
@ -163,7 +158,7 @@
|
|||
line-height: 13px;
|
||||
padding: $gl-vert-padding $gl-padding;
|
||||
letter-spacing: .4px;
|
||||
padding: 10px;
|
||||
padding: 10px 14px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
touch-action: manipulation;
|
||||
|
@ -281,36 +276,6 @@
|
|||
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-thumbnail {
|
||||
text-align: center;
|
||||
|
@ -386,22 +351,6 @@ pre.light-well {
|
|||
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 {
|
||||
margin: 0 7px 0 7px;
|
||||
|
||||
|
@ -437,12 +386,11 @@ pre.light-well {
|
|||
@include basic-list;
|
||||
|
||||
.project-row {
|
||||
padding: $gl-padding 0;
|
||||
border-color: $table-border-color;
|
||||
|
||||
&.no-description {
|
||||
.project {
|
||||
line-height: 44px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,12 +403,16 @@ pre.light-well {
|
|||
.project-controls {
|
||||
float: right;
|
||||
color: $gl-gray;
|
||||
line-height: 45px;
|
||||
line-height: 40px;
|
||||
color: #7f8fa4;
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
> span {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.project-description {
|
||||
|
@ -558,3 +510,19 @@ pre.light-well {
|
|||
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 {
|
||||
td {
|
||||
background: $hover;
|
||||
background: $row-hover;
|
||||
}
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,3 @@
|
|||
margin-right: auto;
|
||||
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_method_call_threshold,
|
||||
:metrics_sample_interval,
|
||||
:ip_blocking_enabled,
|
||||
:dnsbl_servers_list,
|
||||
:recaptcha_enabled,
|
||||
:recaptcha_site_key,
|
||||
:recaptcha_private_key,
|
||||
:sentry_enabled,
|
||||
:sentry_dsn,
|
||||
:akismet_enabled,
|
||||
:akismet_api_key,
|
||||
:email_author_in_body,
|
||||
restricted_visibility_levels: [],
|
||||
import_sources: []
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
|
|||
before_action :finder, only: [:edit, :update, :destroy]
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
|
@ -36,6 +36,10 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def preview
|
||||
@message = broadcast_message_params[:message]
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def finder
|
||||
|
|
|
@ -53,6 +53,6 @@ class Admin::LabelsController < Admin::ApplicationController
|
|||
end
|
||||
|
||||
def label_params
|
||||
params[:label].permit(:title, :color)
|
||||
params[:label].permit(:title, :description, :color)
|
||||
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 :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|
|
||||
log_exception(exception)
|
||||
|
@ -60,6 +60,8 @@ class ApplicationController < ActionController::Base
|
|||
params[:authenticity_token].presence
|
||||
elsif params[:private_token].presence
|
||||
params[:private_token].presence
|
||||
elsif request.headers['PRIVATE-TOKEN'].present?
|
||||
request.headers['PRIVATE-TOKEN']
|
||||
end
|
||||
user = user_token && User.find_by_authentication_token(user_token.to_s)
|
||||
|
||||
|
@ -162,7 +164,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
def method_missing(method_sym, *arguments, &block)
|
||||
|
@ -244,6 +246,8 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def ldap_security_check
|
||||
if current_user && current_user.requires_ldap_check?
|
||||
return unless current_user.try_obtain_ldap_lease
|
||||
|
||||
unless Gitlab::LDAP::Access.allowed?(current_user)
|
||||
sign_out current_user
|
||||
flash[:alert] = "Access denied for your LDAP account."
|
||||
|
@ -275,9 +279,10 @@ class ApplicationController < ActionController::Base
|
|||
}
|
||||
end
|
||||
|
||||
def view_to_html_string(partial)
|
||||
def view_to_html_string(partial, locals = {})
|
||||
render_to_string(
|
||||
partial,
|
||||
locals: locals,
|
||||
layout: false,
|
||||
formats: [:html]
|
||||
)
|
||||
|
@ -298,7 +303,8 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def set_filters_params
|
||||
params[:sort] ||= 'id_desc'
|
||||
set_default_sort
|
||||
|
||||
params[:scope] = 'all' if params[:scope].blank?
|
||||
params[:state] = 'opened' if params[:state].blank?
|
||||
|
||||
|
@ -405,4 +411,31 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
current_user.nil? && root_path == request.path
|
||||
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
|
||||
|
|
|
@ -3,52 +3,5 @@ module Ci
|
|||
def self.railtie_helpers_paths
|
||||
"app/helpers/ci"
|
||||
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
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
module Ci
|
||||
class ProjectsController < Ci::ApplicationController
|
||||
before_action :project, except: [:index]
|
||||
before_action :authenticate_user!, except: [:index, :build, :badge]
|
||||
before_action :authorize_access_project!, except: [:index, :badge]
|
||||
before_action :project
|
||||
before_action :authorize_read_project!, except: [:badge]
|
||||
before_action :no_cache, only: [:badge]
|
||||
skip_before_action :authenticate_user!, only: [:badge]
|
||||
protect_from_forgery
|
||||
|
||||
def show
|
||||
|
@ -13,9 +13,14 @@ module Ci
|
|||
|
||||
# Project status badge
|
||||
# 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
|
||||
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"
|
||||
end
|
||||
|
||||
|
|
|
@ -13,17 +13,11 @@ module CreatesCommit
|
|||
result = service.new(@tree_edit_project, current_user, commit_params).execute
|
||||
|
||||
if result[:status] == :success
|
||||
flash[:notice] = success_notice || "Your changes have been successfully committed."
|
||||
|
||||
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
|
||||
update_flash_notice(success_notice)
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to success_path }
|
||||
format.json { render json: { message: "success", filePath: success_path } }
|
||||
format.html { redirect_to final_success_path(success_path) }
|
||||
format.json { render json: { message: "success", filePath: final_success_path(success_path) } }
|
||||
end
|
||||
else
|
||||
flash[:alert] = result[:message]
|
||||
|
@ -41,14 +35,32 @@ module CreatesCommit
|
|||
end
|
||||
|
||||
def authorize_edit_tree!
|
||||
return if can?(current_user, :push_code, project)
|
||||
return if current_user && current_user.already_forked?(project)
|
||||
return if can_collaborate_with_project?
|
||||
|
||||
access_denied!
|
||||
end
|
||||
|
||||
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
|
||||
new_namespace_project_merge_request_path(
|
||||
@mr_source_project.namespace,
|
||||
|
@ -62,6 +74,19 @@ module CreatesCommit
|
|||
)
|
||||
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?
|
||||
@mr_source_project != @mr_target_project
|
||||
end
|
||||
|
@ -75,7 +100,7 @@ module CreatesCommit
|
|||
end
|
||||
|
||||
def set_commit_variables
|
||||
@mr_source_branch = @target_branch
|
||||
@mr_source_branch ||= @target_branch
|
||||
|
||||
if can?(current_user, :push_code, @project)
|
||||
# Edit file in this project
|
||||
|
@ -89,7 +114,7 @@ module CreatesCommit
|
|||
else
|
||||
# Merge request to this project
|
||||
@mr_target_project = @project
|
||||
@mr_target_branch = @ref
|
||||
@mr_target_branch ||= @ref
|
||||
end
|
||||
else
|
||||
# Edit file in fork
|
||||
|
@ -97,7 +122,7 @@ module CreatesCommit
|
|||
# Merge request from fork to this project
|
||||
@mr_source_project = @tree_edit_project
|
||||
@mr_target_project = @project
|
||||
@mr_target_branch = @ref
|
||||
@mr_target_branch ||= @ref
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,8 @@ module IssuesAction
|
|||
@issues = @issues.page(params[:page]).per(ApplicationController::PER_PAGE)
|
||||
@issues = @issues.preload(:author, :project)
|
||||
|
||||
@label = @issuable_finder.labels.first
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.atom { render layout: false }
|
||||
|
|
|
@ -5,5 +5,7 @@ module MergeRequestsAction
|
|||
@merge_requests = get_merge_requests_collection
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(ApplicationController::PER_PAGE)
|
||||
@merge_requests = @merge_requests.preload(:author, :target_project)
|
||||
|
||||
@label = @issuable_finder.labels.first
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,16 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
|||
|
||||
def index
|
||||
@projects = current_user.authorized_projects.sorted_by_activity.non_archived
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@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
|
||||
|
||||
respond_to do |format|
|
||||
|
@ -13,6 +22,11 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
|||
load_events
|
||||
render layout: false
|
||||
end
|
||||
format.json do
|
||||
render json: {
|
||||
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -20,6 +34,14 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
|||
@projects = current_user.starred_projects
|
||||
@projects = @projects.includes(:namespace, :forked_from_project, :tags)
|
||||
@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
|
||||
@groups = []
|
||||
|
||||
|
@ -27,8 +49,9 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
|||
format.html
|
||||
|
||||
format.json do
|
||||
load_events
|
||||
pager_json("events/_events", @events.count)
|
||||
render json: {
|
||||
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -36,7 +59,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
|||
private
|
||||
|
||||
def load_events
|
||||
@events = Event.in_projects(@projects.pluck(:id))
|
||||
@events = Event.in_projects(@projects)
|
||||
@events = @event_filter.apply_filter(@events).with_associations
|
||||
@events = @events.limit(20).offset(params[:offset] || 0)
|
||||
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
|
||||
|
||||
def load_events
|
||||
project_ids =
|
||||
projects =
|
||||
if params[:filter] == "starred"
|
||||
current_user.starred_projects
|
||||
else
|
||||
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 = @events.limit(20).offset(params[:offset] || 0)
|
||||
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.non_archived
|
||||
@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.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
|
||||
|
||||
def trending
|
||||
@trending_projects = TrendingProjectsFinder.new.execute(current_user)
|
||||
@trending_projects = @trending_projects.non_archived
|
||||
@trending_projects = @trending_projects.page(params[:page]).per(PER_PAGE)
|
||||
@projects = TrendingProjectsFinder.new.execute(current_user)
|
||||
@projects = @projects.non_archived
|
||||
@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
|
||||
|
||||
def starred
|
||||
@starred_projects = ProjectsFinder.new.execute(current_user)
|
||||
@starred_projects = @starred_projects.reorder('star_count DESC')
|
||||
@starred_projects = @starred_projects.page(params[:page]).per(PER_PAGE)
|
||||
@projects = ProjectsFinder.new.execute(current_user)
|
||||
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
|
||||
@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
|
||||
|
|
|
@ -2,18 +2,19 @@ class GroupsController < Groups::ApplicationController
|
|||
include IssuesAction
|
||||
include MergeRequestsAction
|
||||
|
||||
skip_before_action :authenticate_user!, only: [:show, :issues, :merge_requests]
|
||||
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
|
||||
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_create_group!, only: [:new, :create]
|
||||
|
||||
# Load group projects
|
||||
before_action :load_projects, except: [:new, :create, :projects, :edit, :update, :autocomplete]
|
||||
before_action :event_filter, only: :show
|
||||
before_action :load_projects, except: [:index, :new, :create, :projects, :edit, :update, :autocomplete]
|
||||
before_action :event_filter, only: [:show, :events]
|
||||
|
||||
layout :determine_layout
|
||||
|
||||
|
@ -40,13 +41,16 @@ class GroupsController < Groups::ApplicationController
|
|||
def show
|
||||
@last_push = current_user.recent_push if current_user
|
||||
@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|
|
||||
format.html
|
||||
|
||||
format.json do
|
||||
load_events
|
||||
pager_json("events/_events", @events.count)
|
||||
render json: {
|
||||
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
|
||||
}
|
||||
end
|
||||
|
||||
format.atom do
|
||||
|
@ -56,6 +60,15 @@ class GroupsController < Groups::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def events
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
load_events
|
||||
pager_json("events/_events", @events.count)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
|
@ -81,16 +94,13 @@ class GroupsController < Groups::ApplicationController
|
|||
|
||||
def group
|
||||
@group ||= Group.find_by(path: params[:id])
|
||||
@group || render_404
|
||||
end
|
||||
|
||||
def load_projects
|
||||
@projects ||= ProjectsFinder.new.execute(current_user, group: group).sorted_by_activity.non_archived
|
||||
end
|
||||
|
||||
def project_ids
|
||||
@projects.pluck(:id)
|
||||
end
|
||||
|
||||
# Dont allow unauthorized access to group
|
||||
def authorize_read_group!
|
||||
unless @group and (@projects.present? or can?(current_user, :read_group, @group))
|
||||
|
@ -123,7 +133,7 @@ class GroupsController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def load_events
|
||||
@events = Event.in_projects(project_ids)
|
||||
@events = Event.in_projects(@projects)
|
||||
@events = event_filter.apply_filter(@events).with_associations
|
||||
@events = @events.limit(20).offset(params[:offset] || 0)
|
||||
end
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||
include AuthenticatesWithTwoFactor
|
||||
|
||||
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
|
||||
if ldap_user.allowed?
|
||||
log_audit_event(@user, with: :ldap)
|
||||
sign_in_and_redirect(@user)
|
||||
if @user.two_factor_enabled?
|
||||
prompt_for_two_factor(@user)
|
||||
else
|
||||
log_audit_event(@user, with: :ldap)
|
||||
sign_in_and_redirect(@user)
|
||||
end
|
||||
else
|
||||
flash[:alert] = "Access denied for your LDAP account."
|
||||
redirect_to new_user_session_path
|
||||
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
|
||||
@provider = params[:provider]
|
||||
@error = params[:error]
|
||||
|
@ -60,25 +85,11 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
|||
log_audit_event(current_user, with: oauth['provider'])
|
||||
redirect_to profile_account_path, notice: 'Authentication method updated'
|
||||
else
|
||||
@user = Gitlab::OAuth::User.new(oauth)
|
||||
@user.save
|
||||
oauth_user = Gitlab::OAuth::User.new(oauth)
|
||||
oauth_user.save
|
||||
@user = oauth_user.gl_user
|
||||
|
||||
# Only allow properly saved users to login.
|
||||
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
|
||||
continue_login_process
|
||||
end
|
||||
rescue Gitlab::OAuth::SignupDisabledError
|
||||
label = Gitlab::OAuth::Provider.label_for(oauth['provider'])
|
||||
|
@ -99,6 +110,18 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
|||
session[:service_tickets][provider] = ticket
|
||||
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
|
||||
@oauth ||= request.env['omniauth.auth']
|
||||
end
|
||||
|
|
|
@ -12,11 +12,13 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
|
|||
|
||||
current_user.save! if current_user.changed?
|
||||
|
||||
if two_factor_grace_period_expired?
|
||||
flash.now[:alert] = 'You must configure Two-Factor Authentication in your account.'
|
||||
else
|
||||
grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
|
||||
flash.now[:alert] = "You must configure Two-Factor Authentication in your account until #{l(grace_period_deadline)}."
|
||||
if two_factor_authentication_required?
|
||||
if two_factor_grace_period_expired?
|
||||
flash.now[:alert] = 'You must enable Two-factor Authentication for your account.'
|
||||
else
|
||||
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
|
||||
|
||||
@qr_code = build_qr_code
|
||||
|
|
|
@ -28,6 +28,11 @@ class Projects::ApplicationController < ApplicationController
|
|||
|
||||
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
|
||||
return render_404 unless @project.builds_enabled?
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Projects::ArtifactsController < Projects::ApplicationController
|
||||
layout 'project'
|
||||
before_action :authorize_read_build_artifacts!
|
||||
before_action :authorize_read_build!
|
||||
|
||||
def download
|
||||
unless artifacts_file.file_storage?
|
||||
|
@ -43,14 +43,4 @@ class Projects::ArtifactsController < Projects::ApplicationController
|
|||
def artifacts_file
|
||||
@artifacts_file ||= build.artifacts_file
|
||||
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
|
||||
|
|
|
@ -2,15 +2,13 @@ class Projects::AvatarsController < Projects::ApplicationController
|
|||
before_action :project
|
||||
|
||||
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
|
||||
headers['X-Content-Type-Options'] = 'nosniff'
|
||||
send_data(
|
||||
@blob.data,
|
||||
type: @blob.mime_type,
|
||||
disposition: 'inline',
|
||||
filename: @blob.name
|
||||
)
|
||||
headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob))
|
||||
headers['Content-Disposition'] = 'inline'
|
||||
headers['Content-Type'] = @blob.content_type
|
||||
head :ok # 'render nothing: true' messes up the Content-Type
|
||||
else
|
||||
render_404
|
||||
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
|
||||
@last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
|
||||
blob.load_all_data!(@repository)
|
||||
end
|
||||
|
||||
def update
|
||||
|
@ -51,6 +52,7 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
|
||||
def preview
|
||||
@content = params[:content]
|
||||
@blob.load_all_data!(@repository)
|
||||
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
|
||||
diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
|
||||
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
class Projects::BuildsController < Projects::ApplicationController
|
||||
before_action :build, except: [:index, :cancel_all]
|
||||
|
||||
before_action :authorize_manage_builds!, except: [:index, :show, :status]
|
||||
|
||||
layout "project"
|
||||
before_action :authorize_read_build!, except: [:cancel, :cancel_all, :retry]
|
||||
before_action :authorize_update_build!, except: [:index, :show, :status]
|
||||
layout 'project'
|
||||
|
||||
def index
|
||||
@scope = params[:scope]
|
||||
|
@ -23,7 +22,6 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
|
||||
def cancel_all
|
||||
@project.builds.running_or_pending.each(&:cancel)
|
||||
|
||||
redirect_to namespace_project_builds_path(project.namespace, project)
|
||||
end
|
||||
|
||||
|
@ -46,18 +44,22 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
build = Ci::Build.retry(@build)
|
||||
|
||||
redirect_to build_path(build)
|
||||
end
|
||||
|
||||
def cancel
|
||||
@build.cancel
|
||||
redirect_to build_path(@build)
|
||||
end
|
||||
|
||||
def status
|
||||
render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
|
||||
end
|
||||
|
||||
def cancel
|
||||
@build.cancel
|
||||
|
||||
redirect_to build_path(@build)
|
||||
def erase
|
||||
@build.erase(erased_by: current_user)
|
||||
redirect_to namespace_project_build_path(project.namespace, project, @build),
|
||||
notice: "Build has been sucessfully erased!"
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -69,10 +71,4 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
def build_path(build)
|
||||
namespace_project_build_path(build.project.namespace, build.project, build)
|
||||
end
|
||||
|
||||
def authorize_manage_builds!
|
||||
unless can?(current_user, :manage_builds, project)
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,16 +2,19 @@
|
|||
#
|
||||
# Not to be confused with CommitsController, plural.
|
||||
class Projects::CommitController < Projects::ApplicationController
|
||||
include CreatesCommit
|
||||
|
||||
# Authorize
|
||||
before_action :require_non_empty_project
|
||||
before_action :authorize_download_code!, except: [:cancel_builds]
|
||||
before_action :authorize_manage_builds!, only: [:cancel_builds]
|
||||
before_action :authorize_download_code!, except: [:cancel_builds, :retry_builds]
|
||||
before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds]
|
||||
before_action :authorize_read_commit_status!, only: [:builds]
|
||||
before_action :commit
|
||||
before_action :authorize_manage_builds!, only: [:cancel_builds, :retry_builds]
|
||||
before_action :define_show_vars, only: [:show, :builds]
|
||||
before_action :authorize_edit_tree!, only: [:revert]
|
||||
|
||||
def show
|
||||
return git_not_found! unless @commit
|
||||
apply_diff_view_cookie!
|
||||
|
||||
@line_notes = commit.notes.inline
|
||||
@note = @project.build_commit_note(commit)
|
||||
|
@ -55,8 +58,37 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
render layout: false
|
||||
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
|
||||
|
||||
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
|
||||
@commit ||= @project.commit(params[:id])
|
||||
end
|
||||
|
@ -66,6 +98,8 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def define_show_vars
|
||||
return git_not_found! unless commit
|
||||
|
||||
if params[:w].to_i == 1
|
||||
@diffs = commit.diffs({ ignore_whitespace_change: true })
|
||||
else
|
||||
|
@ -78,9 +112,15 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
@statuses = ci_commit.statuses if ci_commit
|
||||
end
|
||||
|
||||
def authorize_manage_builds!
|
||||
unless can?(current_user, :manage_builds, project)
|
||||
return render_404
|
||||
end
|
||||
def assign_revert_commit_vars
|
||||
@commit = project.commit(params[:id])
|
||||
@target_branch = params[:target_branch]
|
||||
@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
|
||||
|
|
|
@ -21,6 +21,9 @@ class Projects::CommitsController < Projects::ApplicationController
|
|||
@note_counts = project.notes.where(commit_id: @commits.map(&:id)).
|
||||
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|
|
||||
format.html
|
||||
format.json { pager_json("projects/commits/_commits", @commits.size) }
|
||||
|
|
|
@ -4,24 +4,23 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
# Authorize
|
||||
before_action :require_non_empty_project
|
||||
before_action :authorize_download_code!
|
||||
before_action :assign_ref_vars, only: [:index, :show]
|
||||
before_action :merge_request, only: [:index, :show]
|
||||
|
||||
def index
|
||||
@ref = Addressable::URI.unescape(params[:to])
|
||||
end
|
||||
|
||||
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'
|
||||
|
||||
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
|
||||
@commits = Commit.decorate(compare_result.commits, @project)
|
||||
@diffs = compare_result.diffs
|
||||
@commit = @project.commit(head_ref)
|
||||
@base_commit = @project.merge_base_commit(base_ref, head_ref)
|
||||
@commit = @project.commit(@head_ref)
|
||||
@base_commit = @project.merge_base_commit(@base_ref, @head_ref)
|
||||
@diff_refs = [@base_commit, @commit]
|
||||
@line_notes = []
|
||||
end
|
||||
|
@ -31,4 +30,16 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
redirect_to namespace_project_compare_path(@project.namespace, @project,
|
||||
params[:from], params[:to])
|
||||
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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue