Merge remote-tracking branch 'upstream/master' into artifacts-from-ref-and-build-name
* upstream/master: (516 commits) Rename `run` task helper method to prevent conflict with StateMachine Add a method in Project to return a cached value of total count of projects Add Changelog entry for Grape upgrade [ci skip] Fix Grape tests. Retain old behavior Update Grape from 0.13.0 to 0.15.0. adds second batch of tests changed to active tense fixes part1 of files to start using active tense Clarify the features for generating default label sets Update tree view to sort folders with submodules Memoize CI config node validator to prevent leaks fix MR source project assignment remove offending empty line Rails prefers require_dependency so that it won't require twice: use Unix line endings for API documentation use long options for curl examples in API documentation (!5703) Prefixes removed branches name with PR number when importing PR from GH Update CHANGELOG Remove SHA suffix for removed branches name when importing PR from GH add linting script for documentation ...
3
.gitattributes
vendored
|
@ -1 +1,2 @@
|
|||
CHANGELOG merge=union
|
||||
CHANGELOG merge=union
|
||||
*.js.es6 gitlab-language=javascript
|
||||
|
|
1
.gitignore
vendored
|
@ -30,6 +30,7 @@
|
|||
/config/secrets.yml
|
||||
/config/sidekiq.yml
|
||||
/coverage/*
|
||||
/coverage-javascript/
|
||||
/db/*.sqlite3
|
||||
/db/*.sqlite3-journal
|
||||
/db/data.yml
|
||||
|
|
|
@ -28,6 +28,7 @@ stages:
|
|||
- prepare
|
||||
- test
|
||||
- post-test
|
||||
- pages
|
||||
|
||||
# Prepare and merge knapsack tests
|
||||
.knapsack-state: &knapsack-state
|
||||
|
@ -40,6 +41,7 @@ stages:
|
|||
paths:
|
||||
- knapsack/
|
||||
artifacts:
|
||||
expire_in: 31d
|
||||
paths:
|
||||
- knapsack/
|
||||
|
||||
|
@ -81,8 +83,10 @@ update-knapsack:
|
|||
- cp knapsack/rspec_report.json ${KNAPSACK_REPORT_PATH}
|
||||
- knapsack rspec
|
||||
artifacts:
|
||||
expire_in: 31d
|
||||
paths:
|
||||
- knapsack/
|
||||
- coverage/
|
||||
|
||||
.spinach-knapsack: &spinach-knapsack
|
||||
stage: test
|
||||
|
@ -97,8 +101,10 @@ update-knapsack:
|
|||
- cp knapsack/spinach_report.json ${KNAPSACK_REPORT_PATH}
|
||||
- knapsack spinach "-r rerun" || retry '[ ! -e tmp/spinach-rerun.txt ] || bundle exec spinach -r rerun $(cat tmp/spinach-rerun.txt)'
|
||||
artifacts:
|
||||
expire_in: 31d
|
||||
paths:
|
||||
- knapsack/
|
||||
- coverage/
|
||||
|
||||
rspec 0 20: *rspec-knapsack
|
||||
rspec 1 20: *rspec-knapsack
|
||||
|
@ -186,14 +192,14 @@ spinach 9 10 ruby23: *spinach-knapsack-ruby23
|
|||
|
||||
# Other generic tests
|
||||
|
||||
.static-analyses-variables: &static-analyses-variables
|
||||
.ruby-static-analysis: &ruby-static-analysis
|
||||
variables:
|
||||
SIMPLECOV: "false"
|
||||
USE_DB: "false"
|
||||
USE_BUNDLE_INSTALL: "true"
|
||||
|
||||
.exec: &exec
|
||||
<<: *static-analyses-variables
|
||||
<<: *ruby-static-analysis
|
||||
stage: test
|
||||
script:
|
||||
- bundle exec $CI_BUILD_NAME
|
||||
|
@ -216,20 +222,54 @@ teaspoon:
|
|||
stage: test
|
||||
<<: *use-db
|
||||
script:
|
||||
- curl --silent --location https://deb.nodesource.com/setup_6.x | bash -
|
||||
- apt-get install --assume-yes nodejs
|
||||
- npm install --global istanbul
|
||||
- teaspoon
|
||||
artifacts:
|
||||
name: coverage-javascript
|
||||
expire_in: 31d
|
||||
paths:
|
||||
- coverage-javascript/default/
|
||||
|
||||
lint-doc:
|
||||
stage: test
|
||||
image: "phusion/baseimage:latest"
|
||||
before_script: []
|
||||
script:
|
||||
- scripts/lint-doc.sh
|
||||
|
||||
bundler:audit:
|
||||
stage: test
|
||||
<<: *static-analyses-variables
|
||||
<<: *ruby-static-analysis
|
||||
only:
|
||||
- master
|
||||
script:
|
||||
- "bundle exec bundle-audit check --update --ignore OSVDB-115941"
|
||||
|
||||
coverage:
|
||||
stage: post-test
|
||||
services: []
|
||||
variables:
|
||||
USE_DB: "false"
|
||||
USE_BUNDLE_INSTALL: "true"
|
||||
script:
|
||||
- bundle exec scripts/merge-simplecov
|
||||
artifacts:
|
||||
name: coverage
|
||||
expire_in: 31d
|
||||
paths:
|
||||
- coverage/index.html
|
||||
- coverage/assets/
|
||||
|
||||
|
||||
# Notify slack in the end
|
||||
|
||||
notify:slack:
|
||||
stage: post-test
|
||||
variables:
|
||||
USE_DB: "false"
|
||||
USE_BUNDLE_INSTALL: "false"
|
||||
script:
|
||||
- ./scripts/notify_slack.sh "#builds" "Build on \`$CI_BUILD_REF_NAME\` failed! Commit \`$(git log -1 --oneline)\` See <https://gitlab.com/gitlab-org/$(basename "$PWD")/commit/"$CI_BUILD_REF"/builds>"
|
||||
when: on_failure
|
||||
|
@ -238,3 +278,20 @@ notify:slack:
|
|||
- tags@gitlab-org/gitlab-ce
|
||||
- master@gitlab-org/gitlab-ee
|
||||
- tags@gitlab-org/gitlab-ee
|
||||
|
||||
pages:
|
||||
before_script: []
|
||||
stage: pages
|
||||
dependencies:
|
||||
- coverage
|
||||
- teaspoon
|
||||
script:
|
||||
- mv public/ .public/
|
||||
- mkdir public/
|
||||
- mv coverage public/coverage-ruby
|
||||
- mv coverage-javascript/default/ public/coverage-javascript/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
|
|
21
.rubocop.yml
|
@ -149,19 +149,19 @@ Style/EmptyLinesAroundAccessModifier:
|
|||
|
||||
# Keeps track of empty lines around block bodies.
|
||||
Style/EmptyLinesAroundBlockBody:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# Keeps track of empty lines around class bodies.
|
||||
Style/EmptyLinesAroundClassBody:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# Keeps track of empty lines around module bodies.
|
||||
Style/EmptyLinesAroundModuleBody:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# Keeps track of empty lines around method bodies.
|
||||
Style/EmptyLinesAroundMethodBody:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# Avoid the use of END blocks.
|
||||
Style/EndBlock:
|
||||
|
@ -373,6 +373,10 @@ Style/SpaceAfterNot:
|
|||
Style/SpaceAfterSemicolon:
|
||||
Enabled: true
|
||||
|
||||
# Use space around equals in parameter default
|
||||
Style/SpaceAroundEqualsInParameterDefault:
|
||||
Enabled: true
|
||||
|
||||
# Use a space around keywords if appropriate.
|
||||
Style/SpaceAroundKeyword:
|
||||
Enabled: true
|
||||
|
@ -510,6 +514,15 @@ Metrics/PerceivedComplexity:
|
|||
|
||||
#################### Lint ################################
|
||||
|
||||
# Checks for useless access modifiers.
|
||||
Lint/UselessAccessModifier:
|
||||
Enabled: true
|
||||
|
||||
# Checks for attempts to use `private` or `protected` to set the visibility
|
||||
# of a class method, which does not work.
|
||||
Lint/IneffectiveAccessModifier:
|
||||
Enabled: false
|
||||
|
||||
# Checks for ambiguous operators in the first argument of a method invocation
|
||||
# without parentheses.
|
||||
Lint/AmbiguousOperator:
|
||||
|
|
|
@ -19,10 +19,6 @@ Lint/AssignmentInCondition:
|
|||
Lint/HandleExceptions:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 21
|
||||
Lint/IneffectiveAccessModifier:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 2
|
||||
Lint/Loop:
|
||||
Enabled: false
|
||||
|
@ -48,10 +44,6 @@ Lint/UnusedBlockArgument:
|
|||
Lint/UnusedMethodArgument:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 11
|
||||
Lint/UselessAccessModifier:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 12
|
||||
# Cop supports --auto-correct.
|
||||
Performance/PushSplat:
|
||||
|
@ -347,13 +339,6 @@ Style/SingleLineBlockParams:
|
|||
Style/SingleLineMethods:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 14
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: space, no_space
|
||||
Style/SpaceAroundEqualsInParameterDefault:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 119
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
# .simplecov
|
||||
SimpleCov.start 'rails' do
|
||||
merge_timeout 3600
|
||||
end
|
140
CHANGELOG
|
@ -1,18 +1,141 @@
|
|||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 8.11.0 (unreleased)
|
||||
- Remove magic comments (`# encoding: UTF-8`) from Ruby files !5456 (winniehell)
|
||||
- Fix don't pass a local variable called `i` to a partial. !20510 (herminiotorres)
|
||||
- Fix rename `add_users_into_project` and `projects_ids`. !20512 (herminiotorres)
|
||||
- Fix the title of the toggle dropdown button. !5515 (herminiotorres)
|
||||
- Improve diff performance by eliminating redundant checks for text blobs
|
||||
- Convert switch icon into icon font (ClemMakesApps)
|
||||
- API: Endpoints for enabling and disabling deploy keys
|
||||
- Use long options for curl examples in documentation !5703 (winniehell)
|
||||
- Remove magic comments (`# encoding: UTF-8`) from Ruby files. !5456 (winniehell)
|
||||
- Add support for relative links starting with ./ or / to RelativeLinkFilter (winniehell)
|
||||
- Ignore URLs starting with // in Markdown links !5677 (winniehell)
|
||||
- Fix CI status icon link underline (ClemMakesApps)
|
||||
- The Repository class is now instrumented
|
||||
- Cache the commit author in RequestStore to avoid extra lookups in PostReceive
|
||||
- Expand commit message width in repo view (ClemMakesApps)
|
||||
- Cache highlighted diff lines for merge requests
|
||||
- Fix of 'Commits being passed to custom hooks are already reachable when using the UI'
|
||||
- Add support for using RequestStore within Sidekiq tasks via SIDEKIQ_REQUEST_STORE env variable
|
||||
- Optimize maximum user access level lookup in loading of notes
|
||||
- Add "No one can push" as an option for protected branches. !5081
|
||||
- Improve performance of AutolinkFilter#text_parse by using XPath
|
||||
- Add experimental Redis Sentinel support !1877
|
||||
- Environments have an url to link to
|
||||
- Update `timeago` plugin to use multiple string/locale settings
|
||||
- Remove unused images (ClemMakesApps)
|
||||
- Limit git rev-list output count to one in forced push check
|
||||
- Clean up unused routes (Josef Strzibny)
|
||||
- Fix issue on empty project to allow developers to only push to protected branches if given permission
|
||||
- Add green outline to New Branch button. !5447 (winniehell)
|
||||
- Optimize generating of cache keys for issues and notes
|
||||
- Improve performance of syntax highlighting Markdown code blocks
|
||||
- Update to gitlab_git 10.4.1 and take advantage of preserved Ref objects
|
||||
- Remove delay when hitting "Reply..." button on page with a lot of discussions
|
||||
- Retrieve rendered HTML from cache in one request
|
||||
- Make fork counter always clickable !5463 (winniehell)
|
||||
- Load project invited groups and members eagerly in ProjectTeam#fetch_members
|
||||
- Fix renaming repository when name contains invalid chararacters under project settings
|
||||
- Upgrade Grape from 0.13.0 to 0.15.0. !4601
|
||||
- Fix devise deprecation warnings.
|
||||
- Update version_sorter and use new interface for faster tag sorting
|
||||
- Optimize checking if a user has read access to a list of issues !5370
|
||||
- Nokogiri's various parsing methods are now instrumented
|
||||
- Add simple identifier to public SSH keys (muteor)
|
||||
- Admin page now references docs instead of a specific file !5600 (AnAverageHuman)
|
||||
- Add a way to send an email and create an issue based on private personal token. Find the email address from issues page. !3363
|
||||
- Fix filter input alignment (ClemMakesApps)
|
||||
- Include old revision in merge request update hooks (Ben Boeckel)
|
||||
- Add build event color in HipChat messages (David Eisner)
|
||||
- Make fork counter always clickable. !5463 (winniehell)
|
||||
- Document that webhook secret token is sent in X-Gitlab-Token HTTP header !5664 (lycoperdon)
|
||||
- Gitlab::Highlight is now instrumented
|
||||
- All created issues, API or WebUI, can be submitted to Akismet for spam check !5333
|
||||
- Allow users to import cross-repository pull requests from GitHub
|
||||
- The overhead of instrumented method calls has been reduced
|
||||
- Remove `search_id` of labels dropdown filter to fix 'Missleading URI for labels in Merge Requests and Issues view'. !5368 (Scott Le)
|
||||
- Load project invited groups and members eagerly in `ProjectTeam#fetch_members`
|
||||
- Bump gitlab_git to speedup DiffCollection iterations
|
||||
- Rewrite description of a blocked user in admin settings. (Elias Werberich)
|
||||
- Make branches sortable without push permission !5462 (winniehell)
|
||||
- Check for Ci::Build artifacts at database level on pipeline partial
|
||||
- Convert image diff background image to CSS (ClemMakesApps)
|
||||
- Remove unnecessary index_projects_on_builds_enabled index from the projects table
|
||||
- Make "New issue" button in Issue page less obtrusive !5457 (winniehell)
|
||||
- Gitlab::Metrics.current_transaction needs to be public for RailsQueueDuration
|
||||
- Fix search for notes which belongs to deleted objects
|
||||
- Add GitLab Workhorse version to admin dashboard (Katarzyna Kobierska Ula Budziszewska)
|
||||
- Allow branch names ending with .json for graph and network page !5579 (winniehell)
|
||||
- Add the `sprockets-es6` gem
|
||||
- Multiple trigger variables show in separate lines (Katarzyna Kobierska Ula Budziszewska)
|
||||
- Profile requests when a header is passed
|
||||
- Avoid calculation of line_code and position for _line partial when showing diff notes on discussion tab.
|
||||
- Speedup DiffNote#active? on discussions, preloading noteables and avoid touching git repository to return diff_refs when possible
|
||||
- Add commit stats in commit api. !5517 (dixpac)
|
||||
- Add CI configuration button on project page
|
||||
- Make error pages responsive (Takuya Noguchi)
|
||||
- Fix skip_repo parameter being ignored when destroying a namespace
|
||||
- Change requests_profiles resource constraint to catch virtually any file
|
||||
- Bump gitlab_git to lazy load compare commits
|
||||
- Reduce number of queries made for merge_requests/:id/diffs
|
||||
- Sensible state specific default sort order for issues and merge requests !5453 (tomb0y)
|
||||
- Fix RequestProfiler::Middleware error when code is reloaded in development
|
||||
- Catch what warden might throw when profiling requests to re-throw it
|
||||
- Add description to new_issue email and new_merge_request_email in text/plain content type. !5663 (dixpac)
|
||||
- Speed up and reduce memory usage of Commit#repo_changes, Repository#expire_avatar_cache and IrkerWorker
|
||||
- Add unfold links for Side-by-Side view. !5415 (Tim Masliuchenko)
|
||||
- Adds support for pending invitation project members importing projects
|
||||
- Update devise initializer to turn on changed password notification emails. !5648 (tombell)
|
||||
- Avoid to show the original password field when password is automatically set. !5712 (duduribeiro)
|
||||
- Fix importing GitLab projects with an invalid MR source project
|
||||
- Sort folders with submodules in Files view !5521
|
||||
|
||||
v 8.10.1 (unreleased)
|
||||
- Fix Error 500 when creating Wiki pages with hyphens or spaces
|
||||
- Ignore invalid trusted proxies in X-Forwarded-For header
|
||||
- Fix bug where replies to commit notes displayed in the MR discussion tab wouldn't show up on the commit page
|
||||
v 8.10.5 (unreleased)
|
||||
|
||||
v 8.10.4
|
||||
- Don't close referenced upstream issues from a forked project.
|
||||
- Fixes issue with dropdowns `enter` key not working correctly. !5544
|
||||
- Fix Import/Export project import not working in HA mode. !5618
|
||||
- Fix Import/Export error checking versions. !5638
|
||||
|
||||
v 8.10.3
|
||||
- Fix Import/Export issue importing milestones and labels not associated properly. !5426
|
||||
- Fix timing problems running imports on production. !5523
|
||||
- Add a log message when a project is scheduled for destruction for debugging. !5540
|
||||
- Fix hooks missing on imported GitLab projects. !5549
|
||||
- Properly abort a merge when merge conflicts occur. !5569
|
||||
- Fix importer for GitHub Pull Requests when a branch was removed. !5573
|
||||
- Ignore invalid IPs in X-Forwarded-For when trusted proxies are configured. !5584
|
||||
- Trim extra displayed carriage returns in diffs and files with CRLFs. !5588
|
||||
|
||||
v 8.10.2
|
||||
- User can now search branches by name. !5144
|
||||
- Page is now properly rendered after committing the first file and creating the first branch. !5399
|
||||
- Add branch or tag icon to ref in builds page. !5434
|
||||
- Fix backup restore. !5459
|
||||
- Use project ID in repository cache to prevent stale data from persisting across projects. !5460
|
||||
- Fix issue with autocomplete search not working with enter key. !5466
|
||||
- Add iid to MR API response. !5468
|
||||
- Disable MySQL foreign key checks before dropping all tables. !5472
|
||||
- Ensure relative paths for video are rewritten as we do for images. !5474
|
||||
- Ensure current user can retry a build before showing the 'Retry' button. !5476
|
||||
- Add ENV variable to skip repository storages validations. !5478
|
||||
- Added `*.js.es6 gitlab-language=javascript` to `.gitattributes`. !5486
|
||||
- Don't show comment button in gutter of diffs on MR discussion tab. !5493
|
||||
- Rescue Rugged::OSError (lock exists) when creating references. !5497
|
||||
- Fix expand all diffs button in compare view. !5500
|
||||
- Show release notes in tags list. !5503
|
||||
- Fix a bug where forking a project from a repository storage to another would fail. !5509
|
||||
- Fix missing schema update for `20160722221922`. !5512
|
||||
- Update `gitlab-shell` version to 3.2.1 in the 8.9->8.10 update guide. !5516
|
||||
|
||||
v 8.10.1
|
||||
- Refactor repository storages documentation. !5428
|
||||
- Gracefully handle case when keep-around references are corrupted or exist already. !5430
|
||||
- Add detailed info on storage path mountpoints. !5437
|
||||
- Fix Error 500 when creating Wiki pages with hyphens or spaces. !5444
|
||||
- Fix bug where replies to commit notes displayed in the MR discussion tab wouldn't show up on the commit page. !5446
|
||||
- Ignore invalid trusted proxies in X-Forwarded-For header. !5454
|
||||
- Add links to the real markdown.md file for all GFM examples. !5458
|
||||
|
||||
v 8.10.0
|
||||
- Fix profile activity heatmap to show correct day name (eanplatter)
|
||||
|
@ -61,6 +184,9 @@ v 8.10.0
|
|||
- Fix check for New Branch button on Issue page. !4630 (winniehell)
|
||||
- Fix GFM autocomplete not working on wiki pages
|
||||
- Fixed enter key not triggering click on first row when searching in a dropdown
|
||||
- Updated dropdowns in issuable form to use new GitLab dropdown style
|
||||
- Make images fit to the size of the viewport !4810
|
||||
- Fix check for New Branch button on Issue page !4630 (winniehell)
|
||||
- Fix MR-auto-close text added to description. !4836
|
||||
- Support U2F devices in Firefox. !5177
|
||||
- Fix issue, preventing users w/o push access to sort tags. !5105 (redetection)
|
||||
|
|
|
@ -41,6 +41,8 @@ abbreviation.
|
|||
If you have read this guide and want to know how the GitLab [core team]
|
||||
operates please see [the GitLab contributing process](PROCESS.md).
|
||||
|
||||
- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
|
||||
|
||||
## Contributor license agreement
|
||||
|
||||
By submitting code as an individual you agree to the
|
||||
|
@ -334,6 +336,10 @@ request is as follows:
|
|||
1. If your code creates new files on disk please read the
|
||||
[shared files guidelines](doc/development/shared_files.md).
|
||||
1. When writing commit messages please follow [these](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) [guidelines](http://chris.beams.io/posts/git-commit/).
|
||||
1. If your merge request adds one or more migrations, make sure to execute all
|
||||
migrations on a fresh database before the MR is reviewed. If the review leads
|
||||
to large changes in the MR, do this again once the review is complete.
|
||||
1. For more complex migrations, write tests.
|
||||
|
||||
The **official merge window** is in the beginning of the month from the 1st to
|
||||
the 7th day of the month. This is the best time to submit an MR and get
|
||||
|
@ -459,8 +465,10 @@ merge request:
|
|||
- multi-line method chaining style **Option B**: dot `.` on previous line
|
||||
- string literal quoting style **Option A**: single quoted by default
|
||||
1. [Rails](https://github.com/bbatsov/rails-style-guide)
|
||||
1. [Newlines styleguide][newlines-styleguide]
|
||||
1. [Testing](doc/development/testing.md)
|
||||
1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style/coffeescript)
|
||||
1. [JavaScript (ES6)](https://github.com/airbnb/javascript)
|
||||
1. [JavaScript (ES5)](https://github.com/airbnb/javascript/tree/master/es5)
|
||||
1. [SCSS styleguide][scss-styleguide]
|
||||
1. [Shell commands](doc/development/shell_commands.md) created by GitLab
|
||||
contributors to enhance security
|
||||
|
@ -530,6 +538,7 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
|
|||
[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
|
||||
[doc-styleguide]: doc/development/doc_styleguide.md "Documentation styleguide"
|
||||
[scss-styleguide]: doc/development/scss_styleguide.md "SCSS styleguide"
|
||||
[newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide"
|
||||
[gitlab-design]: https://gitlab.com/gitlab-org/gitlab-design
|
||||
[free Antetype viewer (Mac OSX only)]: https://itunes.apple.com/us/app/antetype-viewer/id824152298?mt=12
|
||||
[`gitlab8.atype` file]: https://gitlab.com/gitlab-org/gitlab-design/tree/master/current/
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.2.0
|
||||
3.2.1
|
||||
|
|
19
Gemfile
|
@ -9,6 +9,7 @@ gem 'responders', '~> 2.0'
|
|||
# Specify a sprockets version due to increased performance
|
||||
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/6069
|
||||
gem 'sprockets', '~> 3.6.0'
|
||||
gem 'sprockets-es6'
|
||||
|
||||
# Default values for AR models
|
||||
gem 'default_value_for', '~> 3.0.0'
|
||||
|
@ -52,7 +53,7 @@ gem 'browser', '~> 2.2'
|
|||
|
||||
# Extracting information from a git repository
|
||||
# Provide access to Gitlab::Git library
|
||||
gem 'gitlab_git', '~> 10.3.2'
|
||||
gem 'gitlab_git', '~> 10.4.5'
|
||||
|
||||
# LDAP Auth
|
||||
# GitLab fork with several improvements to original library. For full list of changes
|
||||
|
@ -68,7 +69,7 @@ gem 'gollum-rugged_adapter', '~> 0.4.2', require: false
|
|||
gem 'github-linguist', '~> 4.7.0', require: 'linguist'
|
||||
|
||||
# API
|
||||
gem 'grape', '~> 0.13.0'
|
||||
gem 'grape', '~> 0.15.0'
|
||||
gem 'grape-entity', '~> 0.4.2'
|
||||
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
||||
|
||||
|
@ -153,7 +154,7 @@ gem 'settingslogic', '~> 2.0.9'
|
|||
|
||||
# Misc
|
||||
|
||||
gem 'version_sorter', '~> 2.0.0'
|
||||
gem 'version_sorter', '~> 2.1.0'
|
||||
|
||||
# Cache
|
||||
gem 'redis-rails', '~> 4.0.0'
|
||||
|
@ -224,7 +225,7 @@ gem 'addressable', '~> 2.3.8'
|
|||
gem 'bootstrap-sass', '~> 3.3.0'
|
||||
gem 'font-awesome-rails', '~> 4.6.1'
|
||||
gem 'gemojione', '~> 3.0'
|
||||
gem 'gon', '~> 6.0.1'
|
||||
gem 'gon', '~> 6.1.0'
|
||||
gem 'jquery-atwho-rails', '~> 1.3.2'
|
||||
gem 'jquery-rails', '~> 4.1.0'
|
||||
gem 'jquery-ui-rails', '~> 5.0.0'
|
||||
|
@ -252,7 +253,7 @@ group :development do
|
|||
|
||||
gem 'letter_opener_web', '~> 1.3.0'
|
||||
gem 'rerun', '~> 0.11.0'
|
||||
gem 'bullet', '~> 5.0.0', require: false
|
||||
gem 'bullet', '~> 5.2.0', require: false
|
||||
gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
|
||||
gem 'web-console', '~> 2.0'
|
||||
|
||||
|
@ -274,7 +275,7 @@ group :development, :test do
|
|||
gem 'awesome_print', '~> 1.2.0', require: false
|
||||
gem 'fuubar', '~> 2.0.0'
|
||||
|
||||
gem 'database_cleaner', '~> 1.4.0'
|
||||
gem 'database_cleaner', '~> 1.5.0'
|
||||
gem 'factory_girl_rails', '~> 4.6.0'
|
||||
gem 'rspec-rails', '~> 3.5.0'
|
||||
gem 'rspec-retry', '~> 0.4.5'
|
||||
|
@ -302,7 +303,7 @@ group :development, :test do
|
|||
gem 'rubocop', '~> 0.41.2', require: false
|
||||
gem 'rubocop-rspec', '~> 1.5.0', require: false
|
||||
gem 'scss_lint', '~> 0.47.0', require: false
|
||||
gem 'simplecov', '~> 0.11.0', require: false
|
||||
gem 'simplecov', '0.12.0', require: false
|
||||
gem 'flog', '~> 4.3.2', require: false
|
||||
gem 'flay', '~> 2.6.1', require: false
|
||||
gem 'bundler-audit', '~> 0.5.0', require: false
|
||||
|
@ -325,7 +326,7 @@ group :production do
|
|||
gem 'gitlab_meta', '7.0'
|
||||
end
|
||||
|
||||
gem 'newrelic_rpm', '~> 3.14'
|
||||
gem 'newrelic_rpm', '~> 3.16'
|
||||
|
||||
gem 'octokit', '~> 4.3.0'
|
||||
|
||||
|
@ -333,6 +334,8 @@ gem 'mail_room', '~> 0.8'
|
|||
|
||||
gem 'email_reply_parser', '~> 0.5.8'
|
||||
|
||||
gem 'ruby-prof', '~> 0.15.9'
|
||||
|
||||
## CI
|
||||
gem 'activerecord-session_store', '~> 1.0.0'
|
||||
gem 'nested_form', '~> 0.3.2'
|
||||
|
|
59
Gemfile.lock
|
@ -59,7 +59,7 @@ GEM
|
|||
oauth2 (~> 1.0)
|
||||
asciidoctor (1.5.3)
|
||||
ast (2.3.0)
|
||||
attr_encrypted (3.0.1)
|
||||
attr_encrypted (3.0.3)
|
||||
encryptor (~> 3.0.0)
|
||||
attr_required (1.0.0)
|
||||
autoprefixer-rails (6.2.3)
|
||||
|
@ -85,6 +85,10 @@ GEM
|
|||
faraday (~> 0.9)
|
||||
faraday_middleware (~> 0.10)
|
||||
nokogiri (~> 1.6)
|
||||
babel-source (5.8.35)
|
||||
babel-transpiler (0.7.0)
|
||||
babel-source (>= 4.0, < 6)
|
||||
execjs (~> 2.0)
|
||||
babosa (1.0.2)
|
||||
base32 (0.3.2)
|
||||
bcrypt (3.1.11)
|
||||
|
@ -100,9 +104,9 @@ GEM
|
|||
brakeman (3.3.2)
|
||||
browser (2.2.0)
|
||||
builder (3.2.2)
|
||||
bullet (5.0.0)
|
||||
bullet (5.2.0)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.9.0)
|
||||
uniform_notifier (~> 1.10.0)
|
||||
bundler-audit (0.5.0)
|
||||
bundler (~> 1.2)
|
||||
thor (~> 0.18)
|
||||
|
@ -149,11 +153,11 @@ GEM
|
|||
d3_rails (3.5.11)
|
||||
railties (>= 3.1.0)
|
||||
daemons (1.2.3)
|
||||
database_cleaner (1.4.1)
|
||||
database_cleaner (1.5.3)
|
||||
debug_inspector (0.0.2)
|
||||
debugger-ruby_core_source (1.3.8)
|
||||
default_value_for (3.0.1)
|
||||
activerecord (>= 3.2.0, < 5.0)
|
||||
default_value_for (3.0.2)
|
||||
activerecord (>= 3.2.0, < 5.1)
|
||||
descendants_tracker (0.0.4)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
devise (4.1.1)
|
||||
|
@ -274,7 +278,7 @@ GEM
|
|||
diff-lcs (~> 1.1)
|
||||
mime-types (>= 1.16, < 3)
|
||||
posix-spawn (~> 0.3)
|
||||
gitlab_git (10.3.2)
|
||||
gitlab_git (10.4.5)
|
||||
activesupport (~> 4.0)
|
||||
charlock_holmes (~> 0.7.3)
|
||||
github-linguist (~> 4.7.0)
|
||||
|
@ -299,12 +303,12 @@ GEM
|
|||
gollum-rugged_adapter (0.4.2)
|
||||
mime-types (>= 1.15)
|
||||
rugged (~> 0.24.0, >= 0.21.3)
|
||||
gon (6.0.1)
|
||||
gon (6.1.0)
|
||||
actionpack (>= 3.0)
|
||||
json
|
||||
multi_json
|
||||
request_store (>= 1.0)
|
||||
grape (0.13.0)
|
||||
grape (0.15.0)
|
||||
activesupport
|
||||
builder
|
||||
hashie (>= 2.1.0)
|
||||
|
@ -400,7 +404,7 @@ GEM
|
|||
nested_form (0.3.2)
|
||||
net-ldap (0.12.1)
|
||||
net-ssh (3.0.1)
|
||||
newrelic_rpm (3.14.1.311)
|
||||
newrelic_rpm (3.16.0.318)
|
||||
nokogiri (1.6.8)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
pkg-config (~> 1.1.7)
|
||||
|
@ -505,7 +509,7 @@ GEM
|
|||
rack-cors (0.4.0)
|
||||
rack-mount (0.8.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-oauth2 (1.2.1)
|
||||
rack-oauth2 (1.2.3)
|
||||
activesupport (>= 2.3)
|
||||
attr_required (>= 0.0.5)
|
||||
httpclient (>= 2.4)
|
||||
|
@ -571,7 +575,7 @@ GEM
|
|||
redis-store (~> 1.1.0)
|
||||
redis-store (1.1.7)
|
||||
redis (>= 2.2)
|
||||
request_store (1.3.0)
|
||||
request_store (1.3.1)
|
||||
rerun (0.11.0)
|
||||
listen (~> 3.0)
|
||||
responders (2.1.1)
|
||||
|
@ -616,6 +620,7 @@ GEM
|
|||
rubocop (>= 0.40.0)
|
||||
ruby-fogbugz (0.2.1)
|
||||
crack (~> 0.4)
|
||||
ruby-prof (0.15.9)
|
||||
ruby-progressbar (1.8.1)
|
||||
ruby-saml (1.3.0)
|
||||
nokogiri (>= 1.5.10)
|
||||
|
@ -668,9 +673,9 @@ GEM
|
|||
rufus-scheduler (>= 2.0.24)
|
||||
sidekiq (>= 4.0.0)
|
||||
simple_oauth (0.1.9)
|
||||
simplecov (0.11.2)
|
||||
simplecov (0.12.0)
|
||||
docile (~> 1.1.0)
|
||||
json (~> 1.8)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.0)
|
||||
sinatra (1.4.7)
|
||||
|
@ -700,6 +705,10 @@ GEM
|
|||
sprockets (3.6.3)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-es6 (0.9.0)
|
||||
babel-source (>= 5.8.11)
|
||||
babel-transpiler
|
||||
sprockets (>= 3.0.0)
|
||||
sprockets-rails (3.1.1)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
|
@ -766,10 +775,10 @@ GEM
|
|||
unicorn-worker-killer (0.4.4)
|
||||
get_process_mem (~> 0)
|
||||
unicorn (>= 4, < 6)
|
||||
uniform_notifier (1.9.0)
|
||||
uniform_notifier (1.10.0)
|
||||
uuid (2.3.8)
|
||||
macaddr (~> 1.0)
|
||||
version_sorter (2.0.0)
|
||||
version_sorter (2.1.0)
|
||||
virtus (1.0.5)
|
||||
axiom-types (~> 0.1)
|
||||
coercible (~> 1.0)
|
||||
|
@ -821,7 +830,7 @@ DEPENDENCIES
|
|||
bootstrap-sass (~> 3.3.0)
|
||||
brakeman (~> 3.3.0)
|
||||
browser (~> 2.2)
|
||||
bullet (~> 5.0.0)
|
||||
bullet (~> 5.2.0)
|
||||
bundler-audit (~> 0.5.0)
|
||||
byebug (~> 8.2.1)
|
||||
capybara (~> 2.6.2)
|
||||
|
@ -833,7 +842,7 @@ DEPENDENCIES
|
|||
connection_pool (~> 2.0)
|
||||
creole (~> 0.5.0)
|
||||
d3_rails (~> 3.5.0)
|
||||
database_cleaner (~> 1.4.0)
|
||||
database_cleaner (~> 1.5.0)
|
||||
default_value_for (~> 3.0.0)
|
||||
devise (~> 4.0)
|
||||
devise-two-factor (~> 3.0.0)
|
||||
|
@ -861,13 +870,13 @@ DEPENDENCIES
|
|||
github-linguist (~> 4.7.0)
|
||||
github-markup (~> 1.4)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab_git (~> 10.3.2)
|
||||
gitlab_git (~> 10.4.5)
|
||||
gitlab_meta (= 7.0)
|
||||
gitlab_omniauth-ldap (~> 1.2.1)
|
||||
gollum-lib (~> 4.2)
|
||||
gollum-rugged_adapter (~> 0.4.2)
|
||||
gon (~> 6.0.1)
|
||||
grape (~> 0.13.0)
|
||||
gon (~> 6.1.0)
|
||||
grape (~> 0.15.0)
|
||||
grape-entity (~> 0.4.2)
|
||||
hamlit (~> 2.5)
|
||||
health_check (~> 2.1.0)
|
||||
|
@ -893,7 +902,7 @@ DEPENDENCIES
|
|||
mysql2 (~> 0.3.16)
|
||||
nested_form (~> 0.3.2)
|
||||
net-ssh (~> 3.0.1)
|
||||
newrelic_rpm (~> 3.14)
|
||||
newrelic_rpm (~> 3.16)
|
||||
nokogiri (~> 1.6.7, >= 1.6.7.2)
|
||||
oauth2 (~> 1.2.0)
|
||||
octokit (~> 4.3.0)
|
||||
|
@ -940,6 +949,7 @@ DEPENDENCIES
|
|||
rubocop (~> 0.41.2)
|
||||
rubocop-rspec (~> 1.5.0)
|
||||
ruby-fogbugz (~> 0.2.1)
|
||||
ruby-prof (~> 0.15.9)
|
||||
sanitize (~> 2.0)
|
||||
sass-rails (~> 5.0.0)
|
||||
scss_lint (~> 0.47.0)
|
||||
|
@ -952,7 +962,7 @@ DEPENDENCIES
|
|||
shoulda-matchers (~> 2.8.0)
|
||||
sidekiq (~> 4.0)
|
||||
sidekiq-cron (~> 0.4.0)
|
||||
simplecov (~> 0.11.0)
|
||||
simplecov (= 0.12.0)
|
||||
sinatra (~> 1.4.4)
|
||||
six (~> 0.2.0)
|
||||
slack-notifier (~> 1.2.0)
|
||||
|
@ -963,6 +973,7 @@ DEPENDENCIES
|
|||
spring-commands-spinach (~> 1.1.0)
|
||||
spring-commands-teaspoon (~> 0.0.2)
|
||||
sprockets (~> 3.6.0)
|
||||
sprockets-es6
|
||||
state_machines-activerecord (~> 0.4.0)
|
||||
sys-filesystem (~> 1.1.6)
|
||||
task_list (~> 1.0.2)
|
||||
|
@ -978,7 +989,7 @@ DEPENDENCIES
|
|||
unf (~> 0.1.4)
|
||||
unicorn (~> 4.9.0)
|
||||
unicorn-worker-killer (~> 0.4.2)
|
||||
version_sorter (~> 2.0.0)
|
||||
version_sorter (~> 2.1.0)
|
||||
virtus (~> 1.0.1)
|
||||
vmstat (~> 2.1.1)
|
||||
web-console (~> 2.0)
|
||||
|
|
|
@ -8,6 +8,8 @@ treatment, etc.). And so that maintainers know what to expect from contributors
|
|||
(use the latest version, ensure that the issue is addressed, friendly treatment,
|
||||
etc.).
|
||||
|
||||
- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
|
||||
|
||||
## Common actions
|
||||
|
||||
### Issue team
|
||||
|
|
Before Width: | Height: | Size: 90 B |
Before Width: | Height: | Size: 167 B |
Before Width: | Height: | Size: 367 B |
Before Width: | Height: | Size: 418 B |
Before Width: | Height: | Size: 222 B |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 197 B |
Before Width: | Height: | Size: 494 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 231 B |
Before Width: | Height: | Size: 49 B |
|
@ -287,7 +287,7 @@
|
|||
$('.page-with-sidebar').toggleClass('page-sidebar-collapsed page-sidebar-expanded').removeClass('page-sidebar-pinned');
|
||||
$('.navbar-fixed-top').removeClass('header-pinned-nav');
|
||||
}
|
||||
return $document.off('click', '.js-nav-pin').on('click', '.js-nav-pin', function(e) {
|
||||
$document.off('click', '.js-nav-pin').on('click', '.js-nav-pin', function(e) {
|
||||
var $page, $pinBtn, $tooltip, $topNav, doPinNav, tooltipText;
|
||||
e.preventDefault();
|
||||
$pinBtn = $(e.currentTarget);
|
||||
|
@ -315,6 +315,8 @@
|
|||
$tooltip.find('.tooltip-inner').text(tooltipText);
|
||||
return $pinBtn.attr('title', tooltipText).tooltip('fixTitle');
|
||||
});
|
||||
});
|
||||
|
||||
// Custom time ago
|
||||
gl.utils.shortTimeAgo($('.js-short-timeago'));
|
||||
});
|
||||
}).call(this);
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
$date = $('.js-artifacts-remove');
|
||||
if ($date.length) {
|
||||
date = $date.text();
|
||||
return $date.text($.timefor(new Date(date), ' '));
|
||||
return $date.text($.timefor(new Date(date.replace(/-/g, '/')), ' '));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
$(document).off('click', '.js-unfold');
|
||||
$(document).on('click', '.js-unfold', (function(_this) {
|
||||
return function(event) {
|
||||
var line_number, link, offset, old_line, params, prev_new_line, prev_old_line, ref, ref1, since, target, to, unfold, unfoldBottom;
|
||||
var line_number, link, file, offset, old_line, params, prev_new_line, prev_old_line, ref, ref1, since, target, to, unfold, unfoldBottom;
|
||||
target = $(event.target);
|
||||
unfoldBottom = target.hasClass('js-unfold-bottom');
|
||||
unfold = true;
|
||||
|
@ -31,14 +31,16 @@
|
|||
unfold = false;
|
||||
}
|
||||
}
|
||||
link = target.parents('.diff-file').attr('data-blob-diff-path');
|
||||
file = target.parents('.diff-file');
|
||||
link = file.data('blob-diff-path');
|
||||
params = {
|
||||
since: since,
|
||||
to: to,
|
||||
bottom: unfoldBottom,
|
||||
offset: offset,
|
||||
unfold: unfold,
|
||||
indent: 1
|
||||
indent: 1,
|
||||
view: file.data('view')
|
||||
};
|
||||
return $.get(link, params, function(response) {
|
||||
return target.parent().replaceWith(response);
|
||||
|
@ -48,26 +50,13 @@
|
|||
}
|
||||
|
||||
Diff.prototype.lineNumbers = function(line) {
|
||||
var i, l, len, line_number, line_numbers, lines, results;
|
||||
if (!line.children().length) {
|
||||
return [0, 0];
|
||||
}
|
||||
lines = line.children().slice(0, 2);
|
||||
line_numbers = (function() {
|
||||
var i, len, results;
|
||||
results = [];
|
||||
for (i = 0, len = lines.length; i < len; i++) {
|
||||
l = lines[i];
|
||||
results.push($(l).attr('data-linenumber'));
|
||||
}
|
||||
return results;
|
||||
})();
|
||||
results = [];
|
||||
for (i = 0, len = line_numbers.length; i < len; i++) {
|
||||
line_number = line_numbers[i];
|
||||
results.push(parseInt(line_number));
|
||||
}
|
||||
return results;
|
||||
|
||||
return line.find('.diff-line-num').map(function() {
|
||||
return parseInt($(this).data('linenumber'));
|
||||
});
|
||||
};
|
||||
|
||||
return Diff;
|
||||
|
|
|
@ -171,6 +171,11 @@
|
|||
break;
|
||||
case 'search:show':
|
||||
new Search();
|
||||
break;
|
||||
case 'projects:protected_branches:index':
|
||||
new gl.ProtectedBranchCreate();
|
||||
new gl.ProtectedBranchEditList();
|
||||
break;
|
||||
}
|
||||
switch (path.first()) {
|
||||
case 'admin':
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
setup: function(wrap) {
|
||||
this.input = $('.js-gfm-input');
|
||||
setup: function(input) {
|
||||
this.input = input || $('.js-gfm-input');
|
||||
this.destroyAtWho();
|
||||
this.setupAtWho();
|
||||
if (this.dataSource) {
|
||||
|
|
|
@ -28,38 +28,43 @@
|
|||
};
|
||||
})(this));
|
||||
timeout = "";
|
||||
this.input.on("keyup", (function(_this) {
|
||||
return function(e) {
|
||||
this.input
|
||||
.on('keydown', function (e) {
|
||||
var keyCode = e.which;
|
||||
|
||||
if (keyCode === 13) {
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
.on('keyup', function(e) {
|
||||
var keyCode;
|
||||
keyCode = e.which;
|
||||
if (ARROW_KEY_CODES.indexOf(keyCode) >= 0) {
|
||||
return;
|
||||
}
|
||||
if (_this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
|
||||
if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
|
||||
$inputContainer.addClass(HAS_VALUE_CLASS);
|
||||
} else if (_this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
|
||||
} else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
|
||||
$inputContainer.removeClass(HAS_VALUE_CLASS);
|
||||
}
|
||||
if (keyCode === 13) {
|
||||
return false;
|
||||
}
|
||||
if (_this.options.remote) {
|
||||
if (this.options.remote) {
|
||||
clearTimeout(timeout);
|
||||
return timeout = setTimeout(function() {
|
||||
var blur_field;
|
||||
blur_field = _this.shouldBlur(keyCode);
|
||||
if (blur_field && _this.filterInputBlur) {
|
||||
_this.input.blur();
|
||||
var blurField = this.shouldBlur(keyCode);
|
||||
if (blurField && this.filterInputBlur) {
|
||||
this.input.blur();
|
||||
}
|
||||
return _this.options.query(_this.input.val(), function(data) {
|
||||
return _this.options.callback(data);
|
||||
});
|
||||
}, 250);
|
||||
return this.options.query(this.input.val(), function(data) {
|
||||
return this.options.callback(data);
|
||||
}.bind(this));
|
||||
}.bind(this), 250);
|
||||
} else {
|
||||
return _this.filter(_this.input.val());
|
||||
return this.filter(this.input.val());
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
GitLabDropdownFilter.prototype.shouldBlur = function(keyCode) {
|
||||
|
@ -382,6 +387,7 @@
|
|||
|
||||
GitLabDropdown.prototype.opened = function() {
|
||||
var contentHtml;
|
||||
currentIndex = -1;
|
||||
this.addArrowKeyEvent();
|
||||
if (this.options.setIndeterminateIds) {
|
||||
this.options.setIndeterminateIds.call(this);
|
||||
|
@ -601,7 +607,7 @@
|
|||
return this.dropdown.before($input);
|
||||
};
|
||||
|
||||
GitLabDropdown.prototype.selectRowAtIndex = function(e, index) {
|
||||
GitLabDropdown.prototype.selectRowAtIndex = function(index) {
|
||||
var $el, selector;
|
||||
selector = ".dropdown-content li:not(.divider,.dropdown-header,.separator):eq(" + index + ") a";
|
||||
if (this.dropdown.find(".dropdown-toggle-page").length) {
|
||||
|
@ -609,8 +615,6 @@
|
|||
}
|
||||
$el = $(selector, this.dropdown);
|
||||
if ($el.length) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
return $el.first().trigger('click');
|
||||
}
|
||||
};
|
||||
|
@ -619,7 +623,7 @@
|
|||
var $input, ARROW_KEY_CODES, selector;
|
||||
ARROW_KEY_CODES = [38, 40];
|
||||
$input = this.dropdown.find(".dropdown-input-field");
|
||||
selector = '.dropdown-content li:not(.divider,.dropdown-header,.separator)';
|
||||
selector = '.dropdown-content li:not(.divider,.dropdown-header,.separator):visible';
|
||||
if (this.dropdown.find(".dropdown-toggle-page").length) {
|
||||
selector = ".dropdown-page-one " + selector;
|
||||
}
|
||||
|
@ -647,7 +651,7 @@
|
|||
return false;
|
||||
}
|
||||
if (currentKeyCode === 13 && currentIndex !== -1) {
|
||||
return _this.selectRowAtIndex(e, currentIndex);
|
||||
return _this.selectRowAtIndex($('.is-focused', _this.dropdown).closest('li').index() - 1);
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
this.form.find('.div-dropzone').remove();
|
||||
this.form.addClass('gfm-form');
|
||||
disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button'));
|
||||
GitLab.GfmAutoComplete.setup();
|
||||
GitLab.GfmAutoComplete.setup(this.form.find('.js-gfm-input'));
|
||||
new DropzoneInput(this.form);
|
||||
autosize(this.textarea);
|
||||
this.addEventListeners();
|
||||
|
|
|
@ -66,4 +66,12 @@
|
|||
|
||||
})();
|
||||
|
||||
$(function() {
|
||||
if ($('.js-importer-status').length) {
|
||||
var jobsImportPath = $('.js-importer-status').data('jobs-import-path');
|
||||
var importPath = $('.js-importer-status').data('import-path');
|
||||
|
||||
new ImporterStatus(jobsImportPath, importPath);
|
||||
}
|
||||
});
|
||||
}).call(this);
|
||||
|
|
|
@ -8,13 +8,16 @@
|
|||
base.utils = {};
|
||||
}
|
||||
w.gl.utils.days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
||||
|
||||
w.gl.utils.formatDate = function(datetime) {
|
||||
return dateFormat(datetime, 'mmm d, yyyy h:MMtt Z');
|
||||
};
|
||||
|
||||
w.gl.utils.getDayName = function(date) {
|
||||
return this.days[date.getDay()];
|
||||
};
|
||||
return w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago) {
|
||||
|
||||
w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago) {
|
||||
if (setTimeago == null) {
|
||||
setTimeago = true;
|
||||
}
|
||||
|
@ -31,6 +34,39 @@
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
w.gl.utils.shortTimeAgo = function($el) {
|
||||
var shortLocale, tmpLocale;
|
||||
shortLocale = {
|
||||
prefixAgo: null,
|
||||
prefixFromNow: null,
|
||||
suffixAgo: 'ago',
|
||||
suffixFromNow: 'from now',
|
||||
seconds: '1 min',
|
||||
minute: '1 min',
|
||||
minutes: '%d mins',
|
||||
hour: '1 hr',
|
||||
hours: '%d hrs',
|
||||
day: '1 day',
|
||||
days: '%d days',
|
||||
month: '1 month',
|
||||
months: '%d months',
|
||||
year: '1 year',
|
||||
years: '%d years',
|
||||
wordSeparator: ' ',
|
||||
numbers: []
|
||||
};
|
||||
tmpLocale = $.timeago.settings.strings;
|
||||
$el.each(function(el) {
|
||||
var $el1;
|
||||
$el1 = $(this);
|
||||
return $el1.attr('title', gl.utils.formatDate($el.attr('datetime')));
|
||||
});
|
||||
$.timeago.settings.strings = shortLocale;
|
||||
$el.timeago();
|
||||
$.timeago.settings.strings = tmpLocale;
|
||||
};
|
||||
|
||||
})(window);
|
||||
|
||||
}).call(this);
|
||||
|
|
|
@ -1,211 +0,0 @@
|
|||
function md5 (str) {
|
||||
// http://kevin.vanzonneveld.net
|
||||
// + original by: Webtoolkit.info (http://www.webtoolkit.info/)
|
||||
// + namespaced by: Michael White (http://getsprink.com)
|
||||
// + tweaked by: Jack
|
||||
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// + input by: Brett Zamir (http://brett-zamir.me)
|
||||
// + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// - depends on: utf8_encode
|
||||
// * example 1: md5('Kevin van Zonneveld');
|
||||
// * returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
|
||||
var xl;
|
||||
|
||||
var rotateLeft = function (lValue, iShiftBits) {
|
||||
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
|
||||
};
|
||||
|
||||
var addUnsigned = function (lX, lY) {
|
||||
var lX4, lY4, lX8, lY8, lResult;
|
||||
lX8 = (lX & 0x80000000);
|
||||
lY8 = (lY & 0x80000000);
|
||||
lX4 = (lX & 0x40000000);
|
||||
lY4 = (lY & 0x40000000);
|
||||
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
|
||||
if (lX4 & lY4) {
|
||||
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
|
||||
}
|
||||
if (lX4 | lY4) {
|
||||
if (lResult & 0x40000000) {
|
||||
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
|
||||
} else {
|
||||
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
|
||||
}
|
||||
} else {
|
||||
return (lResult ^ lX8 ^ lY8);
|
||||
}
|
||||
};
|
||||
|
||||
var _F = function (x, y, z) {
|
||||
return (x & y) | ((~x) & z);
|
||||
};
|
||||
var _G = function (x, y, z) {
|
||||
return (x & z) | (y & (~z));
|
||||
};
|
||||
var _H = function (x, y, z) {
|
||||
return (x ^ y ^ z);
|
||||
};
|
||||
var _I = function (x, y, z) {
|
||||
return (y ^ (x | (~z)));
|
||||
};
|
||||
|
||||
var _FF = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
|
||||
var _GG = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
|
||||
var _HH = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
|
||||
var _II = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
|
||||
var convertToWordArray = function (str) {
|
||||
var lWordCount;
|
||||
var lMessageLength = str.length;
|
||||
var lNumberOfWords_temp1 = lMessageLength + 8;
|
||||
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
|
||||
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
|
||||
var lWordArray = new Array(lNumberOfWords - 1);
|
||||
var lBytePosition = 0;
|
||||
var lByteCount = 0;
|
||||
while (lByteCount < lMessageLength) {
|
||||
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
|
||||
lBytePosition = (lByteCount % 4) * 8;
|
||||
lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition));
|
||||
lByteCount++;
|
||||
}
|
||||
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
|
||||
lBytePosition = (lByteCount % 4) * 8;
|
||||
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
|
||||
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
|
||||
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
|
||||
return lWordArray;
|
||||
};
|
||||
|
||||
var wordToHex = function (lValue) {
|
||||
var wordToHexValue = "",
|
||||
wordToHexValue_temp = "",
|
||||
lByte, lCount;
|
||||
for (lCount = 0; lCount <= 3; lCount++) {
|
||||
lByte = (lValue >>> (lCount * 8)) & 255;
|
||||
wordToHexValue_temp = "0" + lByte.toString(16);
|
||||
wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
|
||||
}
|
||||
return wordToHexValue;
|
||||
};
|
||||
|
||||
var x = [],
|
||||
k, AA, BB, CC, DD, a, b, c, d, S11 = 7,
|
||||
S12 = 12,
|
||||
S13 = 17,
|
||||
S14 = 22,
|
||||
S21 = 5,
|
||||
S22 = 9,
|
||||
S23 = 14,
|
||||
S24 = 20,
|
||||
S31 = 4,
|
||||
S32 = 11,
|
||||
S33 = 16,
|
||||
S34 = 23,
|
||||
S41 = 6,
|
||||
S42 = 10,
|
||||
S43 = 15,
|
||||
S44 = 21;
|
||||
|
||||
str = this.utf8_encode(str);
|
||||
x = convertToWordArray(str);
|
||||
a = 0x67452301;
|
||||
b = 0xEFCDAB89;
|
||||
c = 0x98BADCFE;
|
||||
d = 0x10325476;
|
||||
|
||||
xl = x.length;
|
||||
for (k = 0; k < xl; k += 16) {
|
||||
AA = a;
|
||||
BB = b;
|
||||
CC = c;
|
||||
DD = d;
|
||||
a = _FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
|
||||
d = _FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
|
||||
c = _FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
|
||||
b = _FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
|
||||
a = _FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
|
||||
d = _FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
|
||||
c = _FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
|
||||
b = _FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
|
||||
a = _FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
|
||||
d = _FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
|
||||
c = _FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
|
||||
b = _FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
|
||||
a = _FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
|
||||
d = _FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
|
||||
c = _FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
|
||||
b = _FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
|
||||
a = _GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
|
||||
d = _GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
|
||||
c = _GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
|
||||
b = _GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
|
||||
a = _GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
|
||||
d = _GG(d, a, b, c, x[k + 10], S22, 0x2441453);
|
||||
c = _GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
|
||||
b = _GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
|
||||
a = _GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
|
||||
d = _GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
|
||||
c = _GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
|
||||
b = _GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
|
||||
a = _GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
|
||||
d = _GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
|
||||
c = _GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
|
||||
b = _GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
|
||||
a = _HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
|
||||
d = _HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
|
||||
c = _HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
|
||||
b = _HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
|
||||
a = _HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
|
||||
d = _HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
|
||||
c = _HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
|
||||
b = _HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
|
||||
a = _HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
|
||||
d = _HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
|
||||
c = _HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
|
||||
b = _HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
|
||||
a = _HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
|
||||
d = _HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
|
||||
c = _HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
|
||||
b = _HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
|
||||
a = _II(a, b, c, d, x[k + 0], S41, 0xF4292244);
|
||||
d = _II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
|
||||
c = _II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
|
||||
b = _II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
|
||||
a = _II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
|
||||
d = _II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
|
||||
c = _II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
|
||||
b = _II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
|
||||
a = _II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
|
||||
d = _II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
|
||||
c = _II(c, d, a, b, x[k + 6], S43, 0xA3014314);
|
||||
b = _II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
|
||||
a = _II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
|
||||
d = _II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
|
||||
c = _II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
|
||||
b = _II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
|
||||
a = addUnsigned(a, AA);
|
||||
b = addUnsigned(b, BB);
|
||||
c = addUnsigned(c, CC);
|
||||
d = addUnsigned(d, DD);
|
||||
}
|
||||
|
||||
var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
|
||||
|
||||
return temp.toLowerCase();
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
function utf8_encode (argString) {
|
||||
// http://kevin.vanzonneveld.net
|
||||
// + original by: Webtoolkit.info (http://www.webtoolkit.info/)
|
||||
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// + improved by: sowberry
|
||||
// + tweaked by: Jack
|
||||
// + bugfixed by: Onno Marsman
|
||||
// + improved by: Yves Sucaet
|
||||
// + bugfixed by: Onno Marsman
|
||||
// + bugfixed by: Ulrich
|
||||
// + bugfixed by: Rafal Kukawski
|
||||
// + improved by: kirilloid
|
||||
// + bugfixed by: kirilloid
|
||||
// * example 1: utf8_encode('Kevin van Zonneveld');
|
||||
// * returns 1: 'Kevin van Zonneveld'
|
||||
|
||||
if (argString === null || typeof argString === "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
var string = (argString + ''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
||||
var utftext = '',
|
||||
start, end, stringl = 0;
|
||||
|
||||
start = end = 0;
|
||||
stringl = string.length;
|
||||
for (var n = 0; n < stringl; n++) {
|
||||
var c1 = string.charCodeAt(n);
|
||||
var enc = null;
|
||||
|
||||
if (c1 < 128) {
|
||||
end++;
|
||||
} else if (c1 > 127 && c1 < 2048) {
|
||||
enc = String.fromCharCode(
|
||||
(c1 >> 6) | 192,
|
||||
( c1 & 63) | 128
|
||||
);
|
||||
} else if (c1 & 0xF800 != 0xD800) {
|
||||
enc = String.fromCharCode(
|
||||
(c1 >> 12) | 224,
|
||||
((c1 >> 6) & 63) | 128,
|
||||
( c1 & 63) | 128
|
||||
);
|
||||
} else { // surrogate pairs
|
||||
if (c1 & 0xFC00 != 0xD800) { throw new RangeError("Unmatched trail surrogate at " + n); }
|
||||
var c2 = string.charCodeAt(++n);
|
||||
if (c2 & 0xFC00 != 0xDC00) { throw new RangeError("Unmatched lead surrogate at " + (n-1)); }
|
||||
c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000;
|
||||
enc = String.fromCharCode(
|
||||
(c1 >> 18) | 240,
|
||||
((c1 >> 12) & 63) | 128,
|
||||
((c1 >> 6) & 63) | 128,
|
||||
( c1 & 63) | 128
|
||||
);
|
||||
}
|
||||
if (enc !== null) {
|
||||
if (end > start) {
|
||||
utftext += string.slice(start, end);
|
||||
}
|
||||
utftext += enc;
|
||||
start = end = n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (end > start) {
|
||||
utftext += string.slice(start, stringl);
|
||||
}
|
||||
|
||||
return utftext;
|
||||
}
|
|
@ -89,8 +89,14 @@
|
|||
toggleLabel: function(obj, $el) {
|
||||
return $el.text().trim();
|
||||
},
|
||||
clicked: function(e) {
|
||||
return $dropdown.closest('form').submit();
|
||||
clicked: function(selected, $el, e) {
|
||||
e.preventDefault()
|
||||
if ($('input[name="ref"]').length) {
|
||||
var $form = $dropdown.closest('form'),
|
||||
action = $form.attr('action'),
|
||||
divider = action.indexOf('?') < 0 ? '?' : '&';
|
||||
Turbolinks.visit(action + '' + divider + '' + $form.serialize());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
(global => {
|
||||
global.gl = global.gl || {};
|
||||
|
||||
gl.ProtectedBranchAccessDropdown = class {
|
||||
constructor(options) {
|
||||
const { $dropdown, data, onSelect } = options;
|
||||
|
||||
$dropdown.glDropdown({
|
||||
data: data,
|
||||
selectable: true,
|
||||
inputId: $dropdown.data('input-id'),
|
||||
fieldName: $dropdown.data('field-name'),
|
||||
toggleLabel(item) {
|
||||
return item.text;
|
||||
},
|
||||
clicked(item, $el, e) {
|
||||
e.preventDefault();
|
||||
onSelect();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})(window);
|
56
app/assets/javascripts/protected_branch_create.js.es6
Normal file
|
@ -0,0 +1,56 @@
|
|||
(global => {
|
||||
global.gl = global.gl || {};
|
||||
|
||||
gl.ProtectedBranchCreate = class {
|
||||
constructor() {
|
||||
this.$wrap = this.$form = $('#new_protected_branch');
|
||||
this.buildDropdowns();
|
||||
}
|
||||
|
||||
buildDropdowns() {
|
||||
const $allowedToMergeDropdown = this.$wrap.find('.js-allowed-to-merge');
|
||||
const $allowedToPushDropdown = this.$wrap.find('.js-allowed-to-push');
|
||||
|
||||
// Cache callback
|
||||
this.onSelectCallback = this.onSelect.bind(this);
|
||||
|
||||
// Allowed to Merge dropdown
|
||||
new gl.ProtectedBranchAccessDropdown({
|
||||
$dropdown: $allowedToMergeDropdown,
|
||||
data: gon.merge_access_levels,
|
||||
onSelect: this.onSelectCallback
|
||||
});
|
||||
|
||||
// Allowed to Push dropdown
|
||||
new gl.ProtectedBranchAccessDropdown({
|
||||
$dropdown: $allowedToPushDropdown,
|
||||
data: gon.push_access_levels,
|
||||
onSelect: this.onSelectCallback
|
||||
});
|
||||
|
||||
// Select default
|
||||
$allowedToPushDropdown.data('glDropdown').selectRowAtIndex(0);
|
||||
$allowedToMergeDropdown.data('glDropdown').selectRowAtIndex(0);
|
||||
|
||||
// Protected branch dropdown
|
||||
new ProtectedBranchDropdown({
|
||||
$dropdown: this.$wrap.find('.js-protected-branch-select'),
|
||||
onSelect: this.onSelectCallback
|
||||
});
|
||||
}
|
||||
|
||||
// This will run after clicked callback
|
||||
onSelect() {
|
||||
|
||||
// Enable submit button
|
||||
const $branchInput = this.$wrap.find('input[name="protected_branch[name]"]');
|
||||
const $allowedToMergeInput = this.$wrap.find('input[name="protected_branch[merge_access_level_attributes][access_level]"]');
|
||||
const $allowedToPushInput = this.$wrap.find('input[name="protected_branch[push_access_level_attributes][access_level]"]');
|
||||
|
||||
if ($branchInput.val() && $allowedToMergeInput.val() && $allowedToPushInput.val()){
|
||||
this.$form.find('input[type="submit"]').removeAttr('disabled');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})(window);
|
75
app/assets/javascripts/protected_branch_dropdown.js.es6
Normal file
|
@ -0,0 +1,75 @@
|
|||
class ProtectedBranchDropdown {
|
||||
constructor(options) {
|
||||
this.onSelect = options.onSelect;
|
||||
this.$dropdown = options.$dropdown;
|
||||
this.$dropdownContainer = this.$dropdown.parent();
|
||||
this.$dropdownFooter = this.$dropdownContainer.find('.dropdown-footer');
|
||||
this.$protectedBranch = this.$dropdownContainer.find('.create-new-protected-branch');
|
||||
|
||||
this.buildDropdown();
|
||||
this.bindEvents();
|
||||
|
||||
// Hide footer
|
||||
this.$dropdownFooter.addClass('hidden');
|
||||
}
|
||||
|
||||
buildDropdown() {
|
||||
this.$dropdown.glDropdown({
|
||||
data: this.getProtectedBranches.bind(this),
|
||||
filterable: true,
|
||||
remote: false,
|
||||
search: {
|
||||
fields: ['title']
|
||||
},
|
||||
selectable: true,
|
||||
toggleLabel(selected) {
|
||||
return (selected && 'id' in selected) ? selected.title : 'Protected Branch';
|
||||
},
|
||||
fieldName: 'protected_branch[name]',
|
||||
text(protectedBranch) {
|
||||
return _.escape(protectedBranch.title);
|
||||
},
|
||||
id(protectedBranch) {
|
||||
return _.escape(protectedBranch.id);
|
||||
},
|
||||
onFilter: this.toggleCreateNewButton.bind(this),
|
||||
clicked: (item, $el, e) => {
|
||||
e.preventDefault();
|
||||
this.onSelect();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
this.$protectedBranch.on('click', this.onClickCreateWildcard.bind(this));
|
||||
}
|
||||
|
||||
onClickCreateWildcard() {
|
||||
this.$dropdown.data('glDropdown').remote.execute();
|
||||
this.$dropdown.data('glDropdown').selectRowAtIndex(0);
|
||||
}
|
||||
|
||||
getProtectedBranches(term, callback) {
|
||||
if (this.selectedBranch) {
|
||||
callback(gon.open_branches.concat(this.selectedBranch));
|
||||
} else {
|
||||
callback(gon.open_branches);
|
||||
}
|
||||
}
|
||||
|
||||
toggleCreateNewButton(branchName) {
|
||||
this.selectedBranch = {
|
||||
title: branchName,
|
||||
id: branchName,
|
||||
text: branchName
|
||||
};
|
||||
|
||||
if (branchName) {
|
||||
this.$dropdownContainer
|
||||
.find('.create-new-protected-branch code')
|
||||
.text(branchName);
|
||||
}
|
||||
|
||||
this.$dropdownFooter.toggleClass('hidden', !branchName);
|
||||
}
|
||||
}
|
61
app/assets/javascripts/protected_branch_edit.js.es6
Normal file
|
@ -0,0 +1,61 @@
|
|||
(global => {
|
||||
global.gl = global.gl || {};
|
||||
|
||||
gl.ProtectedBranchEdit = class {
|
||||
constructor(options) {
|
||||
this.$wrap = options.$wrap;
|
||||
this.$allowedToMergeDropdown = this.$wrap.find('.js-allowed-to-merge');
|
||||
this.$allowedToPushDropdown = this.$wrap.find('.js-allowed-to-push');
|
||||
|
||||
this.buildDropdowns();
|
||||
}
|
||||
|
||||
buildDropdowns() {
|
||||
|
||||
// Allowed to merge dropdown
|
||||
new gl.ProtectedBranchAccessDropdown({
|
||||
$dropdown: this.$allowedToMergeDropdown,
|
||||
data: gon.merge_access_levels,
|
||||
onSelect: this.onSelect.bind(this)
|
||||
});
|
||||
|
||||
// Allowed to push dropdown
|
||||
new gl.ProtectedBranchAccessDropdown({
|
||||
$dropdown: this.$allowedToPushDropdown,
|
||||
data: gon.push_access_levels,
|
||||
onSelect: this.onSelect.bind(this)
|
||||
});
|
||||
}
|
||||
|
||||
onSelect() {
|
||||
const $allowedToMergeInput = this.$wrap.find(`input[name="${this.$allowedToMergeDropdown.data('fieldName')}"]`);
|
||||
const $allowedToPushInput = this.$wrap.find(`input[name="${this.$allowedToPushDropdown.data('fieldName')}"]`);
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: this.$wrap.data('url'),
|
||||
dataType: 'json',
|
||||
data: {
|
||||
_method: 'PATCH',
|
||||
id: this.$wrap.data('banchId'),
|
||||
protected_branch: {
|
||||
merge_access_level_attributes: {
|
||||
access_level: $allowedToMergeInput.val()
|
||||
},
|
||||
push_access_level_attributes: {
|
||||
access_level: $allowedToPushInput.val()
|
||||
}
|
||||
}
|
||||
},
|
||||
success: () => {
|
||||
this.$wrap.effect('highlight');
|
||||
},
|
||||
error() {
|
||||
$.scrollTo(0);
|
||||
new Flash('Failed to update branch!');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})(window);
|
17
app/assets/javascripts/protected_branch_edit_list.js.es6
Normal file
|
@ -0,0 +1,17 @@
|
|||
(global => {
|
||||
global.gl = global.gl || {};
|
||||
|
||||
gl.ProtectedBranchEditList = class {
|
||||
constructor() {
|
||||
this.$wrap = $('.protected-branches-list');
|
||||
|
||||
// Build edit forms
|
||||
this.$wrap.find('.js-protected-branch-edit-form').each((i, el) => {
|
||||
new gl.ProtectedBranchEdit({
|
||||
$wrap: $(el)
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})(window);
|
|
@ -1,72 +0,0 @@
|
|||
(function() {
|
||||
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||
|
||||
this.ProtectedBranchSelect = (function() {
|
||||
function ProtectedBranchSelect(currentProject) {
|
||||
this.toggleCreateNewButton = bind(this.toggleCreateNewButton, this);
|
||||
this.getProtectedBranches = bind(this.getProtectedBranches, this);
|
||||
$('.dropdown-footer').hide();
|
||||
this.dropdown = $('.js-protected-branch-select').glDropdown({
|
||||
data: this.getProtectedBranches,
|
||||
filterable: true,
|
||||
remote: false,
|
||||
search: {
|
||||
fields: ['title']
|
||||
},
|
||||
selectable: true,
|
||||
toggleLabel: function(selected) {
|
||||
if (selected && 'id' in selected) {
|
||||
return selected.title;
|
||||
} else {
|
||||
return 'Protected Branch';
|
||||
}
|
||||
},
|
||||
fieldName: 'protected_branch[name]',
|
||||
text: function(protected_branch) {
|
||||
return _.escape(protected_branch.title);
|
||||
},
|
||||
id: function(protected_branch) {
|
||||
return _.escape(protected_branch.id);
|
||||
},
|
||||
onFilter: this.toggleCreateNewButton,
|
||||
clicked: function() {
|
||||
return $('.protect-branch-btn').attr('disabled', false);
|
||||
}
|
||||
});
|
||||
$('.create-new-protected-branch').on('click', (function(_this) {
|
||||
return function(event) {
|
||||
_this.dropdown.data('glDropdown').remote.execute();
|
||||
return _this.dropdown.data('glDropdown').selectRowAtIndex(event, 0);
|
||||
};
|
||||
})(this));
|
||||
}
|
||||
|
||||
ProtectedBranchSelect.prototype.getProtectedBranches = function(term, callback) {
|
||||
if (this.selectedBranch) {
|
||||
return callback(gon.open_branches.concat(this.selectedBranch));
|
||||
} else {
|
||||
return callback(gon.open_branches);
|
||||
}
|
||||
};
|
||||
|
||||
ProtectedBranchSelect.prototype.toggleCreateNewButton = function(branchName) {
|
||||
this.selectedBranch = {
|
||||
title: branchName,
|
||||
id: branchName,
|
||||
text: branchName
|
||||
};
|
||||
if (branchName === '') {
|
||||
$('.protected-branch-select-footer-list').addClass('hidden');
|
||||
return $('.dropdown-footer').hide();
|
||||
} else {
|
||||
$('.create-new-protected-branch').text("Create Protected Branch: " + branchName);
|
||||
$('.protected-branch-select-footer-list').removeClass('hidden');
|
||||
return $('.dropdown-footer').show();
|
||||
}
|
||||
};
|
||||
|
||||
return ProtectedBranchSelect;
|
||||
|
||||
})();
|
||||
|
||||
}).call(this);
|
|
@ -1,35 +0,0 @@
|
|||
(function() {
|
||||
$(function() {
|
||||
return $(".protected-branches-list :checkbox").change(function(e) {
|
||||
var can_push, id, name, obj, url;
|
||||
name = $(this).attr("name");
|
||||
if (name === "developers_can_push" || name === "developers_can_merge") {
|
||||
id = $(this).val();
|
||||
can_push = $(this).is(":checked");
|
||||
url = $(this).data("url");
|
||||
return $.ajax({
|
||||
type: "PATCH",
|
||||
url: url,
|
||||
dataType: "json",
|
||||
data: {
|
||||
id: id,
|
||||
protected_branch: (
|
||||
obj = {},
|
||||
obj["" + name] = can_push,
|
||||
obj
|
||||
)
|
||||
},
|
||||
success: function() {
|
||||
var row;
|
||||
row = $(e.target);
|
||||
return row.closest('tr').effect('highlight');
|
||||
},
|
||||
error: function() {
|
||||
return new Flash("Failed to update branch!", "alert");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}).call(this);
|
|
@ -13,14 +13,15 @@
|
|||
}
|
||||
$('.js-user-search').each((function(_this) {
|
||||
return function(i, dropdown) {
|
||||
var options = {};
|
||||
var $block, $collapsedSidebar, $dropdown, $loading, $selectbox, $value, abilityName, assignTo, assigneeTemplate, collapsedAssigneeTemplate, defaultLabel, firstUser, issueURL, selectedId, showAnyUser, showNullUser;
|
||||
$dropdown = $(dropdown);
|
||||
_this.projectId = $dropdown.data('project-id');
|
||||
_this.showCurrentUser = $dropdown.data('current-user');
|
||||
options.projectId = $dropdown.data('project-id');
|
||||
options.showCurrentUser = $dropdown.data('current-user');
|
||||
showNullUser = $dropdown.data('null-user');
|
||||
showAnyUser = $dropdown.data('any-user');
|
||||
firstUser = $dropdown.data('first-user');
|
||||
_this.authorId = $dropdown.data('author-id');
|
||||
options.authorId = $dropdown.data('author-id');
|
||||
selectedId = $dropdown.data('selected');
|
||||
defaultLabel = $dropdown.data('default-label');
|
||||
issueURL = $dropdown.data('issueUpdate');
|
||||
|
@ -75,7 +76,7 @@
|
|||
data: function(term, callback) {
|
||||
var isAuthorFilter;
|
||||
isAuthorFilter = $('.js-author-search');
|
||||
return _this.users(term, function(users) {
|
||||
return _this.users(term, options, function(users) {
|
||||
var anyUser, index, j, len, name, obj, showDivider;
|
||||
if (term.length === 0) {
|
||||
showDivider = 0;
|
||||
|
@ -185,10 +186,14 @@
|
|||
$('.ajax-users-select').each((function(_this) {
|
||||
return function(i, select) {
|
||||
var firstUser, showAnyUser, showEmailUser, showNullUser;
|
||||
_this.projectId = $(select).data('project-id');
|
||||
_this.groupId = $(select).data('group-id');
|
||||
_this.showCurrentUser = $(select).data('current-user');
|
||||
_this.authorId = $(select).data('author-id');
|
||||
var options = {};
|
||||
options.skipLdap = $(select).hasClass('skip_ldap');
|
||||
options.projectId = $(select).data('project-id');
|
||||
options.groupId = $(select).data('group-id');
|
||||
options.showCurrentUser = $(select).data('current-user');
|
||||
options.pushCodeToProtectedBranches = $(select).data('push-code-to-protected-branches');
|
||||
options.authorId = $(select).data('author-id');
|
||||
options.skipUsers = $(select).data('skip-users');
|
||||
showNullUser = $(select).data('null-user');
|
||||
showAnyUser = $(select).data('any-user');
|
||||
showEmailUser = $(select).data('email-user');
|
||||
|
@ -198,7 +203,7 @@
|
|||
multiple: $(select).hasClass('multiselect'),
|
||||
minimumInputLength: 0,
|
||||
query: function(query) {
|
||||
return _this.users(query.term, function(users) {
|
||||
return _this.users(query.term, options, function(users) {
|
||||
var anyUser, data, emailUser, index, j, len, name, nullUser, obj, ref;
|
||||
data = {
|
||||
results: users
|
||||
|
@ -308,7 +313,7 @@
|
|||
});
|
||||
};
|
||||
|
||||
UsersSelect.prototype.users = function(query, callback) {
|
||||
UsersSelect.prototype.users = function(query, options, callback) {
|
||||
var url;
|
||||
url = this.buildUrl(this.usersPath);
|
||||
return $.ajax({
|
||||
|
@ -317,10 +322,13 @@
|
|||
search: query,
|
||||
per_page: 20,
|
||||
active: true,
|
||||
project_id: this.projectId,
|
||||
group_id: this.groupId,
|
||||
current_user: this.showCurrentUser,
|
||||
author_id: this.authorId
|
||||
project_id: options.projectId || null,
|
||||
group_id: options.groupId || null,
|
||||
skip_ldap: options.skipLdap || null,
|
||||
current_user: options.showCurrentUser || null,
|
||||
push_code_to_protected_branches: options.pushCodeToProtectedBranches || null,
|
||||
author_id: options.authorId || null,
|
||||
skip_users: options.skipUsers || null
|
||||
},
|
||||
dataType: "json"
|
||||
}).done(function(users) {
|
||||
|
|
|
@ -135,6 +135,15 @@
|
|||
@include btn-green;
|
||||
}
|
||||
|
||||
&.btn-inverted {
|
||||
&.btn-success,
|
||||
&.btn-new,
|
||||
&.btn-create,
|
||||
&.btn-save {
|
||||
@include btn-outline($white-light, $green-normal, $green-normal, $green-light, $white-light, $green-light);
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-gray {
|
||||
@include btn-gray;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,14 @@
|
|||
&.large {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
&.wide {
|
||||
width: 100%;
|
||||
|
||||
+ .dropdown-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu,
|
||||
|
@ -350,6 +358,7 @@
|
|||
|
||||
.dropdown-input-field, .default-dropdown-input {
|
||||
width: 100%;
|
||||
min-height: 30px;
|
||||
padding: 0 7px;
|
||||
color: $dropdown-input-color;
|
||||
line-height: 30px;
|
||||
|
|
|
@ -114,6 +114,12 @@ ul.content-list {
|
|||
font-size: $list-font-size;
|
||||
color: $list-text-color;
|
||||
|
||||
&.no-description {
|
||||
.title {
|
||||
line-height: $list-text-height;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
@ -134,12 +140,11 @@ ul.content-list {
|
|||
}
|
||||
|
||||
.controls {
|
||||
padding-top: 1px;
|
||||
float: right;
|
||||
|
||||
> .control-text {
|
||||
margin-right: $gl-padding-top;
|
||||
line-height: 40px;
|
||||
line-height: $list-text-height;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
|
@ -150,7 +155,7 @@ ul.content-list {
|
|||
> .btn-group {
|
||||
margin-right: $gl-padding-top;
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 4px;
|
||||
|
||||
&:last-child {
|
||||
|
|
|
@ -182,7 +182,6 @@
|
|||
|
||||
> form {
|
||||
display: inline-block;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.icon-label {
|
||||
|
@ -193,7 +192,6 @@
|
|||
height: 35px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
margin-right: $gl-padding-top;
|
||||
|
||||
/* Medium devices (desktops, 992px and up) */
|
||||
|
|
|
@ -23,4 +23,9 @@
|
|||
margin-top: $gl-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-title {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ $gl-header-color: $gl-title-color;
|
|||
$list-font-size: $gl-font-size;
|
||||
$list-title-color: $gl-title-color;
|
||||
$list-text-color: $gl-text-color;
|
||||
$list-text-height: 42px;
|
||||
|
||||
/*
|
||||
* Markdown
|
||||
|
|
|
@ -10,83 +10,48 @@
|
|||
// preference): plain class selectors, type (element name) selectors, or
|
||||
// explicit child selectors.
|
||||
|
||||
table.code {
|
||||
width: 100%;
|
||||
.code {
|
||||
background-color: #fff;
|
||||
font-family: monospace;
|
||||
border: none;
|
||||
border-collapse: separate;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: $code_font_size;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
|
||||
> tr > td {
|
||||
> tr {
|
||||
line-height: $code_line_height;
|
||||
font-family: monospace;
|
||||
font-size: $code_font_size;
|
||||
|
||||
&.diff-line-num {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
padding: 0 5px;
|
||||
border-right: 1px solid;
|
||||
text-align: right;
|
||||
min-width: 35px;
|
||||
max-width: 50px;
|
||||
width: 35px;
|
||||
}
|
||||
|
||||
&.line_content {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0 0.5em;
|
||||
border: none;
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.line-numbers, .diff-line-num {
|
||||
background-color: $background-color;
|
||||
}
|
||||
|
||||
.diff-line-num, .diff-line-num a {
|
||||
color: $black-transparent;
|
||||
}
|
||||
|
||||
pre.code, .diff-line-num {
|
||||
border-color: $table-border-gray;
|
||||
}
|
||||
|
||||
.code.white, pre.code, .line_content {
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.diff-line-num {
|
||||
padding: 0 5px;
|
||||
text-align: right;
|
||||
width: 35px;
|
||||
background-color: $background-color;
|
||||
color: $black-transparent;
|
||||
border-right: 1px solid $table-border-gray;
|
||||
|
||||
&.old {
|
||||
background-color: $line-number-old;
|
||||
border-color: $line-removed-dark;
|
||||
border-right-color: $line-removed-dark;
|
||||
}
|
||||
|
||||
&.new {
|
||||
background-color: $line-number-new;
|
||||
border-color: $line-added-dark;
|
||||
}
|
||||
|
||||
&.hll:not(.empty-cell) {
|
||||
background-color: $line-number-select;
|
||||
border-color: $line-select-yellow-dark;
|
||||
border-right-color: $line-added-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.line_content {
|
||||
padding-left: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
white-space: pre;
|
||||
|
||||
&.old {
|
||||
background-color: $line-removed;
|
||||
|
||||
> .line > span.idiff, > .line > span > span.idiff {
|
||||
> .line > span.idiff,
|
||||
> .line > span > span.idiff {
|
||||
background-color: $line-removed-dark;
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +59,8 @@ pre.code, .diff-line-num {
|
|||
&.new {
|
||||
background-color: $line-added;
|
||||
|
||||
> .line > span.idiff, > .line > span > span.idiff {
|
||||
> .line > span.idiff,
|
||||
> .line > span > span.idiff {
|
||||
background-color: $line-added-dark;
|
||||
}
|
||||
}
|
||||
|
@ -103,14 +69,6 @@ pre.code, .diff-line-num {
|
|||
color: $black-transparent;
|
||||
background-color: $match-line;
|
||||
}
|
||||
|
||||
&.hll:not(.empty-cell) {
|
||||
background-color: $line-select-yellow;
|
||||
}
|
||||
}
|
||||
|
||||
pre > .hll {
|
||||
background-color: #f8eec7 !important;
|
||||
}
|
||||
|
||||
span.highlight_word {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
.commits-compare-switch {
|
||||
@include btn-default;
|
||||
@include btn-white;
|
||||
background: image-url("switch_icon.png") no-repeat center center;
|
||||
text-indent: -9999px;
|
||||
float: left;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
@ -61,6 +59,10 @@
|
|||
font-size: 0;
|
||||
}
|
||||
|
||||
.ci-status-link {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-clipboard, .btn-transparent {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
|
|
|
@ -164,7 +164,10 @@
|
|||
line-height: 0;
|
||||
img {
|
||||
border: 1px solid #fff;
|
||||
background: image-url('trans_bg.gif');
|
||||
background-image: linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%),
|
||||
linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%);
|
||||
background-size: 10px 10px;
|
||||
background-position: 0 0, 5px 5px;
|
||||
max-width: 100%;
|
||||
}
|
||||
&.deleted {
|
||||
|
|
|
@ -23,15 +23,9 @@
|
|||
}
|
||||
|
||||
.group-row {
|
||||
&.no-description {
|
||||
.group-name {
|
||||
line-height: 44px;
|
||||
}
|
||||
}
|
||||
|
||||
.stats {
|
||||
float: right;
|
||||
line-height: 44px;
|
||||
line-height: $list-text-height;
|
||||
color: $gl-gray;
|
||||
|
||||
span {
|
||||
|
|
|
@ -99,3 +99,33 @@ form.edit-issue {
|
|||
.issue-form .select2-container {
|
||||
width: 250px !important;
|
||||
}
|
||||
|
||||
.issues-footer {
|
||||
padding-top: $gl-padding;
|
||||
padding-bottom: 37px;
|
||||
}
|
||||
|
||||
.issue-email-modal-btn {
|
||||
padding: 0;
|
||||
color: $gl-link-color;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.email-modal-input-group {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.form-control {
|
||||
background-color: $white-light;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: $background-color;
|
||||
border: 1px solid $border-gray-light;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,6 +216,11 @@
|
|||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
.btn {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.table.builds {
|
||||
min-width: 1200px;
|
||||
}
|
||||
}
|
||||
|
||||
.content-list {
|
||||
|
@ -35,7 +39,7 @@
|
|||
}
|
||||
|
||||
.table.builds {
|
||||
min-width: 1200px;
|
||||
min-width: 900px;
|
||||
|
||||
&.pipeline {
|
||||
min-width: 650px;
|
||||
|
@ -128,7 +132,7 @@
|
|||
.icon-container {
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
width: 20px;
|
||||
width: 15px;
|
||||
|
||||
.fa {
|
||||
position: relative;
|
||||
|
|
|
@ -512,18 +512,12 @@ pre.light-well {
|
|||
.project-row {
|
||||
border-color: $table-border-color;
|
||||
|
||||
&.no-description {
|
||||
.project {
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.project-full-name {
|
||||
@include str-truncated;
|
||||
}
|
||||
|
||||
.controls {
|
||||
line-height: 40px;
|
||||
line-height: $list-text-height;
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
|
@ -661,14 +655,39 @@ pre.light-well {
|
|||
}
|
||||
}
|
||||
|
||||
.new_protected_branch {
|
||||
label {
|
||||
margin-top: 6px;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.protected-branches-list {
|
||||
a {
|
||||
color: $gl-gray;
|
||||
font-weight: 600;
|
||||
|
||||
&:hover {
|
||||
color: $gl-link-color;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.settings-message {
|
||||
margin: 0;
|
||||
border-radius: 0 0 1px 1px;
|
||||
padding: 20px 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.table-bordered {
|
||||
border-radius: 1px;
|
||||
|
||||
th:not(:last-child), td:not(:last-child) {
|
||||
border-right: solid 1px transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,10 @@
|
|||
|
||||
.tree_commit {
|
||||
max-width: 320px;
|
||||
|
||||
.str-truncated {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.tree_time_ago {
|
||||
|
|
17
app/controllers/admin/requests_profiles_controller.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
class Admin::RequestsProfilesController < Admin::ApplicationController
|
||||
def index
|
||||
@profile_token = Gitlab::RequestProfiler.profile_token
|
||||
@profiles = Gitlab::RequestProfiler::Profile.all.group_by(&:request_path)
|
||||
end
|
||||
|
||||
def show
|
||||
clean_name = Rack::Utils.clean_path_info(params[:name])
|
||||
profile = Gitlab::RequestProfiler::Profile.find(clean_name)
|
||||
|
||||
if profile
|
||||
render text: profile.content
|
||||
else
|
||||
redirect_to admin_requests_profiles_path, alert: 'Profile not found'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -243,42 +243,6 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def set_filters_params
|
||||
set_default_sort
|
||||
|
||||
params[:scope] = 'all' if params[:scope].blank?
|
||||
params[:state] = 'opened' if params[:state].blank?
|
||||
|
||||
@sort = params[:sort]
|
||||
@filter_params = params.dup
|
||||
|
||||
if @project
|
||||
@filter_params[:project_id] = @project.id
|
||||
elsif @group
|
||||
@filter_params[:group_id] = @group.id
|
||||
else
|
||||
# TODO: this filter ignore issues/mr created in public or
|
||||
# internal repos where you are not a member. Enable this filter
|
||||
# or improve current implementation to filter only issues you
|
||||
# created or assigned or mentioned
|
||||
# @filter_params[:authorized_only] = true
|
||||
end
|
||||
|
||||
@filter_params
|
||||
end
|
||||
|
||||
def get_issues_collection
|
||||
set_filters_params
|
||||
@issuable_finder = IssuesFinder.new(current_user, @filter_params)
|
||||
@issuable_finder.execute
|
||||
end
|
||||
|
||||
def get_merge_requests_collection
|
||||
set_filters_params
|
||||
@issuable_finder = MergeRequestsFinder.new(current_user, @filter_params)
|
||||
@issuable_finder.execute
|
||||
end
|
||||
|
||||
def import_sources_enabled?
|
||||
!current_application_settings.import_sources.empty?
|
||||
end
|
||||
|
@ -363,24 +327,4 @@ class ApplicationController < ActionController::Base
|
|||
def u2f_app_id
|
||||
request.base_url
|
||||
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
|
||||
|
|
|
@ -5,6 +5,7 @@ class AutocompleteController < ApplicationController
|
|||
def users
|
||||
@users ||= User.none
|
||||
@users = @users.search(params[:search]) if params[:search].present?
|
||||
@users = @users.where.not(id: params[:skip_users]) if params[:skip_users].present?
|
||||
@users = @users.active
|
||||
@users = @users.reorder(:name)
|
||||
@users = @users.page(params[:page])
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
module DiffForPath
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def render_diff_for_path(diffs, diff_refs, project)
|
||||
diff_file = safe_diff_files(diffs, diff_refs: diff_refs, repository: project.repository).find do |diff|
|
||||
def render_diff_for_path(diffs)
|
||||
diff_file = diffs.diff_files.find do |diff|
|
||||
diff.old_path == params[:old_path] && diff.new_path == params[:new_path]
|
||||
end
|
||||
|
||||
|
@ -14,7 +14,7 @@ module DiffForPath
|
|||
locals = {
|
||||
diff_file: diff_file,
|
||||
diff_commit: diff_commit,
|
||||
diff_refs: diff_refs,
|
||||
diff_refs: diffs.diff_refs,
|
||||
blob: blob,
|
||||
project: project
|
||||
}
|
||||
|
|
79
app/controllers/concerns/issuable_collections.rb
Normal file
|
@ -0,0 +1,79 @@
|
|||
module IssuableCollections
|
||||
extend ActiveSupport::Concern
|
||||
include SortingHelper
|
||||
|
||||
included do
|
||||
helper_method :issues_finder
|
||||
helper_method :merge_requests_finder
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def issues_collection
|
||||
issues_finder.execute
|
||||
end
|
||||
|
||||
def merge_requests_collection
|
||||
merge_requests_finder.execute
|
||||
end
|
||||
|
||||
def issues_finder
|
||||
@issues_finder ||= issuable_finder_for(IssuesFinder)
|
||||
end
|
||||
|
||||
def merge_requests_finder
|
||||
@merge_requests_finder ||= issuable_finder_for(MergeRequestsFinder)
|
||||
end
|
||||
|
||||
def issuable_finder_for(finder_class)
|
||||
finder_class.new(current_user, filter_params)
|
||||
end
|
||||
|
||||
def filter_params
|
||||
set_sort_order_from_cookie
|
||||
set_default_scope
|
||||
set_default_state
|
||||
|
||||
@filter_params = params.dup
|
||||
@filter_params[:sort] ||= default_sort_order
|
||||
|
||||
@sort = @filter_params[:sort]
|
||||
|
||||
if @project
|
||||
@filter_params[:project_id] = @project.id
|
||||
elsif @group
|
||||
@filter_params[:group_id] = @group.id
|
||||
else
|
||||
# TODO: this filter ignore issues/mr created in public or
|
||||
# internal repos where you are not a member. Enable this filter
|
||||
# or improve current implementation to filter only issues you
|
||||
# created or assigned or mentioned
|
||||
# @filter_params[:authorized_only] = true
|
||||
end
|
||||
|
||||
@filter_params
|
||||
end
|
||||
|
||||
def set_default_scope
|
||||
params[:scope] = 'all' if params[:scope].blank?
|
||||
end
|
||||
|
||||
def set_default_state
|
||||
params[:state] = 'opened' if params[:state].blank?
|
||||
end
|
||||
|
||||
def set_sort_order_from_cookie
|
||||
key = 'issuable_sort'
|
||||
|
||||
cookies[key] = params[:sort] if params[:sort].present?
|
||||
params[:sort] = cookies[key]
|
||||
end
|
||||
|
||||
def default_sort_order
|
||||
case params[:state]
|
||||
when 'opened', 'all' then sort_value_recently_created
|
||||
when 'merged', 'closed' then sort_value_recently_updated
|
||||
else sort_value_recently_created
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,12 +1,14 @@
|
|||
module IssuesAction
|
||||
extend ActiveSupport::Concern
|
||||
include IssuableCollections
|
||||
|
||||
def issues
|
||||
@issues = get_issues_collection.non_archived
|
||||
@issues = @issues.page(params[:page])
|
||||
@issues = @issues.preload(:author, :project)
|
||||
@label = issues_finder.labels.first
|
||||
|
||||
@label = @issuable_finder.labels.first
|
||||
@issues = issues_collection
|
||||
.non_archived
|
||||
.preload(:author, :project)
|
||||
.page(params[:page])
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
module MergeRequestsAction
|
||||
extend ActiveSupport::Concern
|
||||
include IssuableCollections
|
||||
|
||||
def merge_requests
|
||||
@merge_requests = get_merge_requests_collection.non_archived
|
||||
@merge_requests = @merge_requests.page(params[:page])
|
||||
@merge_requests = @merge_requests.preload(:author, :target_project)
|
||||
@label = merge_requests_finder.labels.first
|
||||
|
||||
@label = @issuable_finder.labels.first
|
||||
@merge_requests = merge_requests_collection
|
||||
.non_archived
|
||||
.preload(:author, :target_project)
|
||||
.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Explore::ApplicationController < ApplicationController
|
||||
skip_before_action :authenticate_user!, :reject_blocked
|
||||
skip_before_action :authenticate_user!, :reject_blocked!
|
||||
|
||||
layout 'explore'
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class HelpController < ApplicationController
|
||||
skip_before_action :authenticate_user!, :reject_blocked
|
||||
skip_before_action :authenticate_user!, :reject_blocked!
|
||||
|
||||
layout 'help'
|
||||
|
||||
|
|
|
@ -82,8 +82,6 @@ class Import::BitbucketController < Import::BaseController
|
|||
go_to_bitbucket_for_permissions
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def access_params
|
||||
{
|
||||
bitbucket_access_token: session[:bitbucket_access_token],
|
||||
|
|
|
@ -61,8 +61,6 @@ class Import::GitlabController < Import::BaseController
|
|||
go_to_gitlab_for_permissions
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def access_params
|
||||
{ gitlab_access_token: session[:gitlab_access_token] }
|
||||
end
|
||||
|
|
|
@ -12,13 +12,14 @@ class Import::GitlabProjectsController < Import::BaseController
|
|||
return redirect_back_or_default(options: { alert: "You need to upload a GitLab project export archive." })
|
||||
end
|
||||
|
||||
imported_file = project_params[:file].path + "-import"
|
||||
import_upload_path = Gitlab::ImportExport.import_upload_path(filename: project_params[:file].original_filename)
|
||||
|
||||
FileUtils.copy_entry(project_params[:file].path, imported_file)
|
||||
FileUtils.mkdir_p(File.dirname(import_upload_path))
|
||||
FileUtils.copy_entry(project_params[:file].path, import_upload_path)
|
||||
|
||||
@project = Gitlab::ImportExport::ProjectCreator.new(project_params[:namespace_id],
|
||||
current_user,
|
||||
File.expand_path(imported_file),
|
||||
import_upload_path,
|
||||
project_params[:path]).execute
|
||||
|
||||
if @project.saved?
|
||||
|
|
|
@ -50,6 +50,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController
|
|||
flash[:notice] = "Password was successfully updated. Please login with it"
|
||||
redirect_to new_user_session_path
|
||||
else
|
||||
@user.reload
|
||||
render 'edit'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -76,6 +76,8 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def diff
|
||||
apply_diff_view_cookie!
|
||||
|
||||
@form = UnfoldForm.new(params)
|
||||
@lines = Gitlab::Highlight.highlight_lines(repository, @ref, @path)
|
||||
@lines = @lines[@form.since - 1..@form.to - 1]
|
||||
|
|
|
@ -6,8 +6,8 @@ class Projects::BranchesController < Projects::ApplicationController
|
|||
before_action :authorize_push_code!, only: [:new, :create, :destroy]
|
||||
|
||||
def index
|
||||
@sort = params[:sort] || 'name'
|
||||
@branches = @repository.branches_sorted_by(@sort)
|
||||
@sort = params[:sort].presence || 'name'
|
||||
@branches = BranchesFinder.new(@repository, params).execute
|
||||
@branches = Kaminari.paginate_array(@branches).page(params[:page])
|
||||
|
||||
@max_commits = @branches.reduce(0) do |memo, branch|
|
||||
|
|
|
@ -28,7 +28,7 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def diff_for_path
|
||||
render_diff_for_path(@diffs, @commit.diff_refs, @project)
|
||||
render_diff_for_path(@commit.diffs(diff_options))
|
||||
end
|
||||
|
||||
def builds
|
||||
|
|
|
@ -21,7 +21,7 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
def diff_for_path
|
||||
return render_404 unless @compare
|
||||
|
||||
render_diff_for_path(@diffs, @diff_refs, @project)
|
||||
render_diff_for_path(@compare.diffs(diff_options))
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -40,18 +40,12 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
@compare = CompareService.new.execute(@project, @head_ref, @project, @start_ref)
|
||||
|
||||
if @compare
|
||||
@commits = Commit.decorate(@compare.commits, @project)
|
||||
|
||||
@start_commit = @project.commit(@start_ref)
|
||||
@commit = @project.commit(@head_ref)
|
||||
@base_commit = @project.merge_base_commit(@start_ref, @head_ref)
|
||||
@commits = @compare.commits
|
||||
@start_commit = @compare.start_commit
|
||||
@commit = @compare.commit
|
||||
@base_commit = @compare.base_commit
|
||||
|
||||
@diffs = @compare.diffs(diff_options)
|
||||
@diff_refs = Gitlab::Diff::DiffRefs.new(
|
||||
base_sha: @base_commit.try(:sha),
|
||||
start_sha: @start_commit.try(:sha),
|
||||
head_sha: @commit.try(:sha)
|
||||
)
|
||||
|
||||
@diff_notes_disabled = true
|
||||
@grouped_diff_discussions = {}
|
||||
|
|
|
@ -12,8 +12,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
redirect_to namespace_project_deploy_keys_path(@project.namespace,
|
||||
@project)
|
||||
redirect_to namespace_project_deploy_keys_path(@project.namespace, @project)
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -21,19 +20,16 @@ class Projects::DeployKeysController < Projects::ApplicationController
|
|||
set_index_vars
|
||||
|
||||
if @key.valid? && @project.deploy_keys << @key
|
||||
redirect_to namespace_project_deploy_keys_path(@project.namespace,
|
||||
@project)
|
||||
redirect_to namespace_project_deploy_keys_path(@project.namespace, @project)
|
||||
else
|
||||
render "index"
|
||||
end
|
||||
end
|
||||
|
||||
def enable
|
||||
@key = accessible_keys.find(params[:id])
|
||||
@project.deploy_keys << @key
|
||||
Projects::EnableDeployKeyService.new(@project, current_user, params).execute
|
||||
|
||||
redirect_to namespace_project_deploy_keys_path(@project.namespace,
|
||||
@project)
|
||||
redirect_to namespace_project_deploy_keys_path(@project.namespace, @project)
|
||||
end
|
||||
|
||||
def disable
|
||||
|
@ -45,9 +41,9 @@ class Projects::DeployKeysController < Projects::ApplicationController
|
|||
protected
|
||||
|
||||
def set_index_vars
|
||||
@enabled_keys ||= @project.deploy_keys
|
||||
@enabled_keys ||= @project.deploy_keys
|
||||
|
||||
@available_keys ||= accessible_keys - @enabled_keys
|
||||
@available_keys ||= current_user.accessible_deploy_keys - @enabled_keys
|
||||
@available_project_keys ||= current_user.project_deploy_keys - @enabled_keys
|
||||
@available_public_keys ||= DeployKey.are_public - @enabled_keys
|
||||
|
||||
|
@ -56,10 +52,6 @@ class Projects::DeployKeysController < Projects::ApplicationController
|
|||
@available_public_keys -= @available_project_keys
|
||||
end
|
||||
|
||||
def accessible_keys
|
||||
@accessible_keys ||= current_user.accessible_deploy_keys
|
||||
end
|
||||
|
||||
def deploy_key_params
|
||||
params.require(:deploy_key).permit(:key, :title)
|
||||
end
|
||||
|
|
|
@ -2,8 +2,8 @@ class Projects::EnvironmentsController < Projects::ApplicationController
|
|||
layout 'project'
|
||||
before_action :authorize_read_environment!
|
||||
before_action :authorize_create_environment!, only: [:new, :create]
|
||||
before_action :authorize_update_environment!, only: [:destroy]
|
||||
before_action :environment, only: [:show, :destroy]
|
||||
before_action :authorize_update_environment!, only: [:edit, :update, :destroy]
|
||||
before_action :environment, only: [:show, :edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
@environments = project.environments
|
||||
|
@ -17,13 +17,24 @@ class Projects::EnvironmentsController < Projects::ApplicationController
|
|||
@environment = project.environments.new
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def create
|
||||
@environment = project.environments.create(create_params)
|
||||
@environment = project.environments.create(environment_params)
|
||||
|
||||
if @environment.persisted?
|
||||
redirect_to namespace_project_environment_path(project.namespace, project, @environment)
|
||||
else
|
||||
render 'new'
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
if @environment.update(environment_params)
|
||||
redirect_to namespace_project_environment_path(project.namespace, project, @environment)
|
||||
else
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -39,8 +50,8 @@ class Projects::EnvironmentsController < Projects::ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def create_params
|
||||
params.require(:environment).permit(:name)
|
||||
def environment_params
|
||||
params.require(:environment).permit(:name, :external_url)
|
||||
end
|
||||
|
||||
def environment
|
||||
|
|
|
@ -20,9 +20,9 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
elsif receive_pack? && receive_pack_allowed?
|
||||
render_ok
|
||||
elsif http_blocked?
|
||||
render_not_allowed
|
||||
render_http_not_allowed
|
||||
else
|
||||
render_not_found
|
||||
render_denied
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -31,7 +31,7 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
if upload_pack? && upload_pack_allowed?
|
||||
render_ok
|
||||
else
|
||||
render_not_found
|
||||
render_denied
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +40,7 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
if receive_pack? && receive_pack_allowed?
|
||||
render_ok
|
||||
else
|
||||
render_not_found
|
||||
render_denied
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -156,8 +156,17 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
render plain: 'Not Found', status: :not_found
|
||||
end
|
||||
|
||||
def render_not_allowed
|
||||
render plain: download_access.message, status: :forbidden
|
||||
def render_http_not_allowed
|
||||
render plain: access_check.message, status: :forbidden
|
||||
end
|
||||
|
||||
def render_denied
|
||||
if user && user.can?(:read_project, project)
|
||||
render plain: 'Access denied', status: :forbidden
|
||||
else
|
||||
# Do not leak information about project existence
|
||||
render_not_found
|
||||
end
|
||||
end
|
||||
|
||||
def ci?
|
||||
|
@ -168,22 +177,20 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
return false unless Gitlab.config.gitlab_shell.upload_pack
|
||||
|
||||
if user
|
||||
download_access.allowed?
|
||||
access_check.allowed?
|
||||
else
|
||||
ci? || project.public?
|
||||
end
|
||||
end
|
||||
|
||||
def access
|
||||
return @access if defined?(@access)
|
||||
|
||||
@access = Gitlab::GitAccess.new(user, project, 'http')
|
||||
@access ||= Gitlab::GitAccess.new(user, project, 'http')
|
||||
end
|
||||
|
||||
def download_access
|
||||
return @download_access if defined?(@download_access)
|
||||
|
||||
@download_access = access.check('git-upload-pack')
|
||||
def access_check
|
||||
# Use the magic string '_any' to indicate we do not know what the
|
||||
# changes are. This is also what gitlab-shell does.
|
||||
@access_check ||= access.check(git_command, '_any')
|
||||
end
|
||||
|
||||
def http_blocked?
|
||||
|
@ -193,8 +200,6 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
def receive_pack_allowed?
|
||||
return false unless Gitlab.config.gitlab_shell.receive_pack
|
||||
|
||||
# Skip user authorization on upload request.
|
||||
# It will be done by the pre-receive hook in the repository.
|
||||
user.present?
|
||||
access_check.allowed?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
class Projects::IssuesController < Projects::ApplicationController
|
||||
include NotesHelper
|
||||
include ToggleSubscriptionAction
|
||||
include IssuableActions
|
||||
include ToggleAwardEmoji
|
||||
include IssuableCollections
|
||||
|
||||
before_action :redirect_to_external_issue_tracker, only: [:index, :new]
|
||||
before_action :module_enabled
|
||||
before_action :issue, only: [:edit, :update, :show, :referenced_merge_requests,
|
||||
:related_branches, :can_create_branch]
|
||||
|
@ -23,7 +26,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
|
||||
def index
|
||||
terms = params['issue_search']
|
||||
@issues = get_issues_collection
|
||||
@issues = issues_collection
|
||||
|
||||
if terms.present?
|
||||
if terms =~ /\A#(\d+)\z/
|
||||
|
@ -70,6 +73,8 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
@note = @project.notes.new(noteable: @issue)
|
||||
@noteable = @issue
|
||||
|
||||
preload_max_access_for_authors(@notes, @project)
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json do
|
||||
|
@ -79,7 +84,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
@issue = Issues::CreateService.new(project, current_user, issue_params).execute
|
||||
@issue = Issues::CreateService.new(project, current_user, issue_params.merge(request: request)).execute
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
|
@ -89,7 +94,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
render :new
|
||||
end
|
||||
end
|
||||
format.js do |format|
|
||||
format.js do
|
||||
@link = @issue.attachment.url.to_js
|
||||
end
|
||||
end
|
||||
|
@ -197,6 +202,18 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
return render_404 unless @project.issues_enabled && @project.default_issues_tracker?
|
||||
end
|
||||
|
||||
def redirect_to_external_issue_tracker
|
||||
external = @project.external_issue_tracker
|
||||
|
||||
return unless external
|
||||
|
||||
if action_name == 'new'
|
||||
redirect_to external.new_issue_path
|
||||
else
|
||||
redirect_to external.issues_url
|
||||
end
|
||||
end
|
||||
|
||||
# Since iids are implemented only in 6.1
|
||||
# user may navigate to issue page using old global ids.
|
||||
#
|
||||
|
|
|
@ -3,7 +3,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
include DiffForPath
|
||||
include DiffHelper
|
||||
include IssuableActions
|
||||
include NotesHelper
|
||||
include ToggleAwardEmoji
|
||||
include IssuableCollections
|
||||
|
||||
before_action :module_enabled
|
||||
before_action :merge_request, only: [
|
||||
|
@ -28,7 +30,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
|
||||
def index
|
||||
terms = params['issue_search']
|
||||
@merge_requests = get_merge_requests_collection
|
||||
@merge_requests = merge_requests_collection
|
||||
|
||||
if terms.present?
|
||||
if terms =~ /\A[#!](\d+)\z/
|
||||
|
@ -83,7 +85,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html { define_discussion_vars }
|
||||
format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
|
||||
format.json do
|
||||
@diffs = @merge_request.diffs(diff_options)
|
||||
|
||||
render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -101,9 +107,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
define_commit_vars
|
||||
diffs = @merge_request.diffs(diff_options)
|
||||
|
||||
render_diff_for_path(diffs, @merge_request.diff_refs, @merge_request.project)
|
||||
render_diff_for_path(@merge_request.diffs(diff_options))
|
||||
end
|
||||
|
||||
def commits
|
||||
|
@ -151,7 +156,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
@commits = @merge_request.compare_commits.reverse
|
||||
@commit = @merge_request.diff_head_commit
|
||||
@base_commit = @merge_request.diff_base_commit
|
||||
@diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare
|
||||
@diffs = @merge_request.diffs(diff_options) if @merge_request.compare
|
||||
@diff_notes_disabled = true
|
||||
|
||||
@pipeline = @merge_request.pipeline
|
||||
|
@ -376,6 +381,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
fresh.
|
||||
discussions
|
||||
|
||||
preload_noteable_for_regular_notes(@discussions.flat_map(&:notes))
|
||||
|
||||
# This is not executed lazily
|
||||
@notes = Banzai::NoteRenderer.render(
|
||||
@discussions.flat_map(&:notes),
|
||||
|
@ -385,6 +392,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
@project_wiki,
|
||||
@ref
|
||||
)
|
||||
|
||||
preload_max_access_for_authors(@notes, @project)
|
||||
end
|
||||
|
||||
def define_widget_vars
|
||||
|
@ -404,7 +413,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
}
|
||||
|
||||
@use_legacy_diff_notes = !@merge_request.support_new_diff_notes?
|
||||
@grouped_diff_discussions = @merge_request.notes.grouped_diff_discussions
|
||||
@grouped_diff_discussions = @merge_request.notes.inc_author_project_award_emoji.grouped_diff_discussions
|
||||
|
||||
Banzai::NoteRenderer.render(
|
||||
@grouped_diff_discussions.values.flat_map(&:notes),
|
||||
|
|
|
@ -3,19 +3,24 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
|
|||
before_action :require_non_empty_project
|
||||
before_action :authorize_admin_project!
|
||||
before_action :load_protected_branch, only: [:show, :update, :destroy]
|
||||
before_action :load_protected_branches, only: [:index]
|
||||
|
||||
layout "project_settings"
|
||||
|
||||
def index
|
||||
@protected_branches = @project.protected_branches.order(:name).page(params[:page])
|
||||
@protected_branch = @project.protected_branches.new
|
||||
gon.push({ open_branches: @project.open_branches.map { |br| { text: br.name, id: br.name, title: br.name } } })
|
||||
load_protected_branches_gon_variables
|
||||
end
|
||||
|
||||
def create
|
||||
@project.protected_branches.create(protected_branch_params)
|
||||
redirect_to namespace_project_protected_branches_path(@project.namespace,
|
||||
@project)
|
||||
@protected_branch = ProtectedBranches::CreateService.new(@project, current_user, protected_branch_params).execute
|
||||
if @protected_branch.persisted?
|
||||
redirect_to namespace_project_protected_branches_path(@project.namespace, @project)
|
||||
else
|
||||
load_protected_branches
|
||||
load_protected_branches_gon_variables
|
||||
render :index
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
|
@ -23,7 +28,9 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
if @protected_branch && @protected_branch.update_attributes(protected_branch_params)
|
||||
@protected_branch = ProtectedBranches::UpdateService.new(@project, current_user, protected_branch_params).execute(@protected_branch)
|
||||
|
||||
if @protected_branch.valid?
|
||||
respond_to do |format|
|
||||
format.json { render json: @protected_branch, status: :ok }
|
||||
end
|
||||
|
@ -50,6 +57,18 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def protected_branch_params
|
||||
params.require(:protected_branch).permit(:name, :developers_can_push, :developers_can_merge)
|
||||
params.require(:protected_branch).permit(:name,
|
||||
merge_access_level_attributes: [:access_level],
|
||||
push_access_level_attributes: [:access_level])
|
||||
end
|
||||
|
||||
def load_protected_branches
|
||||
@protected_branches = @project.protected_branches.order(:name).page(params[:page])
|
||||
end
|
||||
|
||||
def load_protected_branches_gon_variables
|
||||
gon.push({ open_branches: @project.open_branches.map { |br| { text: br.name, id: br.name, title: br.name } },
|
||||
push_access_levels: ProtectedBranch::PushAccessLevel.human_access_levels.map { |id, text| { id: id, text: text } },
|
||||
merge_access_levels: ProtectedBranch::MergeAccessLevel.human_access_levels.map { |id, text| { id: id, text: text } } })
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,11 +10,12 @@ class Projects::TagsController < Projects::ApplicationController
|
|||
@tags = @repository.tags_sorted_by(@sort)
|
||||
@tags = Kaminari.paginate_array(@tags).page(params[:page])
|
||||
|
||||
@releases = project.releases.where(tag: @tags)
|
||||
@releases = project.releases.where(tag: @tags.map(&:name))
|
||||
end
|
||||
|
||||
def show
|
||||
@tag = @repository.find_tag(params[:id])
|
||||
|
||||
@release = @project.releases.find_or_initialize_by(tag: @tag.name)
|
||||
@commit = @repository.commit(@tag.target)
|
||||
end
|
||||
|
|
|
@ -97,7 +97,7 @@ class ProjectsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
if @project.pending_delete?
|
||||
flash[:alert] = "Project queued for delete."
|
||||
flash[:alert] = "Project #{@project.name} queued for deletion."
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
|
|
|
@ -33,7 +33,7 @@ class RegistrationsController < Devise::RegistrationsController
|
|||
|
||||
protected
|
||||
|
||||
def build_resource(hash=nil)
|
||||
def build_resource(hash = nil)
|
||||
super
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class SearchController < ApplicationController
|
||||
skip_before_action :authenticate_user!, :reject_blocked
|
||||
skip_before_action :authenticate_user!, :reject_blocked!
|
||||
|
||||
include SearchHelper
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ class SessionsController < Devise::SessionsController
|
|||
# Prevent alert from popping up on the first page shown after authentication.
|
||||
flash[:alert] = nil
|
||||
|
||||
redirect_to user_omniauth_authorize_path(provider.to_sym)
|
||||
redirect_to omniauth_authorize_path(:user, provider)
|
||||
end
|
||||
|
||||
def valid_otp_attempt?(user)
|
||||
|
|
31
app/finders/branches_finder.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
class BranchesFinder
|
||||
def initialize(repository, params)
|
||||
@repository = repository
|
||||
@params = params
|
||||
end
|
||||
|
||||
def execute
|
||||
branches = @repository.branches_sorted_by(sort)
|
||||
filter_by_name(branches)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :repository, :params
|
||||
|
||||
def search
|
||||
@params[:search].presence
|
||||
end
|
||||
|
||||
def sort
|
||||
@params[:sort].presence || 'name'
|
||||
end
|
||||
|
||||
def filter_by_name(branches)
|
||||
if search
|
||||
branches.select { |branch| branch.name.include?(search) }
|
||||
else
|
||||
branches
|
||||
end
|
||||
end
|
||||
end
|
|
@ -109,7 +109,7 @@ class IssuableFinder
|
|||
|
||||
scope.where(title: params[:milestone_title])
|
||||
else
|
||||
nil
|
||||
Milestone.none
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -163,9 +163,13 @@ module ApplicationHelper
|
|||
# `html_class` argument is provided.
|
||||
#
|
||||
# Returns an HTML-safe String
|
||||
def time_ago_with_tooltip(time, placement: 'top', html_class: 'time_ago', skip_js: false)
|
||||
def time_ago_with_tooltip(time, placement: 'top', html_class: '', skip_js: false, short_format: false)
|
||||
css_classes = short_format ? 'js-short-timeago' : 'js-timeago'
|
||||
css_classes << " #{html_class}" unless html_class.blank?
|
||||
css_classes << ' js-timeago-pending' unless skip_js
|
||||
|
||||
element = content_tag :time, time.to_s,
|
||||
class: "#{html_class} js-timeago #{"js-timeago-pending" unless skip_js}",
|
||||
class: css_classes,
|
||||
datetime: time.to_time.getutc.iso8601,
|
||||
title: time.to_time.in_time_zone.to_s(:medium),
|
||||
data: { toggle: 'tooltip', placement: placement, container: 'body' }
|
||||
|
@ -245,7 +249,6 @@ module ApplicationHelper
|
|||
milestone_title: params[:milestone_title],
|
||||
assignee_id: params[:assignee_id],
|
||||
author_id: params[:author_id],
|
||||
sort: params[:sort],
|
||||
issue_search: params[:issue_search],
|
||||
label_name: params[:label_name]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
module AvatarsHelper
|
||||
|
||||
def author_avatar(commit_or_event, options = {})
|
||||
user_avatar(options.merge({
|
||||
user: commit_or_event.author,
|
||||
|
@ -26,5 +25,4 @@ module AvatarsHelper
|
|||
mail_to(options[:user_email], avatar)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ module BlobHelper
|
|||
|
||||
blob = project.repository.blob_at(ref, path) rescue nil
|
||||
|
||||
return unless blob && blob_text_viewable?(blob)
|
||||
return unless blob
|
||||
|
||||
from_mr = options[:from_merge_request_id]
|
||||
link_opts = {}
|
||||
|
|
|
@ -9,6 +9,17 @@ module BranchesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def filter_branches_path(options = {})
|
||||
exist_opts = {
|
||||
search: params[:search],
|
||||
sort: params[:sort]
|
||||
}
|
||||
|
||||
options = exist_opts.merge(options)
|
||||
|
||||
namespace_project_branches_path(@project.namespace, @project, @id, options)
|
||||
end
|
||||
|
||||
def can_push_branch?(project, branch_name)
|
||||
return false unless project.repository.branch_exists?(branch_name)
|
||||
|
||||
|
|
|
@ -206,10 +206,10 @@ module CommitsHelper
|
|||
end
|
||||
end
|
||||
|
||||
def view_file_btn(commit_sha, diff, project)
|
||||
def view_file_btn(commit_sha, diff_new_path, project)
|
||||
link_to(
|
||||
namespace_project_blob_path(project.namespace, project,
|
||||
tree_join(commit_sha, diff.new_path)),
|
||||
tree_join(commit_sha, diff_new_path)),
|
||||
class: 'btn view-file js-view-file btn-file-option'
|
||||
) do
|
||||
raw('View file @') + content_tag(:span, commit_sha[0..6],
|
||||
|
|
|
@ -13,12 +13,11 @@ module DiffHelper
|
|||
end
|
||||
|
||||
def diff_view
|
||||
diff_views = %w(inline parallel)
|
||||
|
||||
if diff_views.include?(cookies[:diff_view])
|
||||
cookies[:diff_view]
|
||||
else
|
||||
diff_views.first
|
||||
@diff_view ||= begin
|
||||
diff_views = %w(inline parallel)
|
||||
diff_view = cookies[:diff_view]
|
||||
diff_view = diff_views.first unless diff_views.include?(diff_view)
|
||||
diff_view.to_sym
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -30,19 +29,26 @@ module DiffHelper
|
|||
options[:paths] = params.values_at(:old_path, :new_path)
|
||||
end
|
||||
|
||||
Commit.max_diff_options.merge(options)
|
||||
options
|
||||
end
|
||||
|
||||
def safe_diff_files(diffs, diff_refs: nil, repository: nil)
|
||||
diffs.decorate! { |diff| Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
|
||||
end
|
||||
def diff_match_line(old_pos, new_pos, text: '', view: :inline, bottom: false)
|
||||
content = content_tag :td, text, class: "line_content match #{view == :inline ? '' : view}"
|
||||
cls = ['diff-line-num', 'unfold', 'js-unfold']
|
||||
cls << 'js-unfold-bottom' if bottom
|
||||
|
||||
def unfold_bottom_class(bottom)
|
||||
bottom ? 'js-unfold js-unfold-bottom' : ''
|
||||
end
|
||||
html = ''
|
||||
if old_pos
|
||||
html << content_tag(:td, '...', class: cls + ['old_line'], data: { linenumber: old_pos })
|
||||
html << content unless view == :inline
|
||||
end
|
||||
|
||||
def unfold_class(unfold)
|
||||
unfold ? 'unfold js-unfold' : ''
|
||||
if new_pos
|
||||
html << content_tag(:td, '...', class: cls + ['new_line'], data: { linenumber: new_pos })
|
||||
html << content
|
||||
end
|
||||
|
||||
html.html_safe
|
||||
end
|
||||
|
||||
def diff_line_content(line, line_type = nil)
|
||||
|
@ -71,11 +77,11 @@ module DiffHelper
|
|||
end
|
||||
|
||||
def inline_diff_btn
|
||||
diff_btn('Inline', 'inline', diff_view == 'inline')
|
||||
diff_btn('Inline', 'inline', diff_view == :inline)
|
||||
end
|
||||
|
||||
def parallel_diff_btn
|
||||
diff_btn('Side-by-side', 'parallel', diff_view == 'parallel')
|
||||
diff_btn('Side-by-side', 'parallel', diff_view == :parallel)
|
||||
end
|
||||
|
||||
def submodule_link(blob, ref, repository = @repository)
|
||||
|
@ -107,7 +113,8 @@ module DiffHelper
|
|||
commit = commit_for_diff(diff_file)
|
||||
{
|
||||
blob_diff_path: namespace_project_blob_diff_path(project.namespace, project,
|
||||
tree_join(commit.id, diff_file.file_path))
|
||||
tree_join(commit.id, diff_file.file_path)),
|
||||
view: diff_view
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -144,8 +151,6 @@ module DiffHelper
|
|||
toggle_whitespace_link(url, options)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def hide_whitespace?
|
||||
params[:w] == '1'
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module ExploreHelper
|
||||
def filter_projects_path(options={})
|
||||
def filter_projects_path(options = {})
|
||||
exist_opts = {
|
||||
sort: params[:sort],
|
||||
scope: params[:scope],
|
||||
|
|
|
@ -13,38 +13,6 @@ module IssuesHelper
|
|||
OpenStruct.new(id: 0, title: 'None (backlog)', name: 'Unassigned')
|
||||
end
|
||||
|
||||
def url_for_project_issues(project = @project, options = {})
|
||||
return '' if project.nil?
|
||||
|
||||
url =
|
||||
if options[:only_path]
|
||||
project.issues_tracker.project_path
|
||||
else
|
||||
project.issues_tracker.project_url
|
||||
end
|
||||
|
||||
# Ensure we return a valid URL to prevent possible XSS.
|
||||
URI.parse(url).to_s
|
||||
rescue URI::InvalidURIError
|
||||
''
|
||||
end
|
||||
|
||||
def url_for_new_issue(project = @project, options = {})
|
||||
return '' if project.nil?
|
||||
|
||||
url =
|
||||
if options[:only_path]
|
||||
project.issues_tracker.new_issue_path
|
||||
else
|
||||
project.issues_tracker.new_issue_url
|
||||
end
|
||||
|
||||
# Ensure we return a valid URL to prevent possible XSS.
|
||||
URI.parse(url).to_s
|
||||
rescue URI::InvalidURIError
|
||||
''
|
||||
end
|
||||
|
||||
def url_for_issue(issue_iid, project = @project, options = {})
|
||||
return '' if project.nil?
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ module NotesHelper
|
|||
end
|
||||
|
||||
def note_editable?(note)
|
||||
note.editable? && can?(current_user, :admin_note, note)
|
||||
Ability.can_edit_note?(current_user, note)
|
||||
end
|
||||
|
||||
def noteable_json(noteable)
|
||||
|
@ -87,14 +87,17 @@ module NotesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def note_max_access_for_user(note)
|
||||
@max_access_by_user_id ||= Hash.new do |hash, key|
|
||||
project = key[:project]
|
||||
hash[key] = project.team.human_max_access(key[:user_id])
|
||||
end
|
||||
def preload_max_access_for_authors(notes, project)
|
||||
user_ids = notes.map(&:author_id)
|
||||
project.team.max_member_access_for_user_ids(user_ids)
|
||||
end
|
||||
|
||||
full_key = { project: note.project, user_id: note.author_id }
|
||||
@max_access_by_user_id[full_key]
|
||||
def preload_noteable_for_regular_notes(notes)
|
||||
ActiveRecord::Associations::Preloader.new.preload(notes.select { |note| !note.for_commit? }, :noteable)
|
||||
end
|
||||
|
||||
def note_max_access_for_user(note)
|
||||
note.project.team.human_max_access(note.author_id)
|
||||
end
|
||||
|
||||
def discussion_diff_path(discussion)
|
||||
|
|
|
@ -263,6 +263,10 @@ module ProjectsHelper
|
|||
filename_path(project, :version)
|
||||
end
|
||||
|
||||
def ci_configuration_path(project)
|
||||
filename_path(project, :gitlab_ci_yml)
|
||||
end
|
||||
|
||||
def project_wiki_path_with_version(proj, page, version, is_newest)
|
||||
url_params = is_newest ? {} : { version_id: version }
|
||||
namespace_project_wiki_path(proj.namespace, proj, page, url_params)
|
||||
|
|
|
@ -107,7 +107,7 @@ module SearchHelper
|
|||
Sanitize.clean(str)
|
||||
end
|
||||
|
||||
def search_filter_path(options={})
|
||||
def search_filter_path(options = {})
|
||||
exist_opts = {
|
||||
search: params[:search],
|
||||
project_id: params[:project_id],
|
||||
|
|