Merge branch 'master' of https://gitlab.com/gitlab-org/gitlab-ce into auto-fsck
This commit is contained in:
commit
7b1bb0f4db
|
|
@ -2,7 +2,6 @@ image: "ruby:2.1"
|
|||
|
||||
services:
|
||||
- mysql:latest
|
||||
- postgres:latest
|
||||
- redis:latest
|
||||
|
||||
cache:
|
||||
|
|
@ -35,134 +34,86 @@ spec:feature:
|
|||
script:
|
||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:api:
|
||||
stage: test
|
||||
script:
|
||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:api
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:models:
|
||||
stage: test
|
||||
script:
|
||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:lib:
|
||||
stage: test
|
||||
script:
|
||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:services:
|
||||
stage: test
|
||||
script:
|
||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:other:
|
||||
stage: test
|
||||
script:
|
||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:other
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spinach:project:half:
|
||||
stage: test
|
||||
script:
|
||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spinach:project:rest:
|
||||
stage: test
|
||||
script:
|
||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spinach:other:
|
||||
stage: test
|
||||
script:
|
||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:other
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
teaspoon:
|
||||
stage: test
|
||||
script:
|
||||
- RAILS_ENV=test bundle exec teaspoon
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
rubocop:
|
||||
stage: test
|
||||
script:
|
||||
- bundle exec rubocop
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
scss-lint:
|
||||
stage: test
|
||||
script:
|
||||
- bundle exec rake scss_lint
|
||||
tags:
|
||||
- ruby
|
||||
|
||||
brakeman:
|
||||
stage: test
|
||||
script:
|
||||
- bundle exec rake brakeman
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
flog:
|
||||
stage: test
|
||||
script:
|
||||
- bundle exec rake flog
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
flay:
|
||||
stage: test
|
||||
script:
|
||||
- bundle exec rake flay
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
bundler:audit:
|
||||
stage: test
|
||||
only:
|
||||
- master
|
||||
script:
|
||||
- "bundle exec bundle-audit update"
|
||||
- "bundle exec bundle-audit check --ignore OSVDB-115941"
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
- "bundle exec bundle-audit check --update --ignore OSVDB-115941"
|
||||
|
||||
# Ruby 2.2 jobs
|
||||
|
||||
|
|
@ -178,9 +129,6 @@ spec:feature:ruby22:
|
|||
key: "ruby22"
|
||||
paths:
|
||||
- vendor
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:api:ruby22:
|
||||
stage: test
|
||||
|
|
@ -193,9 +141,6 @@ spec:api:ruby22:
|
|||
key: "ruby22"
|
||||
paths:
|
||||
- vendor
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:models:ruby22:
|
||||
stage: test
|
||||
|
|
@ -208,9 +153,6 @@ spec:models:ruby22:
|
|||
key: "ruby22"
|
||||
paths:
|
||||
- vendor
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:lib:ruby22:
|
||||
stage: test
|
||||
|
|
@ -223,9 +165,6 @@ spec:lib:ruby22:
|
|||
key: "ruby22"
|
||||
paths:
|
||||
- vendor
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:services:ruby22:
|
||||
stage: test
|
||||
|
|
@ -238,9 +177,6 @@ spec:services:ruby22:
|
|||
key: "ruby22"
|
||||
paths:
|
||||
- vendor
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spec:other:ruby22:
|
||||
stage: test
|
||||
|
|
@ -253,9 +189,6 @@ spec:other:ruby22:
|
|||
key: "ruby22"
|
||||
paths:
|
||||
- vendor
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spinach:project:half:ruby22:
|
||||
stage: test
|
||||
|
|
@ -269,9 +202,6 @@ spinach:project:half:ruby22:
|
|||
key: "ruby22"
|
||||
paths:
|
||||
- vendor
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spinach:project:rest:ruby22:
|
||||
stage: test
|
||||
|
|
@ -285,9 +215,6 @@ spinach:project:rest:ruby22:
|
|||
key: "ruby22"
|
||||
paths:
|
||||
- vendor
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
spinach:other:ruby22:
|
||||
stage: test
|
||||
|
|
@ -301,10 +228,6 @@ spinach:other:ruby22:
|
|||
key: "ruby22"
|
||||
paths:
|
||||
- vendor
|
||||
tags:
|
||||
- ruby
|
||||
- mysql
|
||||
|
||||
|
||||
notify:slack:
|
||||
stage: notifications
|
||||
|
|
|
|||
|
|
@ -691,7 +691,7 @@ Style/ZeroLengthPredicate:
|
|||
# branches, and conditions.
|
||||
Metrics/AbcSize:
|
||||
Enabled: true
|
||||
Max: 70
|
||||
Max: 60
|
||||
|
||||
# Avoid excessive block nesting.
|
||||
Metrics/BlockNesting:
|
||||
|
|
|
|||
105
.scss-lint.yml
105
.scss-lint.yml
|
|
@ -7,21 +7,44 @@ exclude:
|
|||
- 'app/assets/stylesheets/pages/emojis.scss'
|
||||
|
||||
linters:
|
||||
# Reports when you use improper spacing around ! (the "bang") in !default,
|
||||
# !global, !important, and !optional flags.
|
||||
BangFormat:
|
||||
enabled: false
|
||||
|
||||
# Whether or not to prefer `border: 0` over `border: none`.
|
||||
BorderZero:
|
||||
enabled: false
|
||||
|
||||
# Reports when you define a rule set using a selector with chained classes
|
||||
# (a.k.a. adjoining classes).
|
||||
ChainedClasses:
|
||||
enabled: false
|
||||
|
||||
# Prefer hexadecimal color codes over color keywords.
|
||||
# (e.g. `color: green` is a color keyword)
|
||||
ColorKeyword:
|
||||
enabled: false
|
||||
|
||||
# Prefer color literals (keywords or hexadecimal codes) to be used only in
|
||||
# variable declarations. They should be referred to via variables everywhere
|
||||
# else.
|
||||
ColorVariable:
|
||||
enabled: false
|
||||
|
||||
# Which form of comments to prefer in CSS.
|
||||
Comment:
|
||||
enabled: false
|
||||
|
||||
# Reports @debug statements (which you probably left behind accidentally).
|
||||
DebugStatement:
|
||||
enabled: false
|
||||
|
||||
# Rule sets should be ordered as follows:
|
||||
# - @extend declarations
|
||||
# - @include declarations without inner @content
|
||||
# - properties, @include declarations with inner @content
|
||||
# - nested rule sets.
|
||||
DeclarationOrder:
|
||||
enabled: false
|
||||
|
||||
|
|
@ -32,15 +55,25 @@ linters:
|
|||
DisableLinterReason:
|
||||
enabled: true
|
||||
|
||||
# Reports when you define the same property twice in a single rule set.
|
||||
DuplicateProperty:
|
||||
enabled: false
|
||||
|
||||
# Separate rule, function, and mixin declarations with empty lines.
|
||||
EmptyLineBetweenBlocks:
|
||||
enabled: false
|
||||
|
||||
# Reports when you have an empty rule set.
|
||||
EmptyRule:
|
||||
enabled: false
|
||||
|
||||
# Reports when you have an @extend directive.
|
||||
ExtendDirective:
|
||||
enabled: false
|
||||
|
||||
# Files should always have a final newline. This results in better diffs
|
||||
# when adding lines to the file, since SCM systems such as git won't
|
||||
# think that you touched the last line.
|
||||
FinalNewline:
|
||||
enabled: false
|
||||
|
||||
|
|
@ -53,12 +86,17 @@ linters:
|
|||
HexNotation:
|
||||
enabled: true
|
||||
|
||||
# Avoid using ID selectors.
|
||||
IdSelector:
|
||||
enabled: false
|
||||
|
||||
# The basenames of @imported SCSS partials should not begin with an
|
||||
# underscore and should not include the filename extension.
|
||||
ImportPath:
|
||||
enabled: false
|
||||
|
||||
# Avoid using !important in properties. It is usually indicative of a
|
||||
# misunderstanding of CSS specificity and can lead to brittle code.
|
||||
ImportantRule:
|
||||
enabled: false
|
||||
|
||||
|
|
@ -67,33 +105,51 @@ linters:
|
|||
enabled: true
|
||||
width: 2
|
||||
|
||||
# Don't write leading zeros for numeric values with a decimal point.
|
||||
LeadingZero:
|
||||
enabled: false
|
||||
|
||||
# Reports when you define the same selector twice in a single sheet.
|
||||
MergeableSelector:
|
||||
enabled: false
|
||||
|
||||
# Functions, mixins, variables, and placeholders should be declared
|
||||
# with all lowercase letters and hyphens instead of underscores.
|
||||
NameFormat:
|
||||
enabled: false
|
||||
|
||||
# Avoid nesting selectors too deeply.
|
||||
NestingDepth:
|
||||
enabled: false
|
||||
|
||||
# Always use placeholder selectors in @extend.
|
||||
PlaceholderInExtend:
|
||||
enabled: false
|
||||
|
||||
# Sort properties in a strict order.
|
||||
PropertySortOrder:
|
||||
enabled: false
|
||||
|
||||
# Reports when you use an unknown or disabled CSS property
|
||||
# (ignoring vendor-prefixed properties).
|
||||
PropertySpelling:
|
||||
enabled: false
|
||||
|
||||
# Configure which units are allowed for property values.
|
||||
PropertyUnits:
|
||||
enabled: false
|
||||
|
||||
# Pseudo-elements, like ::before, and ::first-letter, should be declared
|
||||
# with two colons. Pseudo-classes, like :hover and :first-child, should
|
||||
# be declared with one colon.
|
||||
PseudoElement:
|
||||
enabled: false
|
||||
|
||||
# Avoid qualifying elements in selectors (also known as "tag-qualifying").
|
||||
QualifyingElement:
|
||||
enabled: false
|
||||
|
||||
# Don't write selectors with a depth of applicability greater than 3.
|
||||
SelectorDepth:
|
||||
enabled: false
|
||||
|
||||
|
|
@ -113,9 +169,12 @@ linters:
|
|||
enabled: true
|
||||
allow_single_line_rule_sets: true
|
||||
|
||||
# Split selectors onto separate lines after each comma, and have each
|
||||
# individual selector occupy a single line.
|
||||
SingleLinePerSelector:
|
||||
enabled: false
|
||||
|
||||
# Commas in lists should be followed by a space.
|
||||
SpaceAfterComma:
|
||||
enabled: false
|
||||
|
||||
|
|
@ -128,29 +187,75 @@ linters:
|
|||
# colon.
|
||||
SpaceAfterPropertyName:
|
||||
enabled: true
|
||||
|
||||
# Variables should be formatted with a single space separating the colon
|
||||
# from the variable's value.
|
||||
SpaceAfterVariableColon:
|
||||
enabled: false
|
||||
|
||||
# Variables should be formatted with no space between the name and the
|
||||
# colon.
|
||||
SpaceAfterVariableName:
|
||||
enabled: false
|
||||
|
||||
# Operators should be formatted with a single space on both sides of an
|
||||
# infix operator.
|
||||
SpaceAroundOperator:
|
||||
enabled: false
|
||||
|
||||
# Opening braces should be preceded by a single space.
|
||||
SpaceBeforeBrace:
|
||||
enabled: true
|
||||
|
||||
# Parentheses should not be padded with spaces.
|
||||
SpaceBetweenParens:
|
||||
enabled: false
|
||||
|
||||
# Enforces that string literals should be written with a consistent form
|
||||
# of quotes (single or double).
|
||||
StringQuotes:
|
||||
enabled: false
|
||||
|
||||
# Property values, @extend, @include, and @import directives, and variable
|
||||
# declarations should always end with a semicolon.
|
||||
TrailingSemicolon:
|
||||
enabled: false
|
||||
|
||||
# Reports lines containing trailing whitespace.
|
||||
TrailingWhitespace:
|
||||
enabled: false
|
||||
|
||||
# Don't write trailing zeros for numeric values with a decimal point.
|
||||
TrailingZero:
|
||||
enabled: false
|
||||
|
||||
# Don't use the `all` keyword to specify transition properties.
|
||||
TransitionAll:
|
||||
enabled: false
|
||||
|
||||
# Numeric values should not contain unnecessary fractional portions.
|
||||
UnnecessaryMantissa:
|
||||
enabled: false
|
||||
|
||||
# Do not use parent selector references (&) when they would otherwise
|
||||
# be unnecessary.
|
||||
UnnecessaryParentReference:
|
||||
enabled: false
|
||||
|
||||
# URLs should be valid and not contain protocols or domain names.
|
||||
UrlFormat:
|
||||
enabled: false
|
||||
|
||||
# URLs should always be enclosed within quotes.
|
||||
UrlQuotes:
|
||||
enabled: false
|
||||
|
||||
# Properties, like color and font, are easier to read and maintain
|
||||
# when defined using variables rather than literals.
|
||||
VariableForProperty:
|
||||
enabled: false
|
||||
|
||||
# Avoid vendor prefixes. Or rather: don't write them yourself.
|
||||
VendorPrefix:
|
||||
enabled: false
|
||||
|
||||
|
|
|
|||
64
CHANGELOG
64
CHANGELOG
|
|
@ -1,26 +1,63 @@
|
|||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 8.7.0 (unreleased)
|
||||
- All service classes (those residing in app/services) are now instrumented (Yorick Peterse)
|
||||
- Enable gzip for assets, makes the page size significantly smaller. !3544 / !3632 (Connor Shea)
|
||||
- Load award emoji images separately unless opening the full picker. Saves several hundred KBs of data for most pages. (Connor Shea)
|
||||
- All images in discussions and wikis now link to their source files !3464 (Connor Shea).
|
||||
- Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu)
|
||||
- Improved Markdown rendering performance !3389 (Yorick Peterse)
|
||||
- Don't attempt to look up an avatar in repo if repo directory does not exist (Stan hu)
|
||||
- Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu)
|
||||
- Expose project badges in project settings
|
||||
- Preserve time notes/comments have been updated at when moving issue
|
||||
- Make HTTP(s) label consistent on clone bar (Stan Hu)
|
||||
- Expose label description in API (Mariusz Jachimowicz)
|
||||
- Allow back dating on issues when created through the API
|
||||
- Fix Error 500 after renaming a project path (Stan Hu)
|
||||
- Fix avatar stretching by providing a cropping feature
|
||||
- API: Expose `subscribed` for issues and merge requests (Robert Schilling)
|
||||
- Allow SAML to handle external users based on user's information !3530
|
||||
- Add endpoints to archive or unarchive a project !3372
|
||||
- Add links to CI setup documentation from project settings and builds pages
|
||||
- Handle nil descriptions in Slack issue messages (Stan Hu)
|
||||
- API: Expose open_issues_count, closed_issues_count, open_merge_requests_count for labels (Robert Schilling)
|
||||
- Add default scope to projects to exclude projects pending deletion
|
||||
- Ensure empty recipients are rejected in BuildsEmailService
|
||||
- API: Ability to filter milestones by state `active` and `closed` (Robert Schilling)
|
||||
- API: Fix milestone filtering by `iid` (Robert Schilling)
|
||||
- API: Delete notes of issues, snippets, and merge requests (Robert Schilling)
|
||||
- Implement 'Groups View' as an option for dashboard preferences !3379 (Elias W.)
|
||||
- Better errors handling when creating milestones inside groups
|
||||
- Hide `Create a group` help block when creating a new project in a group
|
||||
- Implement 'TODOs View' as an option for dashboard preferences !3379 (Elias W.)
|
||||
- Gracefully handle notes on deleted commits in merge requests (Stan Hu)
|
||||
- Fix creation of merge requests for orphaned branches (Stan Hu)
|
||||
- API: Ability to retrieve a single tag (Robert Schilling)
|
||||
- Fall back to `In-Reply-To` and `References` headers when sub-addressing is not available (David Padilla)
|
||||
- Remove "Congratulations!" tweet button on newly-created project. (Connor Shea)
|
||||
- Fix admin/projects when using visibility levels on search (PotHix)
|
||||
- Build status notifications
|
||||
- API: Expose user location (Robert Schilling)
|
||||
- ClosingIssueExtractor regex now also works with colons. e.g. "Fixes: #1234" !3591
|
||||
- Update number of Todos in the sidebar when it's marked as "Done". !3600
|
||||
- API: Expose 'updated_at' for issue, snippet, and merge request notes (Robert Schilling)
|
||||
- API: User can leave a project through the API when not master or owner. !3613
|
||||
|
||||
v 8.6.6
|
||||
- Fix error on language detection when repository has no HEAD (e.g., master branch). !3654 (Jeroen Bobbeldijk)
|
||||
|
||||
v 8.6.5
|
||||
- Fix importing from GitHub Enterprise. !3529
|
||||
- Perform the language detection after updating merge requests in `GitPushService`, leading to faster visual feedback for the end-user. !3533
|
||||
- Check permissions when user attempts to import members from another project. !3535
|
||||
- Only update repository language if it is not set to improve performance. !3556
|
||||
- Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu). !3583
|
||||
- Unblock user when active_directory is disabled and it can be found !3550
|
||||
- Fix a 2FA authentication spoofing vulnerability.
|
||||
|
||||
v 8.6.4
|
||||
- Don't attempt to fetch any tags from a forked repo (Stan Hu)
|
||||
- Redesign the Labels page
|
||||
|
||||
v 8.6.3
|
||||
- Mentions on confidential issues doesn't create todos for non-members. !3374
|
||||
|
|
@ -128,6 +165,7 @@ v 8.6.0
|
|||
- Add main language of a project in the list of projects (Tiago Botelho)
|
||||
- Add #upcoming filter to Milestone filter (Tiago Botelho)
|
||||
- Add ability to show archived projects on dashboard, explore and group pages
|
||||
- Remove fork link closes all merge requests opened on source project (Florent Baldino)
|
||||
- Move group activity to separate page
|
||||
- Create external users which are excluded of internal and private projects unless access was explicitly granted
|
||||
- Continue parameters are checked to ensure redirection goes to the same instance
|
||||
|
|
@ -136,6 +174,12 @@ v 8.6.0
|
|||
- Trigger a todo for mentions on commits page
|
||||
- Let project owners and admins soft delete issues and merge requests
|
||||
|
||||
v 8.5.10
|
||||
- Fix a 2FA authentication spoofing vulnerability.
|
||||
|
||||
v 8.5.9
|
||||
- Don't attempt to fetch any tags from a forked repo (Stan Hu).
|
||||
|
||||
v 8.5.8
|
||||
- Bump Git version requirement to 2.7.4
|
||||
|
||||
|
|
@ -277,6 +321,15 @@ v 8.5.0
|
|||
- Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul)
|
||||
- Add Todos
|
||||
|
||||
v 8.4.8
|
||||
- Fix a 2FA authentication spoofing vulnerability.
|
||||
|
||||
v 8.4.7
|
||||
- Don't attempt to fetch any tags from a forked repo (Stan Hu).
|
||||
|
||||
v 8.4.6
|
||||
- Bump Git version requirement to 2.7.4
|
||||
|
||||
v 8.4.5
|
||||
- No CE-specific changes
|
||||
|
||||
|
|
@ -390,6 +443,15 @@ v 8.4.0
|
|||
- Add IP check against DNSBLs at account sign-up
|
||||
- Added cache:key to .gitlab-ci.yml allowing to fine tune the caching
|
||||
|
||||
v 8.3.7
|
||||
- Fix a 2FA authentication spoofing vulnerability.
|
||||
|
||||
v 8.3.6
|
||||
- Don't attempt to fetch any tags from a forked repo (Stan Hu).
|
||||
|
||||
v 8.3.5
|
||||
- Bump Git version requirement to 2.7.4
|
||||
|
||||
v 8.3.4
|
||||
- Use gitlab-workhorse 0.5.4 (fixes API routing bug)
|
||||
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ 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. [Testing](https://github.com/thoughtbot/guides/tree/master/style/testing)
|
||||
1. [Testing](doc/development/testing.md)
|
||||
1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style/coffeescript)
|
||||
1. [SCSS styleguide][scss-styleguide]
|
||||
1. [Shell commands](doc/development/shell_commands.md) created by GitLab
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2.7.0
|
||||
2.7.2
|
||||
|
|
|
|||
13
Gemfile
13
Gemfile
|
|
@ -1,6 +1,6 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gem 'rails', '4.2.5.2'
|
||||
gem 'rails', '4.2.6'
|
||||
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
|
||||
|
||||
# Responders respond_to and respond_with
|
||||
|
|
@ -8,7 +8,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.3.5'
|
||||
gem 'sprockets', '~> 3.6.0'
|
||||
|
||||
# Default values for AR models
|
||||
gem "default_value_for", "~> 3.0.0"
|
||||
|
|
@ -149,6 +149,10 @@ gem 'version_sorter', '~> 2.0.0'
|
|||
# Cache
|
||||
gem "redis-rails", '~> 4.0.0'
|
||||
|
||||
# Redis
|
||||
gem 'redis', '~> 3.2'
|
||||
gem 'connection_pool', '~> 2.0'
|
||||
|
||||
# Campfire integration
|
||||
gem 'tinder', '~> 1.10.0'
|
||||
|
||||
|
|
@ -229,14 +233,13 @@ group :metrics do
|
|||
gem 'allocations', '~> 1.0', require: false, platform: :mri
|
||||
gem 'method_source', '~> 0.8', require: false
|
||||
gem 'influxdb', '~> 0.2', require: false
|
||||
gem 'connection_pool', '~> 2.0', require: false
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem "foreman"
|
||||
gem 'brakeman', '~> 3.2.0', require: false
|
||||
|
||||
gem "annotate", "~> 2.6.0"
|
||||
gem "annotate", "~> 2.7.0"
|
||||
gem "letter_opener", '~> 1.1.2'
|
||||
gem 'quiet_assets', '~> 1.0.2'
|
||||
gem 'rerun', '~> 0.11.0'
|
||||
|
|
@ -290,7 +293,7 @@ group :development, :test do
|
|||
gem 'rubocop', '~> 0.38.0', require: false
|
||||
gem 'scss_lint', '~> 0.47.0', require: false
|
||||
gem 'coveralls', '~> 0.8.2', require: false
|
||||
gem 'simplecov', '~> 0.10.0', require: false
|
||||
gem 'simplecov', '~> 0.11.0', require: false
|
||||
gem 'flog', require: false
|
||||
gem 'flay', require: false
|
||||
gem 'bundler-audit', require: false
|
||||
|
|
|
|||
112
Gemfile.lock
112
Gemfile.lock
|
|
@ -4,41 +4,41 @@ GEM
|
|||
CFPropertyList (2.3.2)
|
||||
RedCloth (4.2.9)
|
||||
ace-rails-ap (2.0.1)
|
||||
actionmailer (4.2.5.2)
|
||||
actionpack (= 4.2.5.2)
|
||||
actionview (= 4.2.5.2)
|
||||
activejob (= 4.2.5.2)
|
||||
actionmailer (4.2.6)
|
||||
actionpack (= 4.2.6)
|
||||
actionview (= 4.2.6)
|
||||
activejob (= 4.2.6)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.5.2)
|
||||
actionview (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
actionpack (4.2.6)
|
||||
actionview (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
actionview (4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
activejob (4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
activejob (4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
globalid (>= 0.3.0)
|
||||
activemodel (4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
activemodel (4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.5.2)
|
||||
activemodel (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
activerecord (4.2.6)
|
||||
activemodel (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
arel (~> 6.0)
|
||||
activerecord-deprecated_finders (1.0.4)
|
||||
activerecord-session_store (0.1.2)
|
||||
actionpack (>= 4.0.0, < 5)
|
||||
activerecord (>= 4.0.0, < 5)
|
||||
railties (>= 4.0.0, < 5)
|
||||
activesupport (4.2.5.2)
|
||||
activesupport (4.2.6)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
|
|
@ -51,8 +51,8 @@ GEM
|
|||
activerecord (>= 3.0)
|
||||
akismet (2.0.0)
|
||||
allocations (1.0.4)
|
||||
annotate (2.6.10)
|
||||
activerecord (>= 3.2, <= 4.3)
|
||||
annotate (2.7.0)
|
||||
activerecord (>= 3.2, < 6.0)
|
||||
rake (~> 10.4)
|
||||
arel (6.0.3)
|
||||
asana (0.4.0)
|
||||
|
|
@ -99,7 +99,7 @@ GEM
|
|||
bullet (5.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.9.0)
|
||||
bundler-audit (0.4.0)
|
||||
bundler-audit (0.5.0)
|
||||
bundler (~> 1.2)
|
||||
thor (~> 0.18)
|
||||
byebug (8.2.1)
|
||||
|
|
@ -136,17 +136,16 @@ GEM
|
|||
colorize (0.7.7)
|
||||
concurrent-ruby (1.0.0)
|
||||
connection_pool (2.2.0)
|
||||
coveralls (0.8.9)
|
||||
coveralls (0.8.13)
|
||||
json (~> 1.8)
|
||||
rest-client (>= 1.6.8, < 2)
|
||||
simplecov (~> 0.10.0)
|
||||
simplecov (~> 0.11.0)
|
||||
term-ansicolor (~> 1.3)
|
||||
thor (~> 0.19.1)
|
||||
tins (~> 1.6.0)
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
creole (0.5.0)
|
||||
css_parser (1.3.7)
|
||||
css_parser (1.4.1)
|
||||
addressable
|
||||
d3_rails (3.5.11)
|
||||
railties (>= 3.1.0)
|
||||
|
|
@ -176,8 +175,6 @@ GEM
|
|||
diff-lcs (1.2.5)
|
||||
diffy (3.0.7)
|
||||
docile (1.1.5)
|
||||
domain_name (0.5.25)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
doorkeeper (2.2.2)
|
||||
railties (>= 3.2)
|
||||
dropzonejs-rails (0.7.2)
|
||||
|
|
@ -421,8 +418,6 @@ GEM
|
|||
nokogiri (~> 1.6.0)
|
||||
ruby_parser (~> 3.5)
|
||||
htmlentities (4.3.4)
|
||||
http-cookie (1.0.2)
|
||||
domain_name (~> 0.5)
|
||||
http_parser.rb (0.5.3)
|
||||
httparty (0.13.7)
|
||||
json (~> 1.8)
|
||||
|
|
@ -464,8 +459,8 @@ GEM
|
|||
nokogiri (>= 1.5.9)
|
||||
macaddr (1.7.1)
|
||||
systemu (~> 2.6.2)
|
||||
mail (2.6.3)
|
||||
mime-types (>= 1.16, < 3)
|
||||
mail (2.6.4)
|
||||
mime-types (>= 1.16, < 4)
|
||||
mail_room (0.6.1)
|
||||
method_source (0.8.2)
|
||||
mime-types (1.25.1)
|
||||
|
|
@ -480,7 +475,6 @@ GEM
|
|||
nested_form (0.3.2)
|
||||
net-ldap (0.12.1)
|
||||
net-ssh (3.0.1)
|
||||
netrc (0.11.0)
|
||||
newrelic_rpm (3.14.1.311)
|
||||
nokogiri (1.6.7.2)
|
||||
mini_portile2 (~> 2.0.0.rc2)
|
||||
|
|
@ -565,8 +559,8 @@ GEM
|
|||
premailer (1.8.6)
|
||||
css_parser (>= 1.3.6)
|
||||
htmlentities (>= 4.0.0)
|
||||
premailer-rails (1.9.0)
|
||||
actionmailer (>= 3, < 5)
|
||||
premailer-rails (1.9.2)
|
||||
actionmailer (>= 3, < 6)
|
||||
premailer (~> 1.7, >= 1.7.9)
|
||||
pry (0.10.3)
|
||||
coderay (~> 1.1.0)
|
||||
|
|
@ -595,16 +589,16 @@ GEM
|
|||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.2.5.2)
|
||||
actionmailer (= 4.2.5.2)
|
||||
actionpack (= 4.2.5.2)
|
||||
actionview (= 4.2.5.2)
|
||||
activejob (= 4.2.5.2)
|
||||
activemodel (= 4.2.5.2)
|
||||
activerecord (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
rails (4.2.6)
|
||||
actionmailer (= 4.2.6)
|
||||
actionpack (= 4.2.6)
|
||||
actionview (= 4.2.6)
|
||||
activejob (= 4.2.6)
|
||||
activemodel (= 4.2.6)
|
||||
activerecord (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.5.2)
|
||||
railties (= 4.2.6)
|
||||
sprockets-rails
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
|
|
@ -614,9 +608,9 @@ GEM
|
|||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
railties (4.2.5.2)
|
||||
actionpack (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
railties (4.2.6)
|
||||
actionpack (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.1.0)
|
||||
|
|
@ -657,10 +651,6 @@ GEM
|
|||
listen (~> 3.0)
|
||||
responders (2.1.1)
|
||||
railties (>= 4.2.0, < 5.1)
|
||||
rest-client (1.8.0)
|
||||
http-cookie (>= 1.0.2, < 2.0)
|
||||
mime-types (>= 1.16, < 3.0)
|
||||
netrc (~> 0.7)
|
||||
rinku (1.7.3)
|
||||
rotp (2.1.1)
|
||||
rouge (1.10.1)
|
||||
|
|
@ -754,7 +744,7 @@ GEM
|
|||
rufus-scheduler (>= 2.0.24)
|
||||
sidekiq (>= 4.0.0)
|
||||
simple_oauth (0.1.9)
|
||||
simplecov (0.10.0)
|
||||
simplecov (0.11.2)
|
||||
docile (~> 1.1.0)
|
||||
json (~> 1.8)
|
||||
simplecov-html (~> 0.10.0)
|
||||
|
|
@ -786,12 +776,13 @@ GEM
|
|||
spring (>= 0.9.1)
|
||||
spring-commands-teaspoon (0.0.2)
|
||||
spring (>= 0.9.1)
|
||||
sprockets (3.3.5)
|
||||
sprockets (3.6.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (2.3.3)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (3.0.4)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
state_machines (0.4.0)
|
||||
state_machines-activemodel (0.3.0)
|
||||
activemodel (~> 4.1)
|
||||
|
|
@ -845,7 +836,7 @@ GEM
|
|||
underscore-rails (1.8.3)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.1)
|
||||
unf_ext (0.0.7.2)
|
||||
unicode-display_width (1.0.2)
|
||||
unicorn (4.9.0)
|
||||
kgio (~> 2.6)
|
||||
|
|
@ -897,7 +888,7 @@ DEPENDENCIES
|
|||
after_commit_queue
|
||||
akismet (~> 2.0)
|
||||
allocations (~> 1.0)
|
||||
annotate (~> 2.6.0)
|
||||
annotate (~> 2.7.0)
|
||||
asana (~> 0.4.0)
|
||||
asciidoctor (~> 1.5.2)
|
||||
attr_encrypted (~> 1.3.4)
|
||||
|
|
@ -1002,13 +993,14 @@ DEPENDENCIES
|
|||
rack-attack (~> 4.3.1)
|
||||
rack-cors (~> 0.4.0)
|
||||
rack-oauth2 (~> 1.2.1)
|
||||
rails (= 4.2.5.2)
|
||||
rails (= 4.2.6)
|
||||
rails-deprecated_sanitizer (~> 1.0.3)
|
||||
raphael-rails (~> 2.1.2)
|
||||
rblineprof
|
||||
rdoc (~> 3.6)
|
||||
recaptcha
|
||||
redcarpet (~> 3.3.3)
|
||||
redis (~> 3.2)
|
||||
redis-namespace
|
||||
redis-rails (~> 4.0.0)
|
||||
request_store (~> 1.3.0)
|
||||
|
|
@ -1032,7 +1024,7 @@ DEPENDENCIES
|
|||
shoulda-matchers (~> 2.8.0)
|
||||
sidekiq (~> 4.0)
|
||||
sidekiq-cron (~> 0.4.0)
|
||||
simplecov (~> 0.10.0)
|
||||
simplecov (~> 0.11.0)
|
||||
sinatra (~> 1.4.4)
|
||||
six (~> 0.2.0)
|
||||
slack-notifier (~> 1.2.0)
|
||||
|
|
@ -1042,7 +1034,7 @@ DEPENDENCIES
|
|||
spring-commands-rspec (~> 1.0.4)
|
||||
spring-commands-spinach (~> 1.0.0)
|
||||
spring-commands-teaspoon (~> 0.0.2)
|
||||
sprockets (~> 3.3.5)
|
||||
sprockets (~> 3.6.0)
|
||||
state_machines-activerecord (~> 0.3.0)
|
||||
task_list (~> 1.0.2)
|
||||
teaspoon (~> 1.1.0)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
class @AwardsHandler
|
||||
constructor: (@post_emoji_url, @noteable_type, @noteable_id, @aliases) ->
|
||||
constructor: (@get_emojis_url, @post_emoji_url, @noteable_type, @noteable_id, @aliases) ->
|
||||
$(".js-add-award").on "click", (event) =>
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
|
|
@ -22,8 +22,19 @@ class @AwardsHandler
|
|||
emoji = $(this)
|
||||
.find(".icon")
|
||||
.data "emoji"
|
||||
|
||||
if emoji is "thumbsup" and awards_handler.didUserClickEmoji $(this), "thumbsdown"
|
||||
awards_handler.addAward "thumbsdown"
|
||||
|
||||
else if emoji is "thumbsdown" and awards_handler.didUserClickEmoji $(this), "thumbsup"
|
||||
awards_handler.addAward "thumbsup"
|
||||
|
||||
awards_handler.addAward emoji
|
||||
|
||||
didUserClickEmoji: (that, emoji) ->
|
||||
if $(that).siblings("button:has([data-emoji=#{emoji}])").attr("data-original-title")
|
||||
$(that).siblings("button:has([data-emoji=#{emoji}])").attr("data-original-title").indexOf('me') > -1
|
||||
|
||||
showEmojiMenu: ->
|
||||
if $(".emoji-menu").length
|
||||
if $(".emoji-menu").is ".is-visible"
|
||||
|
|
@ -34,7 +45,7 @@ class @AwardsHandler
|
|||
$("#emoji_search").focus()
|
||||
else
|
||||
$('.js-add-award').addClass "is-loading"
|
||||
$.get "/emojis", (response) =>
|
||||
$.get @get_emojis_url, (response) =>
|
||||
$('.js-add-award').removeClass "is-loading"
|
||||
$(".js-award-holder").append response
|
||||
setTimeout =>
|
||||
|
|
@ -105,7 +116,7 @@ class @AwardsHandler
|
|||
if origTitle
|
||||
authors = origTitle.split(', ')
|
||||
authors.push("me")
|
||||
award_block.attr("title", authors.join(", "))
|
||||
award_block.attr("data-original-title", authors.join(", "))
|
||||
@resetTooltip(award_block)
|
||||
|
||||
resetTooltip: (award) ->
|
||||
|
|
@ -122,7 +133,7 @@ class @AwardsHandler
|
|||
|
||||
nodes = []
|
||||
nodes.push(
|
||||
"<button class='btn award-control js-emoji-btn has-tooltip active' title='me'>",
|
||||
"<button class='btn award-control js-emoji-btn has-tooltip active' data-original-title='me'>",
|
||||
"<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>",
|
||||
"<span class='award-control-text js-counter'>1</span>",
|
||||
"</button>"
|
||||
|
|
|
|||
|
|
@ -35,4 +35,18 @@ $.fn.requiresInput = ->
|
|||
$form.on 'change input', fieldSelector, requireInput
|
||||
|
||||
$ ->
|
||||
$('form.js-requires-input').requiresInput()
|
||||
$form = $('form.js-requires-input')
|
||||
$form.requiresInput()
|
||||
|
||||
# Hide or Show the help block when creating a new project
|
||||
# based on the option selected
|
||||
hideOrShowHelpBlock = (form) ->
|
||||
selected = $('.js-select-namespace option:selected')
|
||||
if selected.length and selected.data('options-parent') is 'groups'
|
||||
return form.find('.help-block').hide()
|
||||
else if selected.length
|
||||
form.find('.help-block').show()
|
||||
|
||||
hideOrShowHelpBlock($form)
|
||||
|
||||
$('.select2.js-select-namespace').change -> hideOrShowHelpBlock($form)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
class @Compare
|
||||
constructor: (@opts) ->
|
||||
@source_loading = $ ".js-source-loading"
|
||||
@target_loading = $ ".js-target-loading"
|
||||
|
||||
$('.js-compare-dropdown').each (i, dropdown) =>
|
||||
$dropdown = $(dropdown)
|
||||
|
||||
$dropdown.glDropdown(
|
||||
selectable: true
|
||||
fieldName: $dropdown.data 'field-name'
|
||||
filterable: true
|
||||
id: (obj, $el) ->
|
||||
$el.data 'id'
|
||||
toggleLabel: (obj, $el) ->
|
||||
$el.text().trim()
|
||||
clicked: (e, el) =>
|
||||
if $dropdown.is '.js-target-branch'
|
||||
@getTargetHtml()
|
||||
else if $dropdown.is '.js-source-branch'
|
||||
@getSourceHtml()
|
||||
else if $dropdown.is '.js-target-project'
|
||||
@getTargetProject()
|
||||
)
|
||||
|
||||
@initialState()
|
||||
|
||||
initialState: ->
|
||||
@getSourceHtml()
|
||||
@getTargetHtml()
|
||||
|
||||
getTargetProject: ->
|
||||
$.ajax(
|
||||
url: @opts.targetProjectUrl
|
||||
data:
|
||||
target_project_id: $("input[name='merge_request[target_project_id]']").val()
|
||||
beforeSend: ->
|
||||
$('.mr_target_commit').empty()
|
||||
success: (html) ->
|
||||
$('.js-target-branch-dropdown .dropdown-content').html html
|
||||
)
|
||||
|
||||
getSourceHtml: ->
|
||||
@sendAjax(@opts.sourceBranchUrl, @source_loading, '.mr_source_commit',
|
||||
ref: $("input[name='merge_request[source_branch]']").val()
|
||||
)
|
||||
|
||||
getTargetHtml: ->
|
||||
@sendAjax(@opts.targetBranchUrl, @target_loading, '.mr_target_commit',
|
||||
target_project_id: $("input[name='merge_request[target_project_id]']").val()
|
||||
ref: $("input[name='merge_request[target_branch]']").val()
|
||||
)
|
||||
|
||||
sendAjax: (url, loading, target, data) ->
|
||||
$target = $(target)
|
||||
|
||||
$.ajax(
|
||||
url: url
|
||||
data: data
|
||||
beforeSend: ->
|
||||
loading.show()
|
||||
$target.empty()
|
||||
success: (html) ->
|
||||
loading.hide()
|
||||
$target.html html
|
||||
$('.js-timeago', $target).timeago()
|
||||
)
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
class GitLabDropdownFilter
|
||||
BLUR_KEYCODES = [27, 40]
|
||||
ARROW_KEY_CODES = [38, 40]
|
||||
HAS_VALUE_CLASS = "has-value"
|
||||
|
||||
constructor: (@input, @options) ->
|
||||
|
|
@ -22,19 +23,23 @@ class GitLabDropdownFilter
|
|||
# Key events
|
||||
timeout = ""
|
||||
@input.on "keyup", (e) =>
|
||||
keyCode = e.which
|
||||
|
||||
return if ARROW_KEY_CODES.indexOf(keyCode) >= 0
|
||||
|
||||
if @input.val() isnt "" and !$inputContainer.hasClass HAS_VALUE_CLASS
|
||||
$inputContainer.addClass HAS_VALUE_CLASS
|
||||
else if @input.val() is "" and $inputContainer.hasClass HAS_VALUE_CLASS
|
||||
$inputContainer.removeClass HAS_VALUE_CLASS
|
||||
|
||||
if e.keyCode is 13 and @input.val() isnt ""
|
||||
if keyCode is 13 and @input.val() isnt ""
|
||||
if @options.enterCallback
|
||||
@options.enterCallback()
|
||||
return
|
||||
|
||||
clearTimeout timeout
|
||||
timeout = setTimeout =>
|
||||
blur_field = @shouldBlur e.keyCode
|
||||
blur_field = @shouldBlur keyCode
|
||||
search_text = @input.val()
|
||||
|
||||
if blur_field and @filterInputBlur
|
||||
|
|
@ -52,14 +57,30 @@ class GitLabDropdownFilter
|
|||
|
||||
filter: (search_text) ->
|
||||
data = @options.data()
|
||||
results = data
|
||||
|
||||
if search_text isnt ""
|
||||
results = fuzzaldrinPlus.filter(data, search_text,
|
||||
key: @options.keys
|
||||
)
|
||||
if data?
|
||||
results = data
|
||||
|
||||
@options.callback results
|
||||
if search_text isnt ''
|
||||
results = fuzzaldrinPlus.filter(data, search_text,
|
||||
key: @options.keys
|
||||
)
|
||||
|
||||
@options.callback results
|
||||
else
|
||||
elements = @options.elements()
|
||||
|
||||
if search_text
|
||||
elements.each ->
|
||||
$el = $(@)
|
||||
matches = fuzzaldrinPlus.match($el.text().trim(), search_text)
|
||||
|
||||
if matches.length
|
||||
$el.show()
|
||||
else
|
||||
$el.hide()
|
||||
else
|
||||
elements.show()
|
||||
|
||||
class GitLabDropdownRemote
|
||||
constructor: (@dataEndpoint, @options) ->
|
||||
|
|
@ -96,6 +117,7 @@ class GitLabDropdown
|
|||
LOADING_CLASS = "is-loading"
|
||||
PAGE_TWO_CLASS = "is-page-two"
|
||||
ACTIVE_CLASS = "is-active"
|
||||
currentIndex = -1
|
||||
|
||||
FILTER_INPUT = '.dropdown-input .dropdown-input-field'
|
||||
|
||||
|
|
@ -117,7 +139,7 @@ class GitLabDropdown
|
|||
if _.isString(@filterInput)
|
||||
@filterInput = @getElement(@filterInput)
|
||||
|
||||
search_fields = if @options.search then @options.search.fields else [];
|
||||
searchFields = if @options.search then @options.search.fields else [];
|
||||
|
||||
if @options.data
|
||||
# If data is an array
|
||||
|
|
@ -141,15 +163,22 @@ class GitLabDropdown
|
|||
filterInputBlur: @filterInputBlur
|
||||
remote: @options.filterRemote
|
||||
query: @options.data
|
||||
keys: @options.search.fields
|
||||
keys: searchFields
|
||||
elements: =>
|
||||
selector = '.dropdown-content li:not(.divider)'
|
||||
|
||||
if @dropdown.find('.dropdown-toggle-page').length
|
||||
selector = ".dropdown-page-one #{selector}"
|
||||
|
||||
return $(selector)
|
||||
data: =>
|
||||
return @fullData
|
||||
callback: (data) =>
|
||||
currentIndex = -1
|
||||
@parseData data
|
||||
@highlightRow 1
|
||||
enterCallback: =>
|
||||
if @enterCallback
|
||||
@selectFirstRow()
|
||||
@selectRowAtIndex 0
|
||||
|
||||
# Event listeners
|
||||
|
||||
|
|
@ -171,10 +200,11 @@ class GitLabDropdown
|
|||
selector = ".dropdown-page-one .dropdown-content a"
|
||||
|
||||
@dropdown.on "click", selector, (e) ->
|
||||
selected = self.rowClicked $(@)
|
||||
$el = $(@)
|
||||
selected = self.rowClicked $el
|
||||
|
||||
if self.options.clicked
|
||||
self.options.clicked(selected)
|
||||
self.options.clicked(selected, $el, e)
|
||||
|
||||
# Finds an element inside wrapper element
|
||||
getElement: (selector) ->
|
||||
|
|
@ -218,6 +248,8 @@ class GitLabDropdown
|
|||
return true
|
||||
|
||||
opened: =>
|
||||
@addArrowKeyEvent()
|
||||
|
||||
contentHtml = $('.dropdown-content', @dropdown).html()
|
||||
if @remote && contentHtml is ""
|
||||
@remote.execute()
|
||||
|
|
@ -228,6 +260,7 @@ class GitLabDropdown
|
|||
@dropdown.trigger('shown.gl.dropdown')
|
||||
|
||||
hidden: (e) =>
|
||||
@removeArrayKeyEvent()
|
||||
if @options.filterable
|
||||
@dropdown
|
||||
.find(".dropdown-input-field")
|
||||
|
|
@ -307,11 +340,11 @@ class GitLabDropdown
|
|||
if @highlight
|
||||
text = @highlightTextMatches(text, @filterInput.val())
|
||||
|
||||
html = "<li>"
|
||||
html += "<a href='#{url}' class='#{cssClass}'>"
|
||||
html += text
|
||||
html += "</a>"
|
||||
html += "</li>"
|
||||
html = "<li>
|
||||
<a href='#{url}' class='#{cssClass}'>
|
||||
#{text}
|
||||
</a>
|
||||
</li>"
|
||||
|
||||
return html
|
||||
|
||||
|
|
@ -322,11 +355,11 @@ class GitLabDropdown
|
|||
).join('')
|
||||
|
||||
noResults: ->
|
||||
html = "<li>"
|
||||
html += "<a class='dropdown-menu-empty-link is-focused'>"
|
||||
html += "No matching results."
|
||||
html += "</a>"
|
||||
html += "</li>"
|
||||
html = "<li class='dropdown-menu-empty-link'>
|
||||
<a href='#' class='is-focused'>
|
||||
No matching results.
|
||||
</a>
|
||||
</li>"
|
||||
|
||||
highlightRow: (index) ->
|
||||
if @filterInput.val() isnt ""
|
||||
|
|
@ -351,6 +384,8 @@ class GitLabDropdown
|
|||
# Toggle the dropdown label
|
||||
if @options.toggleLabel
|
||||
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel
|
||||
else
|
||||
selectedObject
|
||||
else
|
||||
if !value?
|
||||
field.remove()
|
||||
|
|
@ -364,9 +399,9 @@ class GitLabDropdown
|
|||
|
||||
# Toggle the dropdown label
|
||||
if @options.toggleLabel
|
||||
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selectedObject)
|
||||
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selectedObject, el)
|
||||
if value?
|
||||
if !field.length
|
||||
if !field.length and fieldName
|
||||
# Create hidden input for form
|
||||
input = "<input type='hidden' name='#{fieldName}' value='#{value}' />"
|
||||
if @options.inputId?
|
||||
|
|
@ -378,16 +413,81 @@ class GitLabDropdown
|
|||
|
||||
return selectedObject
|
||||
|
||||
selectFirstRow: ->
|
||||
selector = '.dropdown-content li:first-child a'
|
||||
selectRowAtIndex: (index) ->
|
||||
selector = ".dropdown-content li:not(.divider):eq(#{index}) a"
|
||||
|
||||
if @dropdown.find(".dropdown-toggle-page").length
|
||||
selector = ".dropdown-page-one .dropdown-content li:first-child a"
|
||||
selector = ".dropdown-page-one #{selector}"
|
||||
|
||||
# simulate a click on the first link
|
||||
$(selector).trigger "click"
|
||||
$(selector, @dropdown).trigger "click"
|
||||
|
||||
addArrowKeyEvent: ->
|
||||
ARROW_KEY_CODES = [38, 40]
|
||||
$input = @dropdown.find(".dropdown-input-field")
|
||||
|
||||
selector = '.dropdown-content li:not(.divider)'
|
||||
if @dropdown.find(".dropdown-toggle-page").length
|
||||
selector = ".dropdown-page-one #{selector}"
|
||||
|
||||
$('body').on 'keydown', (e) =>
|
||||
currentKeyCode = e.which
|
||||
|
||||
if ARROW_KEY_CODES.indexOf(currentKeyCode) >= 0
|
||||
e.preventDefault()
|
||||
e.stopImmediatePropagation()
|
||||
|
||||
PREV_INDEX = currentIndex
|
||||
$listItems = $(selector, @dropdown)
|
||||
|
||||
# if @options.filterable
|
||||
# $input.blur()
|
||||
|
||||
if currentKeyCode is 40
|
||||
# Move down
|
||||
currentIndex += 1 if currentIndex < ($listItems.length - 1)
|
||||
else if currentKeyCode is 38
|
||||
# Move up
|
||||
currentIndex -= 1 if currentIndex > 0
|
||||
|
||||
@highlightRowAtIndex($listItems, currentIndex) if currentIndex isnt PREV_INDEX
|
||||
|
||||
return false
|
||||
|
||||
if currentKeyCode is 13
|
||||
@selectRowAtIndex currentIndex
|
||||
|
||||
removeArrayKeyEvent: ->
|
||||
$('body').off 'keydown'
|
||||
|
||||
highlightRowAtIndex: ($listItems, index) ->
|
||||
# Remove the class for the previously focused row
|
||||
$('.is-focused', @dropdown).removeClass 'is-focused'
|
||||
|
||||
# Update the class for the row at the specific index
|
||||
$listItem = $listItems.eq(index)
|
||||
$listItem.find('a:first-child').addClass "is-focused"
|
||||
|
||||
# Dropdown content scroll area
|
||||
$dropdownContent = $listItem.closest('.dropdown-content')
|
||||
dropdownScrollTop = $dropdownContent.scrollTop()
|
||||
dropdownContentHeight = $dropdownContent.outerHeight()
|
||||
dropdownContentTop = $dropdownContent.prop('offsetTop')
|
||||
dropdownContentBottom = dropdownContentTop + dropdownContentHeight
|
||||
|
||||
# Get the offset bottom of the list item
|
||||
listItemHeight = $listItem.outerHeight()
|
||||
listItemTop = $listItem.prop('offsetTop')
|
||||
listItemBottom = listItemTop + listItemHeight
|
||||
|
||||
if listItemBottom > dropdownContentBottom + dropdownScrollTop
|
||||
# Scroll the dropdown content down
|
||||
$dropdownContent.scrollTop(listItemBottom - dropdownContentBottom)
|
||||
else if listItemTop < dropdownContentTop + dropdownScrollTop
|
||||
# Scroll the dropdown content up
|
||||
$dropdownContent.scrollTop(listItemTop - dropdownContentTop)
|
||||
|
||||
$.fn.glDropdown = (opts) ->
|
||||
return @.each ->
|
||||
if (!$.data @, 'glDropdown')
|
||||
$.data(@, 'glDropdown', new GitLabDropdown @, opts)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,25 +6,10 @@ class @Issue
|
|||
constructor: ->
|
||||
# Prevent duplicate event bindings
|
||||
@disableTaskList()
|
||||
@fixAffixScroll()
|
||||
if $('a.btn-close').length
|
||||
@initTaskList()
|
||||
@initIssueBtnEventListeners()
|
||||
|
||||
fixAffixScroll: ->
|
||||
fixAffix = ->
|
||||
$discussion = $('.issuable-discussion')
|
||||
$sidebar = $('.issuable-sidebar')
|
||||
if $sidebar.hasClass('no-affix')
|
||||
$sidebar.removeClass(['affix-top','affix'])
|
||||
discussionHeight = $discussion.height()
|
||||
sidebarHeight = $sidebar.height()
|
||||
if sidebarHeight > discussionHeight
|
||||
$discussion.height(sidebarHeight + 50)
|
||||
$sidebar.addClass('no-affix')
|
||||
$(window).on('resize', fixAffix)
|
||||
fixAffix()
|
||||
|
||||
initTaskList: ->
|
||||
$('.detail-page-description .js-task-list-container').taskList('enable')
|
||||
$(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList
|
||||
|
|
@ -49,7 +34,7 @@ class @Issue
|
|||
issueStatus = if isClose then 'close' else 'open'
|
||||
new Flash(issueFailMessage, 'alert')
|
||||
success: (data, textStatus, jqXHR) ->
|
||||
if data.saved
|
||||
if 'id' of data
|
||||
$(document).trigger('issuable:change');
|
||||
if isClose
|
||||
$('a.btn-close').addClass('hidden')
|
||||
|
|
|
|||
|
|
@ -26,6 +26,20 @@
|
|||
|
||||
$(".selected_issue").bind "change", Issues.checkChanged
|
||||
|
||||
# Update state filters if present in page
|
||||
updateStateFilters: ->
|
||||
stateFilters = $('.issues-state-filters')
|
||||
newParams = {}
|
||||
paramKeys = ['author_id', 'label_name', 'milestone_title', 'assignee_id', 'issue_search']
|
||||
|
||||
for paramKey in paramKeys
|
||||
newParams[paramKey] = gl.utils.getUrlParameter(paramKey) or ''
|
||||
|
||||
if stateFilters.length
|
||||
stateFilters.find('a').each ->
|
||||
initialUrl = $(this).attr 'href'
|
||||
$(this).attr 'href', gl.utils.mergeUrlParams(newParams, initialUrl)
|
||||
|
||||
# Make sure we trigger ajax request only after user stop typing
|
||||
initSearch: ->
|
||||
@timer = null
|
||||
|
|
@ -54,6 +68,7 @@
|
|||
# Change url so if user reload a page - search results are saved
|
||||
history.replaceState {page: issuesUrl}, document.title, issuesUrl
|
||||
Issues.reload()
|
||||
Issues.updateStateFilters()
|
||||
dataType: "json"
|
||||
|
||||
checkChanged: ->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
((w) ->
|
||||
|
||||
w.gl ?= {}
|
||||
w.gl.utils ?= {}
|
||||
|
||||
w.gl.utils.getUrlParameter = (sParam) ->
|
||||
sPageURL = decodeURIComponent(window.location.search.substring(1))
|
||||
sURLVariables = sPageURL.split('&')
|
||||
sParameterName = undefined
|
||||
i = 0
|
||||
while i < sURLVariables.length
|
||||
sParameterName = sURLVariables[i].split('=')
|
||||
if sParameterName[0] is sParam
|
||||
return if sParameterName[1] is undefined then true else sParameterName[1]
|
||||
i++
|
||||
|
||||
# #
|
||||
# @param {Object} params - url keys and value to merge
|
||||
# @param {String} url
|
||||
# #
|
||||
w.gl.utils.mergeUrlParams = (params, url) ->
|
||||
newUrl = decodeURIComponent(url)
|
||||
for paramName, paramValue of params
|
||||
pattern = new RegExp "\\b(#{paramName}=).*?(&|$)"
|
||||
if url.search(pattern) >= 0
|
||||
newUrl = newUrl.replace pattern, "$1#{paramValue}$2"
|
||||
else
|
||||
newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}"
|
||||
newUrl
|
||||
|
||||
) window
|
||||
|
|
@ -15,8 +15,6 @@ class @MergeRequest
|
|||
this.$('.show-all-commits').on 'click', =>
|
||||
this.showAllCommits()
|
||||
|
||||
@fixAffixScroll();
|
||||
|
||||
@initTabs()
|
||||
|
||||
# Prevent duplicate event bindings
|
||||
|
|
@ -30,20 +28,6 @@ class @MergeRequest
|
|||
$: (selector) ->
|
||||
this.$el.find(selector)
|
||||
|
||||
fixAffixScroll: ->
|
||||
fixAffix = ->
|
||||
$discussion = $('.issuable-discussion')
|
||||
$sidebar = $('.issuable-sidebar')
|
||||
if $sidebar.hasClass('no-affix')
|
||||
$sidebar.removeClass(['affix-top','affix'])
|
||||
discussionHeight = $discussion.height()
|
||||
sidebarHeight = $sidebar.height()
|
||||
if sidebarHeight > discussionHeight
|
||||
$discussion.height(sidebarHeight + 50)
|
||||
$sidebar.addClass('no-affix')
|
||||
$(window).on('resize', fixAffix)
|
||||
fixAffix()
|
||||
|
||||
initTabs: ->
|
||||
if @opts.action != 'new'
|
||||
# `MergeRequests#new` has no tab-persisting or lazy-loading behavior
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ class @MergeRequestTabs
|
|||
@expandView()
|
||||
else if action == 'diffs'
|
||||
@loadDiff($target.attr('href'))
|
||||
@shrinkView()
|
||||
if bp? and bp.getBreakpointSize() isnt 'lg'
|
||||
@shrinkView()
|
||||
else if action == 'builds'
|
||||
@loadBuilds($target.attr('href'))
|
||||
@expandView()
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ class @MergeRequestWidget
|
|||
@pollCIStatus()
|
||||
notifyPermissions()
|
||||
|
||||
setOpts: (@opts) ->
|
||||
|
||||
mergeInProgress: (deleteSourceBranch = false)->
|
||||
$.ajax
|
||||
type: 'GET'
|
||||
|
|
@ -48,7 +50,7 @@ class @MergeRequestWidget
|
|||
@getCIStatus(true)
|
||||
|
||||
@readyForCICheck = false
|
||||
), 5000
|
||||
), 10000
|
||||
|
||||
getCIStatus: (showNotification) ->
|
||||
_this = @
|
||||
|
|
@ -61,6 +63,10 @@ class @MergeRequestWidget
|
|||
@firstCICheck = false
|
||||
@opts.ci_status = data.status
|
||||
|
||||
if @opts.ci_status is ''
|
||||
@opts.ci_status = data.status
|
||||
return
|
||||
|
||||
if data.status isnt @opts.ci_status
|
||||
@showCIStatus data.status
|
||||
if data.coverage
|
||||
|
|
|
|||
|
|
@ -85,15 +85,21 @@ class @MilestoneSelect
|
|||
# display:block overrides the hide-collapse rule
|
||||
$value.removeAttr('style')
|
||||
clicked: (selected) ->
|
||||
page = $('body').data 'page'
|
||||
isIssueIndex = page is 'projects:issues:index'
|
||||
isMRIndex = page is page is 'projects:merge_requests:index'
|
||||
|
||||
if $dropdown.hasClass 'js-filter-bulk-update'
|
||||
return
|
||||
|
||||
if $dropdown.hasClass('js-filter-submit')
|
||||
if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
|
||||
if selected.name?
|
||||
selectedMilestone = selected.name
|
||||
else
|
||||
selectedMilestone = ''
|
||||
Issues.filterResults $dropdown.closest('form')
|
||||
else if $dropdown.hasClass('js-filter-submit')
|
||||
$dropdown.closest('form').submit()
|
||||
else
|
||||
selected = $selectbox
|
||||
.find('input[type="hidden"]')
|
||||
|
|
|
|||
|
|
@ -251,13 +251,11 @@ class @Notes
|
|||
Sets some hidden fields in the form.
|
||||
###
|
||||
setupMainTargetNoteForm: ->
|
||||
|
||||
# find the form
|
||||
form = $(".js-new-note-form")
|
||||
|
||||
# insert the form after the button
|
||||
form.clone().replaceAll $(".js-main-target-form")
|
||||
form = form.prev("form")
|
||||
# Set a global clone of the form for later cloning
|
||||
@formClone = form.clone()
|
||||
|
||||
# show the form
|
||||
@setupNoteForm(form)
|
||||
|
|
@ -266,9 +264,7 @@ class @Notes
|
|||
form.removeClass "js-new-note-form"
|
||||
form.addClass "js-main-target-form"
|
||||
|
||||
# remove unnecessary fields and buttons
|
||||
form.find("#note_line_code").remove()
|
||||
form.find(".js-close-discussion-note-form").remove()
|
||||
|
||||
###
|
||||
General note form setup.
|
||||
|
|
@ -297,7 +293,14 @@ class @Notes
|
|||
else
|
||||
previewButton.removeClass("turn-on").addClass "turn-off"
|
||||
|
||||
textarea.on 'focus', ->
|
||||
$(this).closest('.md-area').addClass 'is-focused'
|
||||
|
||||
textarea.on 'blur', ->
|
||||
$(this).closest('.md-area').removeClass 'is-focused'
|
||||
|
||||
autosize(textarea)
|
||||
|
||||
new Autosave textarea, [
|
||||
"Note"
|
||||
form.find("#note_commit_id").val()
|
||||
|
|
@ -307,7 +310,6 @@ class @Notes
|
|||
]
|
||||
|
||||
# remove notify commit author checkbox for non-commit notes
|
||||
form.find(".js-notify-commit-author").remove() if form.find("#note_noteable_type").val() isnt "Commit"
|
||||
GitLab.GfmAutoComplete.setup()
|
||||
new DropzoneInput(form)
|
||||
form.show()
|
||||
|
|
@ -455,15 +457,15 @@ class @Notes
|
|||
Shows the note form below the notes.
|
||||
###
|
||||
replyToDiscussionNote: (e) =>
|
||||
form = $(".js-new-note-form")
|
||||
form = @formClone.clone()
|
||||
replyLink = $(e.target).closest(".js-discussion-reply-button")
|
||||
replyLink.hide()
|
||||
|
||||
# insert the form after the button
|
||||
form.clone().insertAfter replyLink
|
||||
replyLink.after form
|
||||
|
||||
# show the form
|
||||
@setupDiscussionNoteForm(replyLink, replyLink.next("form"))
|
||||
@setupDiscussionNoteForm(replyLink, form)
|
||||
|
||||
###
|
||||
Shows the diff or discussion form and does some setup on it.
|
||||
|
|
@ -488,7 +490,9 @@ class @Notes
|
|||
.text(form.find('.js-close-discussion-note-form').data('cancel-text'))
|
||||
@setupNoteForm form
|
||||
form.find(".js-note-text").focus()
|
||||
form.addClass "js-discussion-note-form"
|
||||
form
|
||||
.removeClass('js-main-target-form')
|
||||
.addClass("discussion-form js-discussion-note-form")
|
||||
|
||||
###
|
||||
Called when clicking on the "add a comment" button on the side of a diff line.
|
||||
|
|
@ -498,9 +502,8 @@ class @Notes
|
|||
###
|
||||
addDiffNote: (e) =>
|
||||
e.preventDefault()
|
||||
link = e.currentTarget
|
||||
form = $(".js-new-note-form")
|
||||
row = $(link).closest("tr")
|
||||
$link = $(e.currentTarget)
|
||||
row = $link.closest("tr")
|
||||
nextRow = row.next()
|
||||
hasNotes = nextRow.is(".notes_holder")
|
||||
addForm = false
|
||||
|
|
@ -509,7 +512,7 @@ class @Notes
|
|||
|
||||
# In parallel view, look inside the correct left/right pane
|
||||
if @isParallelView()
|
||||
lineType = $(link).data("lineType")
|
||||
lineType = $link.data("lineType")
|
||||
targetContent += "." + lineType
|
||||
rowCssToAdd = "<tr class=\"notes_holder js-temp-notes-holder\"><td class=\"notes_line\"></td><td class=\"notes_content parallel old\"></td><td class=\"notes_line\"></td><td class=\"notes_content parallel new\"></td></tr>"
|
||||
|
||||
|
|
@ -531,11 +534,11 @@ class @Notes
|
|||
addForm = true
|
||||
|
||||
if addForm
|
||||
newForm = form.clone()
|
||||
newForm = @formClone.clone()
|
||||
newForm.appendTo row.next().find(targetContent)
|
||||
|
||||
# show the form
|
||||
@setupDiscussionNoteForm $(link), newForm
|
||||
@setupDiscussionNoteForm $link, newForm
|
||||
|
||||
###
|
||||
Called in response to "cancel" on a diff note form.
|
||||
|
|
@ -560,7 +563,6 @@ class @Notes
|
|||
|
||||
cancelDiscussionForm: (e) =>
|
||||
e.preventDefault()
|
||||
form = $(".js-new-note-form")
|
||||
form = $(e.target).closest(".js-discussion-note-form")
|
||||
@removeDiscussionNoteForm(form)
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ class @SearchAutocomplete
|
|||
search:
|
||||
fields: ['text']
|
||||
data: @getData.bind(@)
|
||||
selectable: true
|
||||
clicked: @onClick.bind(@)
|
||||
|
||||
getData: (term, callback) ->
|
||||
_this = @
|
||||
|
|
@ -102,6 +104,8 @@ class @SearchAutocomplete
|
|||
lastCategory = suggestion.category
|
||||
|
||||
data.push
|
||||
id: "#{suggestion.category.toLowerCase()}-#{suggestion.id}"
|
||||
category: suggestion.category
|
||||
text: suggestion.label
|
||||
url: suggestion.url
|
||||
|
||||
|
|
@ -133,12 +137,19 @@ class @SearchAutocomplete
|
|||
}
|
||||
|
||||
bindEvents: ->
|
||||
$(document).on 'click', @onDocumentClick
|
||||
@searchInput.on 'keydown', @onSearchInputKeyDown
|
||||
@searchInput.on 'keyup', @onSearchInputKeyUp
|
||||
@searchInput.on 'click', @onSearchInputClick
|
||||
@searchInput.on 'focus', @onSearchInputFocus
|
||||
@searchInput.on 'blur', @onSearchInputBlur
|
||||
@clearInput.on 'click', @onRemoveLocationClick
|
||||
@clearInput.on 'click', @onClearInputClick
|
||||
|
||||
onDocumentClick: (e) =>
|
||||
# If clicking outside the search box
|
||||
# And search input is not focused
|
||||
# And we are not clicking inside a suggestion
|
||||
if not $.contains(@dropdown[0], e.target) and @isFocused and not $(e.target).parents('ul').length
|
||||
@onSearchInputBlur()
|
||||
|
||||
enableAutocomplete: ->
|
||||
# No need to enable anything if user is not logged in
|
||||
|
|
@ -181,6 +192,8 @@ class @SearchAutocomplete
|
|||
# We should display the menu only when input is not empty
|
||||
@enableAutocomplete()
|
||||
|
||||
@wrap.toggleClass 'has-value', !!e.target.value
|
||||
|
||||
# Avoid falsy value to be returned
|
||||
return
|
||||
|
||||
|
|
@ -189,27 +202,20 @@ class @SearchAutocomplete
|
|||
e.stopImmediatePropagation()
|
||||
|
||||
onSearchInputFocus: =>
|
||||
@isFocused = true
|
||||
@wrap.addClass('search-active')
|
||||
|
||||
onRemoveLocationClick: (e) =>
|
||||
onClearInputClick: (e) =>
|
||||
e.preventDefault()
|
||||
@removeLocationBadge()
|
||||
@searchInput.val('').focus()
|
||||
@skipBlurEvent = true
|
||||
|
||||
onSearchInputBlur: (e) =>
|
||||
@skipBlurEvent = false
|
||||
@isFocused = false
|
||||
@wrap.removeClass('search-active')
|
||||
|
||||
# We should wait to make sure we are not clearing the input instead
|
||||
setTimeout( =>
|
||||
return if @skipBlurEvent
|
||||
|
||||
@wrap.removeClass('search-active')
|
||||
|
||||
# If input is blank then restore state
|
||||
if @searchInput.val() is ''
|
||||
@restoreOriginalState()
|
||||
, 150)
|
||||
# If input is blank then restore state
|
||||
if @searchInput.val() is ''
|
||||
@restoreOriginalState()
|
||||
|
||||
addLocationBadge: (item) ->
|
||||
category = if item.category? then "#{item.category}: " else ''
|
||||
|
|
@ -268,3 +274,23 @@ class @SearchAutocomplete
|
|||
<li><a class='dropdown-menu-empty-link is-focused'>Loading...</a></li>
|
||||
</ul>"
|
||||
@dropdownContent.html(html)
|
||||
|
||||
onClick: (item, $el, e) ->
|
||||
if location.pathname.indexOf(item.url) isnt -1
|
||||
e.preventDefault()
|
||||
if not @badgePresent
|
||||
if item.category is 'Projects'
|
||||
@projectInputEl.val(item.id)
|
||||
@addLocationBadge(
|
||||
value: 'This project'
|
||||
)
|
||||
|
||||
if item.category is 'Groups'
|
||||
@groupInputEl.val(item.id)
|
||||
@addLocationBadge(
|
||||
value: 'This group'
|
||||
)
|
||||
|
||||
$el.removeClass('is-active')
|
||||
@disableAutocomplete()
|
||||
@searchInput.val('').focus()
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ expanded = 'page-sidebar-expanded'
|
|||
toggleSidebar = ->
|
||||
$('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
|
||||
$('header').toggleClass("header-collapsed header-expanded")
|
||||
$('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
|
||||
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
|
||||
|
||||
setTimeout ( ->
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ class @Subscription
|
|||
btn = $(event.currentTarget)
|
||||
action = btn.find('span').text()
|
||||
current_status = @subscription_status.attr('data-status')
|
||||
btn.prop('disabled', true)
|
||||
btn.addClass('disabled')
|
||||
|
||||
$.post @url, =>
|
||||
btn.prop('disabled', false)
|
||||
btn.removeClass('disabled')
|
||||
status = if current_status == 'subscribed' then 'unsubscribed' else 'subscribed'
|
||||
@subscription_status.attr('data-status', status)
|
||||
action = if status == 'subscribed' then 'Unsubscribe' else 'Subscribe'
|
||||
|
|
|
|||
|
|
@ -57,5 +57,10 @@ class @Todos
|
|||
$('.todos-pending .badge, .todos-pending-count').text data.count
|
||||
$('.todos-done .badge').text data.done_count
|
||||
|
||||
goToTodoUrl: ->
|
||||
Turbolinks.visit($(this).data('url'))
|
||||
goToTodoUrl: (e)->
|
||||
todoLink = $(this).data('url')
|
||||
if e.metaKey
|
||||
e.preventDefault()
|
||||
window.open(todoLink,'_blank')
|
||||
else
|
||||
Turbolinks.visit(todoLink)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class @ZenMode
|
|||
$(e.currentTarget).trigger('zen_mode:leave')
|
||||
|
||||
$(document).on 'zen_mode:enter', (e) =>
|
||||
@enter(e.target.parentNode)
|
||||
@enter($(e.target).closest('.md-area').find('.zen-backdrop'))
|
||||
$(document).on 'zen_mode:leave', (e) =>
|
||||
@exit()
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
&:focus,
|
||||
&:active {
|
||||
outline: none;
|
||||
background-color: $btn-active-gray;
|
||||
@include box-shadow($gl-btn-active-background);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +28,8 @@
|
|||
color: $color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
&:active,
|
||||
&.active {
|
||||
@include box-shadow ($gl-btn-active-background);
|
||||
|
||||
background-color: $dark;
|
||||
|
|
@ -61,7 +63,7 @@
|
|||
}
|
||||
|
||||
@mixin btn-white {
|
||||
@include btn-color($white-light, $border-white-light, $white-normal, $border-white-normal, $white-dark, $border-white-dark, #313236);
|
||||
@include btn-color($white-light, $border-color, $white-normal, $border-white-normal, $white-dark, $border-white-dark, $btn-white-active);
|
||||
}
|
||||
|
||||
.btn {
|
||||
|
|
@ -218,3 +220,26 @@
|
|||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-text-field {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 6px 16px;
|
||||
border-color: $border-color;
|
||||
color: $btn-placeholder-gray;
|
||||
background-color: $background-color;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
cursor: text;
|
||||
box-shadow: none;
|
||||
border-color: $border-color;
|
||||
color: $btn-placeholder-gray;
|
||||
background-color: $background-color;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-file-option {
|
||||
background: linear-gradient(180deg, $white-light 25%, $gray-light 100%);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
.calender-block {
|
||||
@media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) {
|
||||
overflow-x: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
.user-calendar-activities {
|
||||
.calendar_onclick_hr {
|
||||
padding: 0;
|
||||
|
|
|
|||
|
|
@ -125,13 +125,6 @@ p.time {
|
|||
height: 150px;
|
||||
}
|
||||
|
||||
// Fixes alignment on notes.
|
||||
.new_note {
|
||||
label {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
// Fix issue with notes & lists creating a bunch of bottom borders.
|
||||
li.note {
|
||||
img { max-width: 100% }
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@
|
|||
|
||||
.dropdown-title {
|
||||
position: relative;
|
||||
padding: 0 0 15px;
|
||||
padding: 0 25px 15px;
|
||||
margin: 0 10px 10px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
|
|
@ -275,7 +275,7 @@
|
|||
}
|
||||
|
||||
.dropdown-menu-close {
|
||||
right: 7px;
|
||||
right: 5px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
top: -1px;
|
||||
|
|
|
|||
|
|
@ -15,11 +15,13 @@
|
|||
|
||||
.file-title {
|
||||
position: relative;
|
||||
background: $background-color;
|
||||
background-color: $background-color;
|
||||
border-bottom: 1px solid $border-color;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
padding: 10px $gl-padding;
|
||||
word-wrap: break-word;
|
||||
border-radius: 3px 3px 0 0;
|
||||
|
||||
.file-actions {
|
||||
float: right;
|
||||
|
|
@ -48,7 +50,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
a {
|
||||
a:not(.btn) {
|
||||
color: $gl-dark-link-color;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,15 +33,10 @@
|
|||
background: $color;
|
||||
}
|
||||
|
||||
.complex-sidebar .nav-primary {
|
||||
border-right: 1px solid lighten($color, 3%);
|
||||
}
|
||||
|
||||
.sidebar-wrapper {
|
||||
background: $color-darker;
|
||||
|
||||
.sidebar-user {
|
||||
border-top: 1px solid lighten($color, 3%);
|
||||
background: $color-darker;
|
||||
color: $color-light;
|
||||
|
||||
|
|
@ -67,6 +62,7 @@
|
|||
|
||||
.count {
|
||||
color: $color-light;
|
||||
background: $color-dark;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,11 +123,11 @@ header {
|
|||
}
|
||||
|
||||
@mixin collapsed-header {
|
||||
margin-left: 40px;
|
||||
margin-left: $sidebar_collapsed_width;
|
||||
}
|
||||
|
||||
.header-collapsed {
|
||||
margin-left: 40px;
|
||||
margin-left: $sidebar_collapsed_width;
|
||||
|
||||
@media (min-width: $screen-md-min) {
|
||||
@include collapsed-header;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
.div-dropzone-wrapper {
|
||||
.div-dropzone {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: -5px;
|
||||
|
||||
.div-dropzone-focus {
|
||||
border-color: #66afe9 !important;
|
||||
|
|
@ -25,12 +23,10 @@
|
|||
|
||||
.div-dropzone-spinner {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 100%;
|
||||
margin-top: -1.1em;
|
||||
margin-left: -1.1em;
|
||||
bottom: 10px;
|
||||
right: 5px;
|
||||
opacity: 0;
|
||||
font-size: 30px;
|
||||
font-size: 20px;
|
||||
transition: opacity 200ms ease-in-out;
|
||||
}
|
||||
|
||||
|
|
@ -65,17 +61,30 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.md-header {
|
||||
.nav-links {
|
||||
.active {
|
||||
a {
|
||||
border-bottom-color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
padding-top: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.referenced-users {
|
||||
color: #4c4e54;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.md-preview-holder {
|
||||
background: #fff;
|
||||
border: 1px solid #ddd;
|
||||
min-height: 169px;
|
||||
padding: 5px;
|
||||
box-shadow: none;
|
||||
min-height: 167px;
|
||||
padding: 10px 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.markdown-area {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,17 @@
|
|||
}
|
||||
}
|
||||
|
||||
.nav-search {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
padding: 11px 0;
|
||||
|
||||
/* Small devices (phones, tablets, 768px and lower) */
|
||||
@media (max-width: $screen-sm-min) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@
|
|||
}
|
||||
|
||||
a {
|
||||
padding: 7px 12px;
|
||||
padding: 7px 15px;
|
||||
font-size: $gl-font-size;
|
||||
line-height: 24px;
|
||||
color: $gray;
|
||||
|
|
@ -169,12 +169,10 @@
|
|||
}
|
||||
|
||||
.count {
|
||||
&:before {
|
||||
content: '(';
|
||||
}
|
||||
&:after {
|
||||
content: ')';
|
||||
}
|
||||
float: right;
|
||||
background: #eee;
|
||||
padding: 0 8px;
|
||||
@include border-radius(6px);
|
||||
}
|
||||
|
||||
&.back-link i {
|
||||
|
|
@ -193,27 +191,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.expand-nav a {
|
||||
color: $gl-icon-color;
|
||||
width: 60px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: 20px;
|
||||
background: transparent;
|
||||
height: 59px;
|
||||
text-align: center;
|
||||
line-height: 59px;
|
||||
border-bottom: 1px solid #eee;
|
||||
transition-duration: .3s;
|
||||
outline: none;
|
||||
z-index: 100;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.collapse-nav a {
|
||||
width: $sidebar_width;
|
||||
position: fixed;
|
||||
|
|
@ -233,12 +210,55 @@
|
|||
}
|
||||
|
||||
.page-sidebar-collapsed {
|
||||
padding-left: $sidebar_collapsed_width;
|
||||
|
||||
.sidebar-wrapper {
|
||||
display: none;
|
||||
width: $sidebar_collapsed_width;
|
||||
|
||||
.header-logo {
|
||||
width: $sidebar_collapsed_width;
|
||||
|
||||
a {
|
||||
padding-left: ($sidebar_collapsed_width - 36) / 2;
|
||||
|
||||
.gitlab-text-container {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-sidebar {
|
||||
width: $sidebar_collapsed_width;
|
||||
|
||||
li {
|
||||
width: auto;
|
||||
|
||||
a {
|
||||
span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.collapse-nav a {
|
||||
width: $sidebar_collapsed_width;
|
||||
}
|
||||
|
||||
.sidebar-user {
|
||||
padding-left: ($sidebar_collapsed_width - 36) / 2;
|
||||
width: $sidebar_collapsed_width;
|
||||
|
||||
.username {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-sidebar-expanded {
|
||||
padding-left: $sidebar_collapsed_width;
|
||||
|
||||
@media (min-width: $screen-md-min) {
|
||||
padding-left: $sidebar_width;
|
||||
}
|
||||
|
|
@ -289,48 +309,3 @@
|
|||
padding-right: $sidebar_collapsed_width;
|
||||
}
|
||||
}
|
||||
|
||||
.complex-sidebar {
|
||||
display: inline-block;
|
||||
|
||||
.nav-primary {
|
||||
width: 61px;
|
||||
float: left;
|
||||
height: 100vh;
|
||||
|
||||
.nav-sidebar {
|
||||
width: 60px;
|
||||
|
||||
li a {
|
||||
width: 60px;
|
||||
|
||||
span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-secondary {
|
||||
$nav-secondary-width: 168px;
|
||||
|
||||
float: left;
|
||||
width: $nav-secondary-width;
|
||||
|
||||
.nav-sidebar {
|
||||
width: $nav-secondary-width;
|
||||
|
||||
li {
|
||||
width: $nav-secondary-width;
|
||||
|
||||
a {
|
||||
width: $nav-secondary-width;
|
||||
|
||||
i {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,6 @@
|
|||
background: $row-hover;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
a.no-attachment-icon {
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Link to current header. */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
position: relative;
|
||||
|
|
@ -244,7 +250,7 @@ a > code {
|
|||
* Textareas intended for GFM
|
||||
*
|
||||
*/
|
||||
textarea.js-gfm-input {
|
||||
.js-gfm-input {
|
||||
font-family: $monospace_font;
|
||||
color: $gl-text-color;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ $gutter_inner_width: 258px;
|
|||
/*
|
||||
* UI elements
|
||||
*/
|
||||
$border-color: #efeff1;
|
||||
$border-color: #e5e5e5;
|
||||
$focus-border-color: #3aabf0;
|
||||
$table-border-color: #eef0f2;
|
||||
$background-color: #faf9f9;
|
||||
$background-color: #fafafa;
|
||||
|
||||
/*
|
||||
* Text
|
||||
|
|
@ -81,7 +81,7 @@ $provider-btn-not-active-color: #4688f1;
|
|||
|
||||
$white-light: #fff;
|
||||
$white-normal: #ededed;
|
||||
$white-dark: #ededed;
|
||||
$white-dark: #ececec;
|
||||
|
||||
$gray-light: #faf9f9;
|
||||
$gray-normal: #f5f5f5;
|
||||
|
|
@ -104,9 +104,11 @@ $orange-light: rgba(252, 109, 38, 0.80);
|
|||
$orange-normal: #e75e40;
|
||||
$orange-dark: #ce5237;
|
||||
|
||||
$red-light: #f06559;
|
||||
$red-normal: #e52c5a;
|
||||
$red-dark: #d22852;
|
||||
$red-light: #e52c5a;
|
||||
$red-normal: #d22852;
|
||||
$red-dark: darken($red-normal, 5%);
|
||||
|
||||
$black-transparent: rgba(0, 0, 0, 0.3);
|
||||
|
||||
$border-white-light: #f1f2f4;
|
||||
$border-white-normal: #d6dae2;
|
||||
|
|
@ -128,9 +130,9 @@ $border-orange-light: #fc6d26;
|
|||
$border-orange-normal: #ce5237;
|
||||
$border-orange-dark: #c14e35;
|
||||
|
||||
$border-red-light: #f24f41;
|
||||
$border-red-normal: #d22852;
|
||||
$border-red-dark: #ca264f;
|
||||
$border-red-light: #d22852;
|
||||
$border-red-normal: #ca264f;
|
||||
$border-red-dark: darken($border-red-normal, 5%);
|
||||
|
||||
$help-well-bg: #fafafa;
|
||||
$help-well-border: #e5e5e5;
|
||||
|
|
@ -150,15 +152,22 @@ $gl-success: $green-normal;
|
|||
$gl-info: $blue-normal;
|
||||
$gl-warning: $orange-normal;
|
||||
$gl-danger: $red-normal;
|
||||
$gl-btn-active-background: rgba(0, 0, 0, 0.12);
|
||||
$gl-btn-active-gradient: inset 0 0 4px $gl-btn-active-background;
|
||||
$gl-btn-active-background: rgba(0, 0, 0, 0.16);
|
||||
$gl-btn-active-gradient: inset 0 2px 3px $gl-btn-active-background;
|
||||
|
||||
/*
|
||||
* Commit Diff Colors
|
||||
*/
|
||||
$added: #63c363;
|
||||
$deleted: #f77;
|
||||
|
||||
$line-added: #ecfdf0;
|
||||
$line-added-dark: #c7f0d2;
|
||||
$line-removed: #fbe9eb;
|
||||
$line-removed-dark: #fac5cd;
|
||||
$line-number-old: #f9d7dc;
|
||||
$line-number-new: #ddfbe6;
|
||||
$match-line: #fafafa;
|
||||
$table-border-gray: #f0f0f0;
|
||||
/*
|
||||
* Fonts
|
||||
*/
|
||||
|
|
@ -191,6 +200,13 @@ $dropdown-toggle-hover-border-color: darken($dropdown-toggle-border-color, 15%);
|
|||
$dropdown-toggle-icon-color: #c4c4c4;
|
||||
$dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color;
|
||||
|
||||
/*
|
||||
* Buttons
|
||||
*/
|
||||
$btn-active-gray: #ececec;
|
||||
$btn-placeholder-gray: #c7c7c7;
|
||||
$btn-white-active: #848484;
|
||||
|
||||
/*
|
||||
* Award emoji
|
||||
*/
|
||||
|
|
@ -201,14 +217,14 @@ $award-emoji-new-btn-icon-color: #dcdcdc;
|
|||
/*
|
||||
* Search Box
|
||||
*/
|
||||
$search-input-border-color: $dropdown-input-focus-border;
|
||||
$search-input-border-color: rgba(#4688f1, .8);
|
||||
$search-input-focus-shadow-color: $dropdown-input-focus-shadow;
|
||||
$search-input-width: $dropdown-width;
|
||||
$search-input-width: 244px;
|
||||
$location-badge-color: #aaa;
|
||||
$location-badge-bg: $gray-normal;
|
||||
$location-badge-active-bg: #4f91f8;
|
||||
$location-icon-color: #e7e9ed;
|
||||
$location-active-color: $gl-text-color;
|
||||
$location-active-bg: $search-input-border-color;
|
||||
$location-icon-active-color: #807e7e;
|
||||
|
||||
/*
|
||||
* Notes
|
||||
|
|
@ -217,3 +233,9 @@ $notes-light-color: #8e8e8e;
|
|||
$notes-action-color: #c3c3c3;
|
||||
$notes-role-color: #8e8e8e;
|
||||
$notes-role-border-color: #e4e4e4;
|
||||
|
||||
$note-disabled-comment-color: #b2b2b2;
|
||||
$note-form-border-color: #e5e5e5;
|
||||
$note-toolbar-color: #959494;
|
||||
|
||||
$zen-control-hover-color: #111;
|
||||
|
|
|
|||
|
|
@ -1,61 +1,62 @@
|
|||
.zennable {
|
||||
a.js-zen-enter {
|
||||
color: $gl-gray;
|
||||
position: absolute;
|
||||
.zen-backdrop {
|
||||
&.fullscreen {
|
||||
background-color: white;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 4px;
|
||||
line-height: 56px;
|
||||
}
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1031;
|
||||
|
||||
a.js-zen-leave {
|
||||
display: none;
|
||||
color: $gl-text-color;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
padding: 5px;
|
||||
font-size: 36px;
|
||||
|
||||
&:hover {
|
||||
color: #111;
|
||||
textarea {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
color: #000;
|
||||
font-size: 20px;
|
||||
line-height: 26px;
|
||||
padding: 30px;
|
||||
display: block;
|
||||
outline: none;
|
||||
resize: none;
|
||||
height: 100vh;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.zen-backdrop {
|
||||
&.fullscreen {
|
||||
background-color: white;
|
||||
position: fixed;
|
||||
.zen-control-leave {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1031;
|
||||
|
||||
textarea {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
color: #000;
|
||||
font-size: 20px;
|
||||
line-height: 26px;
|
||||
padding: 30px;
|
||||
display: block;
|
||||
outline: none;
|
||||
resize: none;
|
||||
height: 100vh;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
a.js-zen-enter {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a.js-zen-leave {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.zen-cotrol {
|
||||
padding: 0;
|
||||
color: #555;
|
||||
background: none;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.zen-control-full {
|
||||
color: $note-toolbar-color;
|
||||
|
||||
&:hover {
|
||||
color: $gl-link-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.zen-control-leave {
|
||||
display: none;
|
||||
color: $gl-text-color;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
padding: 5px;
|
||||
font-size: 36px;
|
||||
|
||||
&:hover {
|
||||
color: $zen-control-hover-color;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
|
||||
.diff-line-num, .diff-line-num a {
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
color: $black-transparent;
|
||||
}
|
||||
|
||||
// Code itself
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
}
|
||||
|
||||
.line_content.match {
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
color: $black-transparent;
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
}
|
||||
|
||||
.diff-line-num, .diff-line-num a {
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
color: $black-transparent;
|
||||
}
|
||||
|
||||
// Code itself
|
||||
pre.code, .diff-line-num {
|
||||
border-color: $border-color;
|
||||
border-color: $table-border-gray;
|
||||
}
|
||||
|
||||
&, pre.code, .line_holder .line_content {
|
||||
|
|
@ -23,36 +23,36 @@
|
|||
.line_holder {
|
||||
.diff-line-num {
|
||||
&.old {
|
||||
background: #fdd;
|
||||
border-color: #f1c0c0;
|
||||
background-color: $line-number-old;
|
||||
border-color: $line-removed-dark;
|
||||
}
|
||||
|
||||
&.new {
|
||||
background: #dbffdb;
|
||||
border-color: #c1e9c1;
|
||||
background-color: $line-number-new;
|
||||
border-color: $line-added-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.line_content {
|
||||
&.old {
|
||||
background: #ffecec;
|
||||
background: $line-removed;
|
||||
|
||||
span.idiff {
|
||||
background-color: #f8cbcb;
|
||||
background-color: $line-removed-dark;
|
||||
}
|
||||
}
|
||||
|
||||
&.new {
|
||||
background: #eaffea;
|
||||
background-color: $line-added;
|
||||
|
||||
span.idiff {
|
||||
background-color: #a6f3a6;
|
||||
background-color: $line-added-dark;
|
||||
}
|
||||
}
|
||||
|
||||
&.match {
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
background: #fafafa;
|
||||
color: $black-transparent;
|
||||
background: $match-line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: 10px;
|
||||
word-break: normal;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.commit-info-row {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ li.commit {
|
|||
|
||||
.commit_short_id {
|
||||
min-width: 65px;
|
||||
color: $gl-dark-link-color;
|
||||
font-family: $monospace_font;
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +89,10 @@ li.commit {
|
|||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $gl-dark-link-color;
|
||||
}
|
||||
}
|
||||
|
||||
.commit-row-info {
|
||||
|
|
|
|||
|
|
@ -33,8 +33,12 @@
|
|||
.description {
|
||||
margin-top: 6px;
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
p {
|
||||
overflow-x: auto;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
.diff-file {
|
||||
border: 1px solid $border-color;
|
||||
margin-bottom: $gl-padding;
|
||||
border-radius: 3px;
|
||||
|
||||
.diff-header {
|
||||
position: relative;
|
||||
|
|
@ -10,6 +11,7 @@
|
|||
padding: 10px 16px;
|
||||
color: #555;
|
||||
z-index: 10;
|
||||
border-radius: 3px 3px 0 0;
|
||||
|
||||
.diff-title {
|
||||
font-family: $monospace_font;
|
||||
|
|
@ -31,6 +33,7 @@
|
|||
overflow-y: hidden;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
border-radius: 0 0 3px 3px;
|
||||
|
||||
.unfold {
|
||||
cursor: pointer;
|
||||
|
|
@ -59,9 +62,14 @@
|
|||
border-collapse: separate;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.line_holder td {
|
||||
line-height: $code_line_height;
|
||||
font-size: $code_font_size;
|
||||
|
||||
span {
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +112,10 @@
|
|||
display: table-cell;
|
||||
}
|
||||
}
|
||||
|
||||
.text-file.diff-wrap-lines table .line_holder td span {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
.image {
|
||||
background: #ddd;
|
||||
|
|
@ -316,6 +328,16 @@
|
|||
float: right;
|
||||
}
|
||||
|
||||
.diffs {
|
||||
.content-block {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.files-changed {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
// Mobile
|
||||
@media (max-width: 480px) {
|
||||
.diff-title {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@
|
|||
position: relative;
|
||||
overflow-y: auto;
|
||||
padding: 15px;
|
||||
.form-actions {
|
||||
margin: -$gl-padding+1;
|
||||
}
|
||||
}
|
||||
|
||||
body.modal-open {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,15 @@
|
|||
}
|
||||
|
||||
.label-row {
|
||||
.label-name {
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
|
||||
@media (max-width: $screen-xs-min) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
padding: 9px;
|
||||
font-size: 14px;
|
||||
|
|
@ -69,3 +78,52 @@
|
|||
background-color: $gl-danger;
|
||||
color: $white-light;
|
||||
}
|
||||
|
||||
.manage-labels-list {
|
||||
|
||||
.prepend-left-10 {
|
||||
display: inline-block;
|
||||
width: 40%;
|
||||
vertical-align: middle;
|
||||
|
||||
@media (max-width: $screen-xs-min) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
padding: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.pull-info-right {
|
||||
float: right;
|
||||
|
||||
@media (max-width: $screen-xs-min) {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
border-color: transparent;
|
||||
padding: 6px;
|
||||
color: $gl-text-color;
|
||||
|
||||
&.subscribe-button {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
color: $gl-text-color;
|
||||
}
|
||||
|
||||
.append-right-20 {
|
||||
a {
|
||||
color: $gl-text-color;
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-min) {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@
|
|||
|
||||
.mr_source_commit,
|
||||
.mr_target_commit {
|
||||
margin-bottom: 0;
|
||||
|
||||
.commit {
|
||||
margin: 0;
|
||||
padding: 2px 0;
|
||||
|
|
@ -174,10 +176,6 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.merge-request-form .select2-container {
|
||||
width: 250px !important;
|
||||
}
|
||||
|
||||
#modal_merge_info .modal-dialog {
|
||||
width: 600px;
|
||||
|
||||
|
|
@ -195,44 +193,81 @@
|
|||
line-height: 31px;
|
||||
}
|
||||
|
||||
.disabled-comment-area {
|
||||
padding: 16px 0;
|
||||
|
||||
.disabled-profile {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: $border-gray-dark;
|
||||
border-radius: 20px;
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.disabled-comment {
|
||||
background: $gray-light;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
height: 200px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid $border-gray-normal;
|
||||
padding-top: 90px;
|
||||
text-align: center;
|
||||
right: 20px;
|
||||
position: absolute;
|
||||
left: 70px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
span {
|
||||
color: #b2b2b2;
|
||||
|
||||
a {
|
||||
color: $md-link-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.builds {
|
||||
.table-holder {
|
||||
overflow-x: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-new-merge-request {
|
||||
.panel-heading {
|
||||
padding: 5px 10px;
|
||||
font-weight: 600;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
padding: 10px 5px;
|
||||
}
|
||||
|
||||
.panel-footer {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.commit {
|
||||
.commit-row-title {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.commit-row-info {
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-clipboard {
|
||||
margin-right: 5px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.ci-status-link {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.merge-request-select {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
float: left;
|
||||
width: 50%;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.dropdown-menu-toggle {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.issuable-form-select-holder {
|
||||
display: inline-block;
|
||||
width: 250px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
/**
|
||||
* Note Form
|
||||
*/
|
||||
|
||||
.comment-btn {
|
||||
@extend .btn-create;
|
||||
}
|
||||
.reply-btn {
|
||||
@extend .btn-primary;
|
||||
margin: 10px $gl-padding;
|
||||
}
|
||||
|
||||
.diff-file .diff-content {
|
||||
tr.line_holder:hover > td .line_note_link {
|
||||
opacity: 1.0;
|
||||
|
|
@ -17,16 +13,17 @@
|
|||
}
|
||||
.diff-file,
|
||||
.discussion {
|
||||
.new_note {
|
||||
.new-note {
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
.new_note {
|
||||
|
||||
.new-note {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.new_note, .note-edit-form {
|
||||
.new-note, .note-edit-form {
|
||||
.note-form-actions {
|
||||
margin-top: $gl-padding;
|
||||
}
|
||||
|
|
@ -40,19 +37,16 @@
|
|||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.note_text {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.comment-hints {
|
||||
margin-top: -12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* loading indicator */
|
||||
.notes-busy {
|
||||
margin: 18px;
|
||||
.note-textarea {
|
||||
padding: 10px 0;
|
||||
font-family: $regular_font;
|
||||
border: 0;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.note-image-attach {
|
||||
|
|
@ -62,38 +56,29 @@
|
|||
}
|
||||
|
||||
.common-note-form {
|
||||
margin: 0;
|
||||
background: #fff;
|
||||
padding: $gl-padding;
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
margin-bottom: -$gl-padding;
|
||||
}
|
||||
.md-area {
|
||||
padding: $gl-padding-top $gl-padding;
|
||||
border: 1px solid $note-form-border-color;
|
||||
border-radius: $border-radius-base;
|
||||
|
||||
.note-form-actions {
|
||||
.note-form-option {
|
||||
margin-top: 8px;
|
||||
margin-left: 30px;
|
||||
@extend .pull-left;
|
||||
}
|
||||
&.is-focused {
|
||||
border-color: $focus-border-color;
|
||||
box-shadow: 0 0 2px rgba(#000, .2),
|
||||
0 0 4px rgba($focus-border-color, .4);
|
||||
|
||||
.js-notify-commit-author {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.write-preview-btn {
|
||||
// makes the "absolute" position for links relative to this
|
||||
position: relative;
|
||||
|
||||
// preview/edit buttons
|
||||
> a {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 8px;
|
||||
.comment-toolbar,
|
||||
.nav-links {
|
||||
border-color: $focus-border-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.discussion-form {
|
||||
padding: $gl-padding-top $gl-padding;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.note-edit-form {
|
||||
display: none;
|
||||
font-size: 15px;
|
||||
|
|
@ -128,13 +113,12 @@
|
|||
.discussion-body,
|
||||
.diff-file {
|
||||
.notes .note {
|
||||
border-color: #ddd;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.discussion-reply-holder {
|
||||
background: $background-color;
|
||||
border-top: 1px solid $border-color;
|
||||
background-color: $white-light;
|
||||
padding: 10px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,11 +136,49 @@
|
|||
}
|
||||
}
|
||||
|
||||
.comment-hints {
|
||||
color: #999;
|
||||
background: #fff;
|
||||
padding: 7px;
|
||||
margin-top: -7px;
|
||||
border: 1px solid $border-color;
|
||||
font-size: 13px;
|
||||
.comment-toolbar {
|
||||
padding-top: $gl-padding-top;
|
||||
color: $note-toolbar-color;
|
||||
border-top: 1px solid $border-color;
|
||||
}
|
||||
|
||||
.toolbar-button {
|
||||
padding: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $gl-link-color;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@media (min-width: $screen-md-min) {
|
||||
float: left;
|
||||
margin-right: $gl-padding;
|
||||
|
||||
&:last-child {
|
||||
float: right;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar-button-icon {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
margin-right: 3px;
|
||||
color: inherit;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.toolbar-text {
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
|
||||
@media (min-width: $screen-md-min) {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ ul.notes {
|
|||
|
||||
.timeline-content {
|
||||
margin-left: 55px;
|
||||
|
||||
&.timeline-content-form {
|
||||
@media (max-width: $screen-sm-max) {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.note-created-ago, .note-updated-at {
|
||||
|
|
@ -52,6 +58,7 @@ ul.notes {
|
|||
.note {
|
||||
display: block;
|
||||
position: relative;
|
||||
border-bottom: 1px solid $table-border-gray;
|
||||
|
||||
&.is-editting {
|
||||
.note-header,
|
||||
|
|
@ -76,7 +83,7 @@ ul.notes {
|
|||
// On diffs code should wrap nicely and not overflow
|
||||
pre {
|
||||
code {
|
||||
white-space: pre-wrap;
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -111,9 +118,6 @@ ul.notes {
|
|||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: 1px solid $border-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -131,14 +135,14 @@ ul.notes {
|
|||
font-family: $regular_font;
|
||||
|
||||
td {
|
||||
border: 1px solid #ddd;
|
||||
border: 1px solid $table-border-gray;
|
||||
border-left: none;
|
||||
|
||||
&.notes_line {
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
background: #fff;
|
||||
background: $background-color;
|
||||
color: $text-color;
|
||||
}
|
||||
&.notes_line2 {
|
||||
|
|
@ -149,7 +153,7 @@ ul.notes {
|
|||
&.notes_content {
|
||||
background-color: #fff;
|
||||
border-width: 1px 0;
|
||||
padding-top: 0;
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
&.parallel {
|
||||
border-width: 1px;
|
||||
|
|
@ -169,9 +173,6 @@ ul.notes {
|
|||
}
|
||||
}
|
||||
|
||||
.author_link {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.note-headline-light,
|
||||
|
|
@ -197,14 +198,26 @@ ul.notes {
|
|||
line-height: 24px;
|
||||
|
||||
.fa {
|
||||
color: $notes-action-color;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.fa-trash-o {
|
||||
top: 0;
|
||||
font-size: 16px;
|
||||
&.js-note-delete {
|
||||
i {
|
||||
&:hover {
|
||||
color: $gl-text-red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.js-note-edit {
|
||||
i {
|
||||
&:hover {
|
||||
color: $gl-link-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -281,3 +294,21 @@ ul.notes {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.disabled-comment {
|
||||
margin-left: -$gl-padding-top;
|
||||
margin-right: -$gl-padding-top;
|
||||
background-color: $gray-light;
|
||||
border-radius: $border-radius-base;
|
||||
border: 1px solid $border-gray-normal;
|
||||
color: $note-disabled-comment-color;
|
||||
line-height: 200px;
|
||||
|
||||
.disabled-comment-text {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $gl-link-color;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ pre.light-well {
|
|||
}
|
||||
|
||||
.git-empty {
|
||||
margin: 0 7px;
|
||||
margin: 0 7px 7px;
|
||||
|
||||
h5 {
|
||||
color: #5c5d5e;
|
||||
|
|
@ -401,7 +401,7 @@ pre.light-well {
|
|||
}
|
||||
|
||||
.commit_short_id {
|
||||
margin-right: 5px;
|
||||
margin: 0 5px;
|
||||
color: $gl-link-color;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,25 +135,25 @@
|
|||
|
||||
.location-badge {
|
||||
@include transition(all .15s);
|
||||
background-color: $location-active-bg;
|
||||
background-color: $location-badge-active-bg;
|
||||
color: $white-light;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
i {
|
||||
color: $location-active-color;
|
||||
color: $location-icon-active-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.has-location-badge {
|
||||
.search-icon {
|
||||
display: none;
|
||||
}
|
||||
&.has-value {
|
||||
.search-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.clear-icon {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
.clear-icon {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.container-fluid .content {
|
||||
.container-fluid {
|
||||
.ci-status {
|
||||
padding: 2px 7px;
|
||||
margin-right: 5px;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ class Admin::ProjectsController < Admin::ApplicationController
|
|||
def index
|
||||
@projects = Project.all
|
||||
@projects = @projects.in_namespace(params[:namespace_id]) if params[:namespace_id].present?
|
||||
@projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
|
||||
@projects = @projects.where("projects.visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
|
||||
@projects = @projects.with_push if params[:with_push].present?
|
||||
@projects = @projects.abandoned if params[:abandoned].present?
|
||||
@projects = @projects.where(last_repository_check_failed: true) if params[:last_repository_check_failed].present?
|
||||
|
|
|
|||
|
|
@ -47,6 +47,16 @@ class ApplicationController < ActionController::Base
|
|||
email: current_user.email,
|
||||
username: current_user.username,
|
||||
)
|
||||
|
||||
Raven.tags_context(program: sentry_program_context)
|
||||
end
|
||||
end
|
||||
|
||||
def sentry_program_context
|
||||
if Sidekiq.server?
|
||||
'sidekiq'
|
||||
else
|
||||
'rails'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ class Groups::MilestonesController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
project_ids = params[:milestone][:project_ids]
|
||||
project_ids = params[:milestone][:project_ids].reject(&:blank?)
|
||||
title = milestone_params[:title]
|
||||
|
||||
@projects.where(id: project_ids).each do |project|
|
||||
Milestones::CreateService.new(project, current_user, milestone_params).execute
|
||||
if create_milestones(project_ids)
|
||||
redirect_to milestone_path(title)
|
||||
else
|
||||
render_new_with_error(project_ids.empty?)
|
||||
end
|
||||
|
||||
redirect_to milestone_path(title)
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
@ -41,6 +41,27 @@ class Groups::MilestonesController < Groups::ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def create_milestones(project_ids)
|
||||
return false unless project_ids.present?
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@projects.where(id: project_ids).each do |project|
|
||||
Milestones::CreateService.new(project, current_user, milestone_params).execute
|
||||
end
|
||||
end
|
||||
|
||||
true
|
||||
rescue ActiveRecord::ActiveRecordError => e
|
||||
flash.now[:alert] = "An error occurred while creating the milestone: #{e.message}"
|
||||
false
|
||||
end
|
||||
|
||||
def render_new_with_error(empty_project_ids)
|
||||
@milestone = Milestone.new(milestone_params)
|
||||
@milestone.errors.add(:project_id, "Please select at least one project.") if empty_project_ids
|
||||
render :new
|
||||
end
|
||||
|
||||
def authorize_admin_milestones!
|
||||
return render_404 unless can?(current_user, :admin_milestones, group)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
|||
end
|
||||
else
|
||||
saml_user = Gitlab::Saml::User.new(oauth)
|
||||
saml_user.save
|
||||
saml_user.save if saml_user.changed?
|
||||
@user = saml_user.gl_user
|
||||
|
||||
continue_login_process
|
||||
|
|
|
|||
|
|
@ -68,7 +68,9 @@ class Projects::ApplicationController < ApplicationController
|
|||
end
|
||||
|
||||
def require_non_empty_project
|
||||
redirect_to namespace_project_path(@project.namespace, @project) if @project.empty_repo?
|
||||
# Be sure to return status code 303 to avoid a double DELETE:
|
||||
# http://api.rubyonrails.org/classes/ActionController/Redirecting.html
|
||||
redirect_to namespace_project_path(@project.namespace, @project), status: 303 if @project.empty_repo?
|
||||
end
|
||||
|
||||
def require_branch_head
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
class Projects::BadgesController < Projects::ApplicationController
|
||||
before_action :no_cache_headers
|
||||
layout 'project_settings'
|
||||
before_action :authorize_admin_project!, only: [:index]
|
||||
before_action :no_cache_headers, except: [:index]
|
||||
|
||||
def index
|
||||
@ref = params[:ref] || @project.default_branch || 'master'
|
||||
@build_badge = Gitlab::Badge::Build.new(@project, @ref)
|
||||
end
|
||||
|
||||
def build
|
||||
badge = Gitlab::Badge::Build.new(project, params[:ref])
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class Projects::BranchesController < Projects::ApplicationController
|
|||
respond_to do |format|
|
||||
format.html do
|
||||
redirect_to namespace_project_branches_path(@project.namespace,
|
||||
@project)
|
||||
@project), status: 303
|
||||
end
|
||||
format.js { render status: status[:return_code] }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -207,20 +207,20 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
#This is always source
|
||||
@source_project = @merge_request.nil? ? @project : @merge_request.source_project
|
||||
@commit = @repository.commit(params[:ref]) if params[:ref].present?
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def branch_to
|
||||
@target_project = selected_target_project
|
||||
@commit = @target_project.commit(params[:ref]) if params[:ref].present?
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def update_branches
|
||||
@target_project = selected_target_project
|
||||
@target_branches = @target_project.repository.branch_names
|
||||
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def ci_status
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
|
||||
def destroy
|
||||
if note.editable?
|
||||
note.destroy
|
||||
note.reset_events_cache
|
||||
Notes::DeleteService.new(project, current_user).execute(note)
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
|
|
|
|||
|
|
@ -94,9 +94,14 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def apply_import
|
||||
giver = Project.find(params[:source_project_id])
|
||||
status = @project.team.import(giver, current_user)
|
||||
notice = status ? "Successfully imported" : "Import failed"
|
||||
source_project = Project.find(params[:source_project_id])
|
||||
|
||||
if can?(current_user, :read_project_member, source_project)
|
||||
status = @project.team.import(source_project, current_user)
|
||||
notice = status ? "Successfully imported" : "Import failed"
|
||||
else
|
||||
return render_404
|
||||
end
|
||||
|
||||
redirect_to(namespace_project_project_members_path(project.namespace, project),
|
||||
notice: notice)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ class Projects::RefsController < Projects::ApplicationController
|
|||
namespace_project_find_file_path(@project.namespace, @project, @id)
|
||||
when "graphs_commits"
|
||||
commits_namespace_project_graph_path(@project.namespace, @project, @id)
|
||||
when "badges"
|
||||
namespace_project_badges_path(@project.namespace, @project, ref: @id)
|
||||
else
|
||||
namespace_project_commits_path(@project.namespace, @project, @id)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -88,6 +88,20 @@ class Projects::WikisController < Projects::ApplicationController
|
|||
)
|
||||
end
|
||||
|
||||
def markdown_preview
|
||||
text = params[:text]
|
||||
|
||||
ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user)
|
||||
ext.analyze(text)
|
||||
|
||||
render json: {
|
||||
body: view_context.markdown(text, pipeline: :wiki, project_wiki: @project_wiki),
|
||||
references: {
|
||||
users: ext.users.map(&:username)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def git_access
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ class ProjectsController < Projects::ApplicationController
|
|||
def update
|
||||
status = ::Projects::UpdateService.new(@project, current_user, project_params).execute
|
||||
|
||||
# Refresh the repo in case anything changed
|
||||
@repository = project.repository
|
||||
|
||||
respond_to do |format|
|
||||
if status
|
||||
flash[:notice] = "Project '#{@project.name}' was successfully updated."
|
||||
|
|
@ -71,7 +74,7 @@ class ProjectsController < Projects::ApplicationController
|
|||
def remove_fork
|
||||
return access_denied! unless can?(current_user, :remove_fork_project, @project)
|
||||
|
||||
if @project.unlink_fork
|
||||
if ::Projects::UnlinkForkService.new(@project, current_user).execute
|
||||
flash[:notice] = 'The fork relationship has been removed.'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ class SessionsController < Devise::SessionsController
|
|||
skip_before_action :check_2fa_requirement, only: [:destroy]
|
||||
|
||||
prepend_before_action :check_initial_setup, only: [:new]
|
||||
prepend_before_action :authenticate_with_two_factor, only: [:create]
|
||||
prepend_before_action :authenticate_with_two_factor,
|
||||
if: :two_factor_enabled?, only: [:create]
|
||||
prepend_before_action :store_redirect_path, only: [:new]
|
||||
|
||||
before_action :auto_sign_in_with_provider, only: [:new]
|
||||
|
|
@ -56,10 +57,10 @@ class SessionsController < Devise::SessionsController
|
|||
end
|
||||
|
||||
def find_user
|
||||
if user_params[:login]
|
||||
User.by_login(user_params[:login])
|
||||
elsif user_params[:otp_attempt] && session[:otp_user_id]
|
||||
if session[:otp_user_id]
|
||||
User.find(session[:otp_user_id])
|
||||
elsif user_params[:login]
|
||||
User.by_login(user_params[:login])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -83,11 +84,13 @@ class SessionsController < Devise::SessionsController
|
|||
end
|
||||
end
|
||||
|
||||
def two_factor_enabled?
|
||||
find_user.try(:two_factor_enabled?)
|
||||
end
|
||||
|
||||
def authenticate_with_two_factor
|
||||
user = self.resource = find_user
|
||||
|
||||
return unless user && user.two_factor_enabled?
|
||||
|
||||
if user_params[:otp_attempt].present? && session[:otp_user_id]
|
||||
if valid_otp_attempt?(user)
|
||||
# Remove any lingering user data from login
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ module BlobHelper
|
|||
link_opts)
|
||||
|
||||
if !on_top_of_branch?(project, ref)
|
||||
button_tag "Edit", class: "btn btn-default disabled has-tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
|
||||
button_tag "Edit", class: "btn disabled has-tooltip btn-file-option", title: "You can only edit files when you are on a branch", data: { container: 'body' }
|
||||
elsif can_edit_blob?(blob, project, ref)
|
||||
link_to "Edit", edit_path, class: 'btn'
|
||||
link_to "Edit", edit_path, class: 'btn btn-file-option'
|
||||
elsif can?(current_user, :fork_project, project)
|
||||
continue_params = {
|
||||
to: edit_path,
|
||||
|
|
@ -38,7 +38,7 @@ module BlobHelper
|
|||
}
|
||||
fork_path = namespace_project_forks_path(project.namespace, project, namespace_key: current_user.namespace.id, continue: continue_params)
|
||||
|
||||
link_to "Edit", fork_path, class: 'btn', method: :post
|
||||
link_to "Edit", fork_path, class: 'btn btn-file-option', method: :post
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ module CommitsHelper
|
|||
|
||||
def commit_to_html(commit, project, inline = true)
|
||||
template = inline ? "inline_commit" : "commit"
|
||||
escape_javascript(render "projects/commits/#{template}", commit: commit, project: project) unless commit.nil?
|
||||
render "projects/commits/#{template}", commit: commit, project: project unless commit.nil?
|
||||
end
|
||||
|
||||
# Breadcrumb links for a Project and, if applicable, a tree path
|
||||
|
|
@ -117,7 +117,7 @@ module CommitsHelper
|
|||
end
|
||||
end
|
||||
link_to(
|
||||
"Browse Files »",
|
||||
"Browse Files",
|
||||
namespace_project_tree_path(project.namespace, project, commit),
|
||||
class: "pull-right"
|
||||
)
|
||||
|
|
@ -197,7 +197,7 @@ module CommitsHelper
|
|||
link_to(
|
||||
namespace_project_blob_path(project.namespace, project,
|
||||
tree_join(commit_sha, diff.new_path)),
|
||||
class: 'btn view-file js-view-file'
|
||||
class: 'btn view-file js-view-file btn-file-option'
|
||||
) do
|
||||
raw('View file @') + content_tag(:span, commit_sha[0..6],
|
||||
class: 'commit-short-id')
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ module EventsHelper
|
|||
end
|
||||
|
||||
def event_row_class(event)
|
||||
if event.body? || event.created_project?
|
||||
if event.body?
|
||||
"event-block"
|
||||
else
|
||||
"event-inline"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
module FormHelper
|
||||
def form_errors(model)
|
||||
return unless model.errors.any?
|
||||
|
||||
pluralized = 'error'.pluralize(model.errors.count)
|
||||
headline = "The form contains the following #{pluralized}:"
|
||||
|
||||
content_tag(:div, class: 'alert alert-danger', id: 'error_explanation') do
|
||||
content_tag(:h4, headline) <<
|
||||
content_tag(:ul) do
|
||||
model.errors.full_messages.
|
||||
map { |msg| content_tag(:li, msg) }.
|
||||
join.
|
||||
html_safe
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -116,29 +116,6 @@ module GitlabMarkdownHelper
|
|||
end
|
||||
end
|
||||
|
||||
MARKDOWN_TIPS = [
|
||||
"End a line with two or more spaces for a line-break, or soft-return",
|
||||
"Inline code can be denoted by `surrounding it with backticks`",
|
||||
"Blocks of code can be denoted by three backticks ``` or four leading spaces",
|
||||
"Emoji can be added by :emoji_name:, for example :thumbsup:",
|
||||
"Notify other participants using @user_name",
|
||||
"Notify a specific group using @group_name",
|
||||
"Notify the entire team using @all",
|
||||
"Reference an issue using a hash, for example issue #123",
|
||||
"Reference a merge request using an exclamation point, for example MR !123",
|
||||
"Italicize words or phrases using *asterisks* or _underscores_",
|
||||
"Bold words or phrases using **double asterisks** or __double underscores__",
|
||||
"Strikethrough words or phrases using ~~two tildes~~",
|
||||
"Make a bulleted list using + pluses, - minuses, or * asterisks",
|
||||
"Denote blockquotes using > at the beginning of a line",
|
||||
"Make a horizontal line using three or more hyphens ---, asterisks ***, or underscores ___"
|
||||
].freeze
|
||||
|
||||
# Returns a random markdown tip for use as a textarea placeholder
|
||||
def random_markdown_tip
|
||||
MARKDOWN_TIPS.sample
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Return +text+, truncated to +max_chars+ characters, excluding any HTML
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ module IssuesHelper
|
|||
|
||||
def milestone_options(object)
|
||||
milestones = object.project.milestones.active.reorder(due_date: :asc, title: :asc).to_a
|
||||
milestones.unshift(object.milestone) if object.milestone.present? && object.milestone.closed?
|
||||
milestones.unshift(Milestone::None)
|
||||
|
||||
options_from_collection_for_select(milestones, 'id', 'title', object.milestone_id)
|
||||
|
|
@ -115,17 +116,32 @@ module IssuesHelper
|
|||
icon('eye-slash') if issue.confidential?
|
||||
end
|
||||
|
||||
def emoji_icon(name, unicode = nil, aliases = [])
|
||||
def emoji_icon(name, unicode = nil, aliases = [], sprite: true)
|
||||
unicode ||= Emoji.emoji_filename(name) rescue ""
|
||||
|
||||
content_tag :div, "",
|
||||
class: "icon emoji-icon emoji-#{unicode}",
|
||||
title: name,
|
||||
data: {
|
||||
aliases: aliases.join(' '),
|
||||
emoji: name,
|
||||
unicode_name: unicode
|
||||
}
|
||||
data = {
|
||||
aliases: aliases.join(" "),
|
||||
emoji: name,
|
||||
unicode_name: unicode
|
||||
}
|
||||
|
||||
if sprite
|
||||
# Emoji icons for the emoji menu, these use a spritesheet.
|
||||
content_tag :div, "",
|
||||
class: "icon emoji-icon emoji-#{unicode}",
|
||||
title: name,
|
||||
data: data
|
||||
else
|
||||
# Emoji icons displayed separately, used for the awards already given
|
||||
# to an issue or merge request.
|
||||
content_tag :img, "",
|
||||
class: "icon emoji",
|
||||
title: name,
|
||||
height: "20px",
|
||||
width: "20px",
|
||||
src: url_to_image("#{unicode}.png"),
|
||||
data: data
|
||||
end
|
||||
end
|
||||
|
||||
def emoji_author_list(notes, current_user)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,16 @@ module NamespacesHelper
|
|||
groups = current_user.owned_groups + current_user.masters_groups
|
||||
users = [current_user.namespace]
|
||||
|
||||
group_opts = ["Groups", groups.sort_by(&:human_name).map {|g| [display_path ? g.path : g.human_name, g.id]} ]
|
||||
users_opts = [ "Users", users.sort_by(&:human_name).map {|u| [display_path ? u.path : u.human_name, u.id]} ]
|
||||
data_attr_group = { 'data-options-parent' => 'groups' }
|
||||
data_attr_users = { 'data-options-parent' => 'users' }
|
||||
|
||||
group_opts = [
|
||||
"Groups", groups.sort_by(&:human_name).map { |g| [display_path ? g.path : g.human_name, g.id, data_attr_group] }
|
||||
]
|
||||
|
||||
users_opts = [
|
||||
"Users", users.sort_by(&:human_name).map { |u| [display_path ? u.path : u.human_name, u.id, data_attr_users] }
|
||||
]
|
||||
|
||||
options = []
|
||||
options << group_opts
|
||||
|
|
|
|||
|
|
@ -69,10 +69,7 @@ module NotesHelper
|
|||
line_type: line_type
|
||||
}
|
||||
|
||||
button_tag class: 'btn btn-nr reply-btn js-discussion-reply-button',
|
||||
data: data, title: 'Add a reply' do
|
||||
link_text = icon('comment')
|
||||
link_text << ' Reply'
|
||||
end
|
||||
button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
|
||||
data: data, title: 'Add a reply'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ class MergeRequest < ActiveRecord::Base
|
|||
scope :cared, ->(user) { where('assignee_id = :user OR author_id = :user', user: user.id) }
|
||||
scope :by_milestone, ->(milestone) { where(milestone_id: milestone) }
|
||||
scope :of_projects, ->(ids) { where(target_project_id: ids) }
|
||||
scope :from_project, ->(project) { where(source_project_id: project.id) }
|
||||
scope :merged, -> { with_state(:merged) }
|
||||
scope :closed_and_merged, -> { with_states(:closed, :merged) }
|
||||
|
||||
|
|
|
|||
|
|
@ -931,16 +931,6 @@ class Project < ActiveRecord::Base
|
|||
self.builds_enabled = true
|
||||
end
|
||||
|
||||
def unlink_fork
|
||||
if forked?
|
||||
forked_from_project.lfs_objects.find_each do |lfs_object|
|
||||
lfs_object.projects << self
|
||||
end
|
||||
|
||||
forked_project_link.destroy
|
||||
end
|
||||
end
|
||||
|
||||
def any_runners?(&block)
|
||||
if runners.active.any?(&block)
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -50,12 +50,15 @@ class BuildsEmailService < Service
|
|||
|
||||
def execute(push_data)
|
||||
return unless supported_events.include?(push_data[:object_kind])
|
||||
return unless should_build_be_notified?(push_data)
|
||||
|
||||
if should_build_be_notified?(push_data)
|
||||
recipients = all_recipients(push_data)
|
||||
|
||||
if recipients.any?
|
||||
BuildEmailWorker.perform_async(
|
||||
push_data[:build_id],
|
||||
all_recipients(push_data),
|
||||
push_data,
|
||||
recipients,
|
||||
push_data
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -84,7 +87,7 @@ class BuildsEmailService < Service
|
|||
end
|
||||
|
||||
def all_recipients(data)
|
||||
all_recipients = recipients.split(',')
|
||||
all_recipients = recipients.split(',').compact.reject(&:blank?)
|
||||
|
||||
if add_pusher? && data[:user][:email]
|
||||
all_recipients << "#{data[:user][:email]}"
|
||||
|
|
|
|||
|
|
@ -331,6 +331,8 @@ class Repository
|
|||
# Runs code after a repository has been created.
|
||||
def after_create
|
||||
expire_exists_cache
|
||||
expire_root_ref_cache
|
||||
expire_emptiness_caches
|
||||
end
|
||||
|
||||
# Runs code just before a repository is deleted.
|
||||
|
|
@ -364,6 +366,11 @@ class Repository
|
|||
expire_tag_count_cache
|
||||
end
|
||||
|
||||
def before_import
|
||||
expire_emptiness_caches
|
||||
expire_exists_cache
|
||||
end
|
||||
|
||||
# Runs code after a repository has been forked/imported.
|
||||
def after_import
|
||||
expire_emptiness_caches
|
||||
|
|
@ -889,9 +896,9 @@ class Repository
|
|||
end
|
||||
|
||||
def main_language
|
||||
unless empty?
|
||||
Linguist::Repository.new(rugged, rugged.head.target_id).language
|
||||
end
|
||||
return if empty? || rugged.head_unborn?
|
||||
|
||||
Linguist::Repository.new(rugged, rugged.head.target_id).language
|
||||
end
|
||||
|
||||
def avatar
|
||||
|
|
|
|||
|
|
@ -43,23 +43,27 @@ class GitPushService < BaseService
|
|||
@push_commits = @project.repository.commits_between(params[:oldrev], params[:newrev])
|
||||
process_commit_messages
|
||||
end
|
||||
# Checks if the main language has changed in the project and if so
|
||||
# it updates it accordingly
|
||||
update_main_language
|
||||
# Update merge requests that may be affected by this push. A new branch
|
||||
# could cause the last commit of a merge request to change.
|
||||
update_merge_requests
|
||||
|
||||
# Checks if the main language has changed in the project and if so
|
||||
# it updates it accordingly
|
||||
update_main_language
|
||||
|
||||
perform_housekeeping
|
||||
end
|
||||
|
||||
def update_main_language
|
||||
# Performance can be bad so for now only check main_language once
|
||||
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/14937
|
||||
return if @project.main_language.present?
|
||||
|
||||
return unless is_default_branch?
|
||||
return unless push_to_new_branch? || push_to_existing_branch?
|
||||
|
||||
current_language = @project.repository.main_language
|
||||
|
||||
unless current_language == @project.main_language
|
||||
return @project.update_attributes(main_language: current_language)
|
||||
end
|
||||
|
||||
@project.update_attributes(main_language: current_language)
|
||||
true
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ module Milestones
|
|||
def execute
|
||||
milestone = project.milestones.new(params)
|
||||
|
||||
if milestone.save
|
||||
if milestone.save!
|
||||
event_service.open_milestone(milestone, current_user)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
module Notes
|
||||
class DeleteService < BaseService
|
||||
def execute(note)
|
||||
note.destroy
|
||||
note.reset_events_cache
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -46,6 +46,8 @@ module Projects
|
|||
def import_data
|
||||
return unless has_importer?
|
||||
|
||||
project.repository.before_import
|
||||
|
||||
unless importer.execute
|
||||
raise Error, 'The remote data could not be imported.'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
module Projects
|
||||
class UnlinkForkService < BaseService
|
||||
def execute
|
||||
return unless @project.forked?
|
||||
|
||||
@project.forked_from_project.lfs_objects.find_each do |lfs_object|
|
||||
lfs_object.projects << @project
|
||||
end
|
||||
|
||||
merge_requests = @project.forked_from_project.merge_requests.opened.from_project(@project)
|
||||
|
||||
merge_requests.each do |mr|
|
||||
MergeRequests::CloseService.new(@project, @current_user).execute(mr)
|
||||
end
|
||||
|
||||
@project.forked_project_link.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,11 +3,9 @@
|
|||
%p Please use this form to report users who create spam issues, comments or behave inappropriately.
|
||||
%hr
|
||||
= form_for @abuse_report, html: { class: 'form-horizontal js-quick-submit js-requires-input'} do |f|
|
||||
= form_errors(@abuse_report)
|
||||
|
||||
= f.hidden_field :user_id
|
||||
- if @abuse_report.errors.any?
|
||||
.alert.alert-danger
|
||||
- @abuse_report.errors.full_messages.each do |msg|
|
||||
%p= msg
|
||||
.form-group
|
||||
= f.label :user_id, class: 'control-label'
|
||||
.col-sm-10
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
= form_for @appearance, url: admin_appearances_path, html: { class: 'form-horizontal'} do |f|
|
||||
- if @appearance.errors.any?
|
||||
.alert.alert-danger
|
||||
- @appearance.errors.full_messages.each do |msg|
|
||||
%p= msg
|
||||
= form_errors(@appearance)
|
||||
|
||||
%fieldset.sign-in
|
||||
%legend
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
= form_for @application_setting, url: admin_application_settings_path, html: { class: 'form-horizontal fieldset-form' } do |f|
|
||||
- if @application_setting.errors.any?
|
||||
#error_explanation
|
||||
.alert.alert-danger
|
||||
- @application_setting.errors.full_messages.each do |msg|
|
||||
%p= msg
|
||||
= form_errors(@application_setting)
|
||||
|
||||
%fieldset
|
||||
%legend Visibility and Access Controls
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
= form_for [:admin, @application], url: @url, html: {class: 'form-horizontal', role: 'form'} do |f|
|
||||
- if application.errors.any?
|
||||
.alert.alert-danger
|
||||
%button{ type: "button", class: "close", "data-dismiss" => "alert"} ×
|
||||
- application.errors.full_messages.each do |msg|
|
||||
%p= msg
|
||||
= form_errors(application)
|
||||
|
||||
= content_tag :div, class: 'form-group' do
|
||||
= f.label :name, class: 'col-sm-2 control-label'
|
||||
.col-sm-10
|
||||
|
|
|
|||
|
|
@ -4,10 +4,8 @@
|
|||
= render_broadcast_message(@broadcast_message.message.presence || "Your message here")
|
||||
|
||||
= form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal js-quick-submit js-requires-input'} do |f|
|
||||
-if @broadcast_message.errors.any?
|
||||
.alert.alert-danger
|
||||
- @broadcast_message.errors.full_messages.each do |msg|
|
||||
%p= msg
|
||||
= form_errors(@broadcast_message)
|
||||
|
||||
.form-group
|
||||
= f.label :message, class: 'control-label'
|
||||
.col-sm-10
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
%td
|
||||
- if project
|
||||
= link_to project.name_with_namespace, admin_namespace_project_path(project.namespace, project), class: "monospace"
|
||||
= link_to project.name_with_namespace, admin_namespace_project_path(project.namespace, project)
|
||||
|
||||
%td
|
||||
= link_to build.short_sha, namespace_project_commit_path(build.project.namespace, build.project, build.sha), class: "monospace"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.admin-dashboard
|
||||
.admin-dashboard.prepend-top-default
|
||||
.row
|
||||
.col-md-4
|
||||
%h4 Statistics
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- page_title "Deploy Keys"
|
||||
.panel.panel-default
|
||||
.panel.panel-default.prepend-top-default
|
||||
.panel-heading
|
||||
Public deploy keys (#{@deploy_keys.count})
|
||||
.controls
|
||||
|
|
|
|||
|
|
@ -4,11 +4,7 @@
|
|||
|
||||
%div
|
||||
= form_for [:admin, @deploy_key], html: { class: 'deploy-key-form form-horizontal' } do |f|
|
||||
-if @deploy_key.errors.any?
|
||||
.alert.alert-danger
|
||||
%ul
|
||||
- @deploy_key.errors.full_messages.each do |msg|
|
||||
%li= msg
|
||||
= form_errors(@deploy_key)
|
||||
|
||||
.form-group
|
||||
= f.label :title, class: "control-label"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
= form_for [:admin, @group], html: { class: "form-horizontal" } do |f|
|
||||
- if @group.errors.any?
|
||||
.alert.alert-danger
|
||||
%span= @group.errors.full_messages.first
|
||||
|
||||
= form_errors(@group)
|
||||
= render 'shared/group_form', f: f
|
||||
|
||||
.form-group.group-description-holder
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
- css_class = '' unless local_assigns[:css_class]
|
||||
- css_class += ' no-description' if group.description.blank?
|
||||
|
||||
%li.group-row{ class: css_class }
|
||||
.controls.hidden-xs
|
||||
= link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: 'btn btn-grouped btn-sm'
|
||||
= link_to 'Destroy', [:admin, group], data: {confirm: "REMOVE #{group.name}? Are you sure?"}, method: :delete, class: 'btn btn-grouped btn-sm btn-remove'
|
||||
|
||||
.stats
|
||||
%span
|
||||
= icon('bookmark')
|
||||
= number_with_delimiter(group.projects.count)
|
||||
|
||||
%span
|
||||
= icon('users')
|
||||
= number_with_delimiter(group.users.count)
|
||||
|
||||
%span.visibility-icon.has-tooltip{data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group)}
|
||||
= visibility_level_icon(group.visibility_level, fw: false)
|
||||
|
||||
= image_tag group_icon(group), class: 'avatar s40 hidden-xs'
|
||||
.title
|
||||
= link_to [:admin, group], class: 'group-name' do
|
||||
= group.name
|
||||
|
||||
- if group.description.present?
|
||||
.description
|
||||
= markdown(group.description, pipeline: :description)
|
||||
|
|
@ -1,20 +1,19 @@
|
|||
- page_title "Groups"
|
||||
%h3.page-title
|
||||
Groups (#{number_with_delimiter(@groups.total_count)})
|
||||
= link_to 'New Group', new_admin_group_path, class: "btn btn-new pull-right"
|
||||
|
||||
%p.light
|
||||
Group allows you to keep projects organized.
|
||||
Use groups for uniting related projects.
|
||||
|
||||
%hr
|
||||
= form_tag admin_groups_path, method: :get, class: 'form-inline' do
|
||||
= hidden_field_tag :sort, @sort
|
||||
.form-group
|
||||
= text_field_tag :name, params[:name], class: "form-control"
|
||||
= button_tag "Search", class: "btn submit btn-primary"
|
||||
.top-area
|
||||
.nav-search
|
||||
= form_tag admin_groups_path, method: :get, class: 'form-inline' do
|
||||
= hidden_field_tag :sort, @sort
|
||||
= text_field_tag :name, params[:name], class: "form-control"
|
||||
= button_tag "Search", class: "btn submit btn-primary"
|
||||
|
||||
.pull-right
|
||||
.nav-controls
|
||||
.dropdown.inline
|
||||
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
|
||||
%span.light
|
||||
|
|
@ -33,34 +32,10 @@
|
|||
= sort_title_recently_updated
|
||||
= link_to admin_groups_path(sort: sort_value_oldest_updated) do
|
||||
= sort_title_oldest_updated
|
||||
= link_to 'New Group', new_admin_group_path, class: "btn btn-new"
|
||||
|
||||
%hr
|
||||
|
||||
%ul.bordered-list
|
||||
%ul.content-list
|
||||
- @groups.each do |group|
|
||||
%li
|
||||
.clearfix
|
||||
.pull-right.prepend-top-10
|
||||
= link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-sm"
|
||||
= link_to 'Destroy', [:admin, group], data: {confirm: "REMOVE #{group.name}? Are you sure?"}, method: :delete, class: "btn btn-sm btn-remove"
|
||||
|
||||
%h4
|
||||
= link_to [:admin, group] do
|
||||
%span{ class: visibility_level_color(group.visibility_level) }
|
||||
= visibility_level_icon(group.visibility_level)
|
||||
|
||||
%i.fa.fa-folder
|
||||
= group.name
|
||||
|
||||
→
|
||||
%span.monospace
|
||||
%strong #{group.path}/
|
||||
.clearfix
|
||||
%p
|
||||
= truncate group.description, length: 150
|
||||
.clearfix
|
||||
%p.light
|
||||
#{pluralize(group.members.size, 'member')}, #{pluralize(group.projects.count, 'project')}
|
||||
|
||||
= render 'group', group: group
|
||||
|
||||
= paginate @groups, theme: "gitlab"
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@
|
|||
|
||||
|
||||
= form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-horizontal' } do |f|
|
||||
-if @hook.errors.any?
|
||||
.alert.alert-danger
|
||||
- @hook.errors.full_messages.each do |msg|
|
||||
%p= msg
|
||||
= form_errors(@hook)
|
||||
|
||||
.form-group
|
||||
= f.label :url, "URL:", class: 'control-label'
|
||||
.col-sm-10
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
= form_for [:admin, @user, @identity], html: { class: 'form-horizontal fieldset-form' } do |f|
|
||||
- if @identity.errors.any?
|
||||
#error_explanation
|
||||
.alert.alert-danger
|
||||
- @identity.errors.full_messages.each do |msg|
|
||||
%p= msg
|
||||
= form_errors(@identity)
|
||||
|
||||
.form-group
|
||||
= f.label :provider, class: 'control-label'
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
= form_for [:admin, @label], html: { class: 'form-horizontal label-form js-requires-input' } do |f|
|
||||
-if @label.errors.any?
|
||||
.row
|
||||
.col-sm-offset-2.col-sm-10
|
||||
.alert.alert-danger
|
||||
- @label.errors.full_messages.each do |msg|
|
||||
%span= msg
|
||||
%br
|
||||
= form_errors(@label)
|
||||
|
||||
.form-group
|
||||
= f.label :title, class: 'control-label'
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
- page_title "Labels"
|
||||
= link_to new_admin_label_path, class: "pull-right btn btn-nr btn-new" do
|
||||
New label
|
||||
%h3.page-title
|
||||
Labels
|
||||
|
||||
%div
|
||||
= link_to new_admin_label_path, class: "pull-right btn btn-nr btn-new" do
|
||||
New label
|
||||
%h3.page-title
|
||||
Labels
|
||||
%hr
|
||||
|
||||
.labels
|
||||
|
|
@ -13,4 +15,4 @@
|
|||
- else
|
||||
.light-well
|
||||
.nothing-here-block There are no labels yet
|
||||
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue