Commit d29c816d authored by James Lopez's avatar James Lopez

Merge branch 'feature/project-export' of gitlab.com:gitlab-org/gitlab-ce into...

Merge branch 'feature/project-export' of gitlab.com:gitlab-org/gitlab-ce into feature/project-import
parents b0f34fb0 5d642fb7
{ {
"always-semicolon": true, "exclude": [
"color-case": "lower", "app/assets/stylesheets/framework/tw_bootstrap_variables.scss",
"block-indent": " ", "app/assets/stylesheets/framework/fonts.scss"
"color-shorthand": true, ],
"element-case": "lower", "always-semicolon": true,
"space-before-colon": "", "color-case": "lower",
"space-after-colon": " ", "block-indent": " ",
"space-before-combinator": " ", "color-shorthand": true,
"space-after-combinator": " ", "element-case": "lower",
"space-between-declarations": "\n", "space-before-colon": "",
"space-before-opening-brace": " ", "space-after-colon": " ",
"space-after-opening-brace": "\n", "space-before-combinator": " ",
"space-before-closing-brace": "\n", "space-after-combinator": " ",
"unitless-zero": true "space-between-declarations": "\n",
"space-before-opening-brace": " ",
"space-after-opening-brace": "\n",
"space-before-closing-brace": "\n",
"unitless-zero": true
} }
...@@ -2,7 +2,6 @@ image: "ruby:2.1" ...@@ -2,7 +2,6 @@ image: "ruby:2.1"
services: services:
- mysql:latest - mysql:latest
- postgres:latest
- redis:latest - redis:latest
cache: cache:
...@@ -35,135 +34,86 @@ spec:feature: ...@@ -35,135 +34,86 @@ spec:feature:
script: script:
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null - RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature
tags:
- ruby
- mysql
spec:api: spec:api:
stage: test stage: test
script: script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:api - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:api
tags:
- ruby
- mysql
spec:models: spec:models:
stage: test stage: test
script: script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models
tags:
- ruby
- mysql
spec:lib: spec:lib:
stage: test stage: test
script: script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib
tags:
- ruby
- mysql
spec:services: spec:services:
stage: test stage: test
script: script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services
tags:
- ruby
- mysql
spec:other: spec:other:
stage: test stage: test
script: script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:other - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:other
tags:
- ruby
- mysql
spinach:project:half: spinach:project:half:
stage: test stage: test
script: script:
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null - RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half - RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half
tags:
- ruby
- mysql
spinach:project:rest: spinach:project:rest:
stage: test stage: test
script: script:
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null - RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest - RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest
tags:
- ruby
- mysql
spinach:other: spinach:other:
stage: test stage: test
script: script:
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null - RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:other - RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:other
tags:
- ruby
- mysql
teaspoon: teaspoon:
stage: test stage: test
script: script:
- RAILS_ENV=test bundle exec teaspoon - RAILS_ENV=test bundle exec teaspoon
tags:
- ruby
- mysql
rubocop: rubocop:
stage: test stage: test
script: script:
- bundle exec rubocop - bundle exec rubocop
tags:
- ruby
- mysql
scss-lint: scss-lint:
stage: test stage: test
script: script:
- bundle exec rake scss_lint - bundle exec rake scss_lint
tags:
- ruby
allow_failure: true
brakeman: brakeman:
stage: test stage: test
script: script:
- bundle exec rake brakeman - bundle exec rake brakeman
tags:
- ruby
- mysql
flog: flog:
stage: test stage: test
script: script:
- bundle exec rake flog - bundle exec rake flog
tags:
- ruby
- mysql
flay: flay:
stage: test stage: test
script: script:
- bundle exec rake flay - bundle exec rake flay
tags:
- ruby
- mysql
bundler:audit: bundler:audit:
stage: test stage: test
only: only:
- master - master
script: script:
- "bundle exec bundle-audit update" - "bundle exec bundle-audit check --update --ignore OSVDB-115941"
- "bundle exec bundle-audit check --ignore OSVDB-115941"
tags:
- ruby
- mysql
# Ruby 2.2 jobs # Ruby 2.2 jobs
...@@ -179,9 +129,6 @@ spec:feature:ruby22: ...@@ -179,9 +129,6 @@ spec:feature:ruby22:
key: "ruby22" key: "ruby22"
paths: paths:
- vendor - vendor
tags:
- ruby
- mysql
spec:api:ruby22: spec:api:ruby22:
stage: test stage: test
...@@ -194,9 +141,6 @@ spec:api:ruby22: ...@@ -194,9 +141,6 @@ spec:api:ruby22:
key: "ruby22" key: "ruby22"
paths: paths:
- vendor - vendor
tags:
- ruby
- mysql
spec:models:ruby22: spec:models:ruby22:
stage: test stage: test
...@@ -209,9 +153,6 @@ spec:models:ruby22: ...@@ -209,9 +153,6 @@ spec:models:ruby22:
key: "ruby22" key: "ruby22"
paths: paths:
- vendor - vendor
tags:
- ruby
- mysql
spec:lib:ruby22: spec:lib:ruby22:
stage: test stage: test
...@@ -224,9 +165,6 @@ spec:lib:ruby22: ...@@ -224,9 +165,6 @@ spec:lib:ruby22:
key: "ruby22" key: "ruby22"
paths: paths:
- vendor - vendor
tags:
- ruby
- mysql
spec:services:ruby22: spec:services:ruby22:
stage: test stage: test
...@@ -239,9 +177,6 @@ spec:services:ruby22: ...@@ -239,9 +177,6 @@ spec:services:ruby22:
key: "ruby22" key: "ruby22"
paths: paths:
- vendor - vendor
tags:
- ruby
- mysql
spec:other:ruby22: spec:other:ruby22:
stage: test stage: test
...@@ -254,9 +189,6 @@ spec:other:ruby22: ...@@ -254,9 +189,6 @@ spec:other:ruby22:
key: "ruby22" key: "ruby22"
paths: paths:
- vendor - vendor
tags:
- ruby
- mysql
spinach:project:half:ruby22: spinach:project:half:ruby22:
stage: test stage: test
...@@ -270,9 +202,6 @@ spinach:project:half:ruby22: ...@@ -270,9 +202,6 @@ spinach:project:half:ruby22:
key: "ruby22" key: "ruby22"
paths: paths:
- vendor - vendor
tags:
- ruby
- mysql
spinach:project:rest:ruby22: spinach:project:rest:ruby22:
stage: test stage: test
...@@ -286,9 +215,6 @@ spinach:project:rest:ruby22: ...@@ -286,9 +215,6 @@ spinach:project:rest:ruby22:
key: "ruby22" key: "ruby22"
paths: paths:
- vendor - vendor
tags:
- ruby
- mysql
spinach:other:ruby22: spinach:other:ruby22:
stage: test stage: test
...@@ -302,10 +228,6 @@ spinach:other:ruby22: ...@@ -302,10 +228,6 @@ spinach:other:ruby22:
key: "ruby22" key: "ruby22"
paths: paths:
- vendor - vendor
tags:
- ruby
- mysql
notify:slack: notify:slack:
stage: notifications stage: notifications
......
...@@ -7,21 +7,44 @@ exclude: ...@@ -7,21 +7,44 @@ exclude:
- 'app/assets/stylesheets/pages/emojis.scss' - 'app/assets/stylesheets/pages/emojis.scss'
linters: linters:
# Reports when you use improper spacing around ! (the "bang") in !default,
# !global, !important, and !optional flags.
BangFormat: BangFormat:
enabled: false enabled: false
# Whether or not to prefer `border: 0` over `border: none`.
BorderZero: BorderZero:
enabled: false 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: ColorKeyword:
enabled: false 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: ColorVariable:
enabled: false enabled: false
# Which form of comments to prefer in CSS.
Comment: Comment:
enabled: false 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: DeclarationOrder:
enabled: false enabled: false
...@@ -32,15 +55,25 @@ linters: ...@@ -32,15 +55,25 @@ linters:
DisableLinterReason: DisableLinterReason:
enabled: true enabled: true
# Reports when you define the same property twice in a single rule set.
DuplicateProperty: DuplicateProperty:
enabled: false enabled: false
# Separate rule, function, and mixin declarations with empty lines.
EmptyLineBetweenBlocks: EmptyLineBetweenBlocks:
enabled: false enabled: false
# Reports when you have an empty rule set.
EmptyRule: EmptyRule:
enabled: false 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: FinalNewline:
enabled: false enabled: false
...@@ -53,12 +86,17 @@ linters: ...@@ -53,12 +86,17 @@ linters:
HexNotation: HexNotation:
enabled: true enabled: true
# Avoid using ID selectors.
IdSelector: IdSelector:
enabled: false enabled: false
# The basenames of @imported SCSS partials should not begin with an
# underscore and should not include the filename extension.
ImportPath: ImportPath:
enabled: false enabled: false
# Avoid using !important in properties. It is usually indicative of a
# misunderstanding of CSS specificity and can lead to brittle code.
ImportantRule: ImportantRule:
enabled: false enabled: false
...@@ -67,40 +105,58 @@ linters: ...@@ -67,40 +105,58 @@ linters:
enabled: true enabled: true
width: 2 width: 2
# Don't write leading zeros for numeric values with a decimal point.
LeadingZero: LeadingZero:
enabled: false enabled: false
# Reports when you define the same selector twice in a single sheet.
MergeableSelector: MergeableSelector:
enabled: false enabled: false
# Functions, mixins, variables, and placeholders should be declared
# with all lowercase letters and hyphens instead of underscores.
NameFormat: NameFormat:
enabled: false enabled: false
# Avoid nesting selectors too deeply.
NestingDepth: NestingDepth:
enabled: false enabled: false
# Always use placeholder selectors in @extend.
PlaceholderInExtend: PlaceholderInExtend:
enabled: false enabled: false
# Sort properties in a strict order.
PropertySortOrder: PropertySortOrder:
enabled: false enabled: false
# Reports when you use an unknown or disabled CSS property
# (ignoring vendor-prefixed properties).
PropertySpelling: PropertySpelling:
enabled: false 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: PseudoElement:
enabled: false enabled: false
# Avoid qualifying elements in selectors (also known as "tag-qualifying").
QualifyingElement: QualifyingElement:
enabled: false enabled: false
# Don't write selectors with a depth of applicability greater than 3.
SelectorDepth: SelectorDepth:
enabled: false enabled: false
# Selectors should always use hyphenated-lowercase, rather than camelCase or # Selectors should always use hyphenated-lowercase, rather than camelCase or
# snake_case. # snake_case.
SelectorFormat: SelectorFormat:
enabled: true enabled: false
convention: hyphenated_lowercase convention: hyphenated_lowercase
# Prefer the shortest shorthand form possible for properties that support it. # Prefer the shortest shorthand form possible for properties that support it.
...@@ -113,9 +169,12 @@ linters: ...@@ -113,9 +169,12 @@ linters:
enabled: true enabled: true
allow_single_line_rule_sets: 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: SingleLinePerSelector:
enabled: false enabled: false
# Commas in lists should be followed by a space.
SpaceAfterComma: SpaceAfterComma:
enabled: false enabled: false
...@@ -128,28 +187,75 @@ linters: ...@@ -128,28 +187,75 @@ linters:
# colon. # colon.
SpaceAfterPropertyName: SpaceAfterPropertyName:
enabled: true 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: SpaceAroundOperator:
enabled: false enabled: false
# Opening braces should be preceded by a single space.
SpaceBeforeBrace: SpaceBeforeBrace:
enabled: true
# Parentheses should not be padded with spaces.
SpaceBetweenParens:
enabled: false enabled: false
# Enforces that string literals should be written with a consistent form
# of quotes (single or double).
StringQuotes: StringQuotes:
enabled: false enabled: false
# Property values, @extend, @include, and @import directives, and variable
# declarations should always end with a semicolon.
TrailingSemicolon: TrailingSemicolon:
enabled: false enabled: false
# Reports lines containing trailing whitespace.
TrailingWhitespace: TrailingWhitespace:
enabled: false 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: UnnecessaryMantissa:
enabled: false enabled: false
# Do not use parent selector references (&) when they would otherwise
# be unnecessary.
UnnecessaryParentReference: UnnecessaryParentReference:
enabled: false 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: VendorPrefix:
enabled: false enabled: false
......
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.6.0 (unreleased) v 8.7.0 (unreleased)
- Fix bug where wrong commit ID was being used in a merge request diff to show old image (Stan Hu) - All images in discussions and wikis now link to their source files !3464 (Connor Shea).
- 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)
- Preserve time notes/comments have been updated at when moving issue
- Make HTTP(s) label consistent on clone bar (Stan Hu) - 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
- 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)
- Add default scope to projects to exclude projects pending deletion
- Ensure empty recipients are rejected in BuildsEmailService
- Implement 'Groups View' as an option for dashboard preferences !3379 (Elias W.)
- 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)
- 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)
- Improved UX of the navigation sidebar
- Build status notifications
- API: Ability to retrieve a specific tag (Robert Schilling)
- API: Expose user location (Robert Schilling)
v 8.6.5 (unreleased)
- Check permissions when user attempts to import members from another project
v 8.6.4
- Don't attempt to fetch any tags from a forked repo (Stan Hu)
v 8.6.3
- Mentions on confidential issues doesn't create todos for non-members. !3374
- Destroy related todos when an Issue/MR is deleted. !3376
- Fix error 500 when target is nil on todo list. !3376
- Fix copying uploads when moving issue to another project. !3382
- Ensuring Merge Request API returns boolean values for work_in_progress (Abhi Rao). !3432
- Fix raw/rendered diff producing different results on merge requests. !3450
- Fix commit comment alignment (Stan Hu). !3466
- Fix Error 500 when searching for a comment in a project snippet. !3468
- Allow temporary email as notification email. !3477
- Fix issue with dropdowns not selecting values. !3478
- Update gitlab-shell version and doc to 2.6.12. gitlab-org/gitlab-ee!280
v 8.6.2
- Fix dropdown alignment. !3298
- Fix issuable sidebar overlaps on tablet. !3299
- Make dropdowns pixel perfect. !3337
- Fix order of steps to prevent PostgreSQL errors when running migration. !3355
- Fix bold text in issuable sidebar. !3358
- Fix error with anonymous token in applications settings. !3362
- Fix the milestone 'upcoming' filter. !3364 + !3368
- Fix comments on confidential issues showing up in activity feed to non-members. !3375
- Fix `NoMethodError` when visiting CI root path at `/ci`. !3377
- Add a tooltip to new branch button in issue page. !3380
- Fix an issue hiding the password form when signed-in with a linked account. !3381
- Add links to CI setup documentation from project settings and builds pages. !3384
- Fix an issue with width of project select dropdown. !3386
- Remove redundant `require`s from Banzai files. !3391
- Fix error 500 with cancel button on issuable edit form. !3392 + !3417
- Fix background when editing a highlighted note. !3423
- Remove tabstop from the WIP toggle links. !3426
- Ensure private project snippets are not viewable by unauthorized people.
- Gracefully handle notes on deleted commits in merge requests (Stan Hu). !3402
- Fixed issue with notification settings not saving. !3452
v 8.6.1
- Add option to reload the schema before restoring a database backup. !2807
- Display navigation controls on mobile. !3214
- Fixed bug where participants would not work correctly on merge requests. !3329
- Fix sorting issues by votes on the groups issues page results in SQL errors. !3333
- Restrict notifications for confidential issues. !3334
- Do not allow to move issue if it has not been persisted. !3340
- Add a confirmation step before deleting an issuable. !3341
- Fixes issue with signin button overflowing on mobile. !3342
- Auto collapses the navigation sidebar when resizing. !3343
- Fix build dependencies, when the dependency is a string. !3344
- Shows error messages when trying to create label in dropdown menu. !3345
- Fixes issue with assign milestone not loading milestone list. !3346
- Fix an issue causing the Dashboard/Milestones page to be blank. !3348
v 8.6.0
- Add ability to move issue to another project
- Prevent tokens in the import URL to be showed by the UI
- Fix bug where wrong commit ID was being used in a merge request diff to show old image (Stan Hu)
- Add confidential issues - Add confidential issues
- Bump gitlab_git to 9.0.3 (Stan Hu) - Bump gitlab_git to 9.0.3 (Stan Hu)
- Fix diff image view modes (2-up, swipe, onion skin) not working (Stan Hu)
- Support Golang subpackage fetching (Stan Hu) - Support Golang subpackage fetching (Stan Hu)
- Bump Capybara gem to 2.6.2 (Stan Hu) - Bump Capybara gem to 2.6.2 (Stan Hu)
- New branch button appears on issues where applicable - New branch button appears on issues where applicable
...@@ -16,9 +100,11 @@ v 8.6.0 (unreleased) ...@@ -16,9 +100,11 @@ v 8.6.0 (unreleased)
setup. A password can be provided during setup (see installation docs), or setup. A password can be provided during setup (see installation docs), or
GitLab will ask the user to create a new one upon first visit. GitLab will ask the user to create a new one upon first visit.
- Fix issue when pushing to projects ending in .wiki - Fix issue when pushing to projects ending in .wiki
- Properly display YAML front matter in Markdown
- Add support for wiki with UTF-8 page names (Hiroyuki Sato) - Add support for wiki with UTF-8 page names (Hiroyuki Sato)
- Fix wiki search results point to raw source (Hiroyuki Sato) - Fix wiki search results point to raw source (Hiroyuki Sato)
- Don't load all of GitLab in mail_room - Don't load all of GitLab in mail_room
- Add information about `image` and `services` field at `job` level in the `.gitlab-ci.yml` documentation (Pat Turner)
- HTTP error pages work independently from location and config (Artem Sidorenko) - HTTP error pages work independently from location and config (Artem Sidorenko)
- Update `omniauth-saml` to 1.5.0 to allow for custom response attributes to be set - Update `omniauth-saml` to 1.5.0 to allow for custom response attributes to be set
- Memoize @group in Admin::GroupsController (Yatish Mehta) - Memoize @group in Admin::GroupsController (Yatish Mehta)
...@@ -52,12 +138,17 @@ v 8.6.0 (unreleased) ...@@ -52,12 +138,17 @@ v 8.6.0 (unreleased)
- Add main language of a project in the list of projects (Tiago Botelho) - Add main language of a project in the list of projects (Tiago Botelho)
- Add #upcoming filter to Milestone filter (Tiago Botelho) - Add #upcoming filter to Milestone filter (Tiago Botelho)
- Add ability to show archived projects on dashboard, explore and group pages - 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 - Move group activity to separate page
- Create external users which are excluded of internal and private projects unless access was explicitly granted - 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 - Continue parameters are checked to ensure redirection goes to the same instance
- User deletion is now done in the background so the request can not time out - User deletion is now done in the background so the request can not time out
- Canceled builds are now ignored in compound build status if marked as `allowed to fail` - Canceled builds are now ignored in compound build status if marked as `allowed to fail`
- Trigger a todo for mentions on commits page - Trigger a todo for mentions on commits page
- Let project owners and admins soft delete issues and merge requests
v 8.5.9
- Don't attempt to fetch any tags from a forked repo (Stan Hu).
v 8.5.8 v 8.5.8
- Bump Git version requirement to 2.7.4 - Bump Git version requirement to 2.7.4
...@@ -200,6 +291,12 @@ v 8.5.0 ...@@ -200,6 +291,12 @@ v 8.5.0
- Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul) - Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul)
- Add Todos - Add Todos
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 v 8.4.5
- No CE-specific changes - No CE-specific changes
...@@ -313,6 +410,12 @@ v 8.4.0 ...@@ -313,6 +410,12 @@ v 8.4.0
- Add IP check against DNSBLs at account sign-up - Add IP check against DNSBLs at account sign-up
- Added cache:key to .gitlab-ci.yml allowing to fine tune the caching - Added cache:key to .gitlab-ci.yml allowing to fine tune the caching
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 v 8.3.4
- Use gitlab-workhorse 0.5.4 (fixes API routing bug) - Use gitlab-workhorse 0.5.4 (fixes API routing bug)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
- [Issue tracker guidelines](#issue-tracker-guidelines) - [Issue tracker guidelines](#issue-tracker-guidelines)
- [Issue weight](#issue-weight) - [Issue weight](#issue-weight)
- [Regression issues](#regression-issues) - [Regression issues](#regression-issues)
- [Technical debt](#technical-debt)
- [Merge requests](#merge-requests) - [Merge requests](#merge-requests)
- [Merge request guidelines](#merge-request-guidelines) - [Merge request guidelines](#merge-request-guidelines)
- [Merge request description format](#merge-request-description-format) - [Merge request description format](#merge-request-description-format)
...@@ -242,6 +243,28 @@ addressed. ...@@ -242,6 +243,28 @@ addressed.
[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127 [8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127
[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue [update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue
### Technical debt
In order to track things that can be improved in GitLab's codebase, we created
the ~"technical debt" label in [GitLab's issue tracker][ce-tracker].
This label should be added to issues that describe things that can be improved,
shortcuts that have been taken, code that needs refactoring, features that need
additional attention, and all other things that have been left behind due to
high velocity of development.
Everyone can create an issue, though you may need to ask for adding a specific
label, if you do not have permissions to do it by yourself. Additional labels
can be combined with the `technical debt` label, to make it easier to schedule
the improvements for a release.
Issues tagged with the `technical debt` label have the same priority like issues
that describe a new feature to be introduced in GitLab, and should be scheduled
for a release by the appropriate person.
Make sure to mention the merge request that the `technical debt` issue is
associated with in the description of the issue.
## Merge requests ## Merge requests
We welcome merge requests with fixes and improvements to GitLab code, tests, We welcome merge requests with fixes and improvements to GitLab code, tests,
......
...@@ -214,7 +214,7 @@ gem 'jquery-rails', '~> 4.0.0' ...@@ -214,7 +214,7 @@ gem 'jquery-rails', '~> 4.0.0'
gem 'jquery-scrollto-rails', '~> 1.4.3' gem 'jquery-scrollto-rails', '~> 1.4.3'
gem 'jquery-ui-rails', '~> 5.0.0' gem 'jquery-ui-rails', '~> 5.0.0'
gem 'raphael-rails', '~> 2.1.2' gem 'raphael-rails', '~> 2.1.2'
gem 'request_store', '~> 1.2.0' gem 'request_store', '~> 1.3.0'
gem 'select2-rails', '~> 3.5.9' gem 'select2-rails', '~> 3.5.9'
gem 'virtus', '~> 1.0.1' gem 'virtus', '~> 1.0.1'
gem 'net-ssh', '~> 3.0.1' gem 'net-ssh', '~> 3.0.1'
...@@ -222,6 +222,8 @@ gem 'net-ssh', '~> 3.0.1' ...@@ -222,6 +222,8 @@ gem 'net-ssh', '~> 3.0.1'
# Sentry integration # Sentry integration
gem 'sentry-raven', '~> 0.15' gem 'sentry-raven', '~> 0.15'
gem 'premailer-rails', '~> 1.9.0'
# Metrics # Metrics
group :metrics do group :metrics do
gem 'allocations', '~> 1.0', require: false, platform: :mri gem 'allocations', '~> 1.0', require: false, platform: :mri
...@@ -232,7 +234,7 @@ end ...@@ -232,7 +234,7 @@ end
group :development do group :development do
gem "foreman" gem "foreman"
gem 'brakeman', '~> 3.1.0', require: false gem 'brakeman', '~> 3.2.0', require: false
gem "annotate", "~> 2.6.0" gem "annotate", "~> 2.6.0"
gem "letter_opener", '~> 1.1.2' gem "letter_opener", '~> 1.1.2'
...@@ -277,7 +279,7 @@ group :development, :test do ...@@ -277,7 +279,7 @@ group :development, :test do
gem 'capybara-screenshot', '~> 1.0.0' gem 'capybara-screenshot', '~> 1.0.0'
gem 'poltergeist', '~> 1.9.0' gem 'poltergeist', '~> 1.9.0'
gem 'teaspoon', '~> 1.0.0' gem 'teaspoon', '~> 1.1.0'
gem 'teaspoon-jasmine', '~> 2.2.0' gem 'teaspoon-jasmine', '~> 2.2.0'
gem 'spring', '~> 1.6.4' gem 'spring', '~> 1.6.4'
......
...@@ -84,24 +84,22 @@ GEM ...@@ -84,24 +84,22 @@ GEM
bootstrap-sass (3.3.6) bootstrap-sass (3.3.6)
autoprefixer-rails (>= 5.2.1) autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4) sass (>= 3.3.4)
brakeman (3.1.4) brakeman (3.2.1)
erubis (~> 2.6) erubis (~> 2.6)
fastercsv (~> 1.5)
haml (>= 3.0, < 5.0) haml (>= 3.0, < 5.0)
highline (>= 1.6.20, < 2.0) highline (>= 1.6.20, < 2.0)
multi_json (~> 1.2) ruby2ruby (~> 2.3.0)
ruby2ruby (>= 2.1.1, < 2.3.0) ruby_parser (~> 3.8.1)
ruby_parser (~> 3.7.0)
safe_yaml (>= 1.0) safe_yaml (>= 1.0)
sass (~> 3.0) sass (~> 3.0)
slim (>= 1.3.6, < 4.0) slim (>= 1.3.6, < 4.0)
terminal-table (~> 1.4) terminal-table (~> 1.4)
browser (1.0.1) browser (1.0.1)
builder (3.2.2) builder (3.2.2)
bullet (4.14.10) bullet (5.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.9.0) uniform_notifier (~> 1.9.0)
bundler-audit (0.4.0) bundler-audit (0.5.0)
bundler (~> 1.2) bundler (~> 1.2)
thor (~> 0.18) thor (~> 0.18)
byebug (8.2.1) byebug (8.2.1)
...@@ -128,9 +126,9 @@ GEM ...@@ -128,9 +126,9 @@ GEM
coderay (1.1.0) coderay (1.1.0)
coercible (1.0.0) coercible (1.0.0)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
coffee-rails (4.1.0) coffee-rails (4.1.1)
coffee-script (>= 2.2.0) coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0) railties (>= 4.0.0, < 5.1.x)
coffee-script (2.4.1) coffee-script (2.4.1)
coffee-script-source coffee-script-source
execjs execjs
...@@ -148,6 +146,8 @@ GEM ...@@ -148,6 +146,8 @@ GEM
crack (0.4.3) crack (0.4.3)
safe_yaml (~> 1.0.0) safe_yaml (~> 1.0.0)
creole (0.5.0) creole (0.5.0)
css_parser (1.3.7)
addressable
d3_rails (3.5.11) d3_rails (3.5.11)
railties (>= 3.1.0) railties (>= 3.1.0)
daemons (1.2.3) daemons (1.2.3)
...@@ -206,7 +206,6 @@ GEM ...@@ -206,7 +206,6 @@ GEM
faraday_middleware-multi_json (0.0.6) faraday_middleware-multi_json (0.0.6)
faraday_middleware faraday_middleware
multi_json multi_json
fastercsv (1.5.5)
ffaker (2.0.0) ffaker (2.0.0)
ffi (1.9.10) ffi (1.9.10)
fission (0.5.0) fission (0.5.0)
...@@ -326,8 +325,8 @@ GEM ...@@ -326,8 +325,8 @@ GEM
fog-xml (0.1.2) fog-xml (0.1.2)
fog-core fog-core
nokogiri (~> 1.5, >= 1.5.11) nokogiri (~> 1.5, >= 1.5.11)
font-awesome-rails (4.5.0.0) font-awesome-rails (4.5.0.1)
railties (>= 3.2, < 5.0) railties (>= 3.2, < 5.1)
foreman (0.78.0) foreman (0.78.0)
thor (~> 0.19.1) thor (~> 0.19.1)
formatador (0.2.5) formatador (0.2.5)
...@@ -421,6 +420,7 @@ GEM ...@@ -421,6 +420,7 @@ GEM
haml (~> 4.0.0) haml (~> 4.0.0)
nokogiri (~> 1.6.0) nokogiri (~> 1.6.0)
ruby_parser (~> 3.5) ruby_parser (~> 3.5)
htmlentities (4.3.4)
http-cookie (1.0.2) http-cookie (1.0.2)
domain_name (~> 0.5) domain_name (~> 0.5)
http_parser.rb (0.5.3) http_parser.rb (0.5.3)
...@@ -562,6 +562,12 @@ GEM ...@@ -562,6 +562,12 @@ GEM
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
posix-spawn (0.3.11) posix-spawn (0.3.11)
powerpack (0.1.1) powerpack (0.1.1)
premailer (1.8.6)
css_parser (>= 1.3.6)
htmlentities (>= 4.0.0)
premailer-rails (1.9.0)
actionmailer (>= 3, < 5)
premailer (~> 1.7, >= 1.7.9)
pry (0.10.3) pry (0.10.3)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.8.1)
...@@ -646,7 +652,7 @@ GEM ...@@ -646,7 +652,7 @@ GEM
redis-store (~> 1.1.0) redis-store (~> 1.1.0)
redis-store (1.1.7) redis-store (1.1.7)
redis (>= 2.2) redis (>= 2.2)
request_store (1.2.1) request_store (1.3.0)
rerun (0.11.0) rerun (0.11.0)
listen (~> 3.0) listen (~> 3.0)
responders (2.1.1) responders (2.1.1)
...@@ -697,10 +703,10 @@ GEM ...@@ -697,10 +703,10 @@ GEM
ruby-saml (1.1.2) ruby-saml (1.1.2)
nokogiri (>= 1.5.10) nokogiri (>= 1.5.10)
uuid (~> 2.3) uuid (~> 2.3)
ruby2ruby (2.2.0) ruby2ruby (2.3.0)
ruby_parser (~> 3.1) ruby_parser (~> 3.1)
sexp_processor (~> 4.0) sexp_processor (~> 4.0)
ruby_parser (3.7.2) ruby_parser (3.8.1)
sexp_processor (~> 4.1) sexp_processor (~> 4.1)
rubyntlm (0.5.2) rubyntlm (0.5.2)
rubypants (0.2.0) rubypants (0.2.0)
...@@ -709,7 +715,7 @@ GEM ...@@ -709,7 +715,7 @@ GEM
safe_yaml (1.0.4) safe_yaml (1.0.4)
sanitize (2.1.0) sanitize (2.1.0)
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
sass (3.4.20) sass (3.4.21)
sass-rails (5.0.4) sass-rails (5.0.4)
railties (>= 4.0.0, < 5.0) railties (>= 4.0.0, < 5.0)
sass (~> 3.1) sass (~> 3.1)
...@@ -733,7 +739,7 @@ GEM ...@@ -733,7 +739,7 @@ GEM
sentry-raven (0.15.6) sentry-raven (0.15.6)
faraday (>= 0.7.6) faraday (>= 0.7.6)
settingslogic (2.0.9) settingslogic (2.0.9)
sexp_processor (4.6.0) sexp_processor (4.7.0)
sham_rack (1.3.6) sham_rack (1.3.6)
rack rack
shoulda-matchers (2.8.0) shoulda-matchers (2.8.0)
...@@ -797,8 +803,8 @@ GEM ...@@ -797,8 +803,8 @@ GEM
systemu (2.6.5) systemu (2.6.5)
task_list (1.0.2) task_list (1.0.2)
html-pipeline html-pipeline
teaspoon (1.0.2) teaspoon (1.1.5)
railties (>= 3.2.5, < 5) railties (>= 3.2.5, < 6)
teaspoon-jasmine (2.2.0) teaspoon-jasmine (2.2.0)
teaspoon (>= 1.0.0) teaspoon (>= 1.0.0)
temple (0.7.6) temple (0.7.6)
...@@ -859,7 +865,7 @@ GEM ...@@ -859,7 +865,7 @@ GEM
equalizer (~> 0.0, >= 0.0.9) equalizer (~> 0.0, >= 0.0.9)
warden (1.2.4) warden (1.2.4)
rack (>= 1.0) rack (>= 1.0)
web-console (2.2.1) web-console (2.3.0)
activemodel (>= 4.0) activemodel (>= 4.0)
binding_of_caller (>= 0.7.2) binding_of_caller (>= 0.7.2)
railties (>= 4.0) railties (>= 4.0)
...@@ -901,7 +907,7 @@ DEPENDENCIES ...@@ -901,7 +907,7 @@ DEPENDENCIES
better_errors (~> 1.0.1) better_errors (~> 1.0.1)
binding_of_caller (~> 0.7.2) binding_of_caller (~> 0.7.2)
bootstrap-sass (~> 3.3.0) bootstrap-sass (~> 3.3.0)
brakeman (~> 3.1.0) brakeman (~> 3.2.0)
browser (~> 1.0.0) browser (~> 1.0.0)
bullet bullet
bundler-audit bundler-audit
...@@ -990,6 +996,7 @@ DEPENDENCIES ...@@ -990,6 +996,7 @@ DEPENDENCIES
paranoia (~> 2.0) paranoia (~> 2.0)
pg (~> 0.18.2) pg (~> 0.18.2)
poltergeist (~> 1.9.0) poltergeist (~> 1.9.0)
premailer-rails (~> 1.9.0)
pry-rails pry-rails
quiet_assets (~> 1.0.2) quiet_assets (~> 1.0.2)
rack-attack (~> 4.3.1) rack-attack (~> 4.3.1)
...@@ -1004,7 +1011,7 @@ DEPENDENCIES ...@@ -1004,7 +1011,7 @@ DEPENDENCIES
redcarpet (~> 3.3.3) redcarpet (~> 3.3.3)
redis-namespace redis-namespace
redis-rails (~> 4.0.0) redis-rails (~> 4.0.0)
request_store (~> 1.2.0) request_store (~> 1.3.0)
rerun (~> 0.11.0) rerun (~> 0.11.0)
responders (~> 2.0) responders (~> 2.0)
rouge (~> 1.10.1) rouge (~> 1.10.1)
...@@ -1038,7 +1045,7 @@ DEPENDENCIES ...@@ -1038,7 +1045,7 @@ DEPENDENCIES
sprockets (~> 3.3.5) sprockets (~> 3.3.5)
state_machines-activerecord (~> 0.3.0) state_machines-activerecord (~> 0.3.0)
task_list (~> 1.0.2) task_list (~> 1.0.2)
teaspoon (~> 1.0.0) teaspoon (~> 1.1.0)
teaspoon-jasmine (~> 2.2.0) teaspoon-jasmine (~> 2.2.0)
test_after_commit (~> 0.4.2) test_after_commit (~> 0.4.2)
thin (~> 1.6.1) thin (~> 1.6.1)
......
8.6.0-pre 8.7.0-pre
...@@ -74,6 +74,8 @@ ...@@ -74,6 +74,8 @@
dataType: "json" dataType: "json"
).done (label) -> ).done (label) ->
callback(label) callback(label)
.error (message) ->
callback(message.responseJSON)
# Return group projects list. Filtered by query # Return group projects list. Filtered by query
groupProjects: (group_id, query, callback) -> groupProjects: (group_id, query, callback) ->
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#= require jquery #= require jquery
#= require jquery-ui/autocomplete #= require jquery-ui/autocomplete
#= require jquery-ui/datepicker #= require jquery-ui/datepicker
#= require jquery-ui/draggable
#= require jquery-ui/effect-highlight #= require jquery-ui/effect-highlight
#= require jquery-ui/sortable #= require jquery-ui/sortable
#= require jquery_ujs #= require jquery_ujs
...@@ -42,6 +43,7 @@ ...@@ -42,6 +43,7 @@
#= require jquery.nicescroll #= require jquery.nicescroll
#= require_tree . #= require_tree .
#= require fuzzaldrin-plus #= require fuzzaldrin-plus
#= require cropper
window.slugify = (text) -> window.slugify = (text) ->
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase() text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
...@@ -138,7 +140,7 @@ $ -> ...@@ -138,7 +140,7 @@ $ ->
# Initialize tooltips # Initialize tooltips
$('body').tooltip( $('body').tooltip(
selector: '.has_tooltip, [data-toggle="tooltip"]' selector: '.has-tooltip, [data-toggle="tooltip"]'
placement: (_, el) -> placement: (_, el) ->
$el = $(el) $el = $(el)
$el.data('placement') || 'bottom' $el.data('placement') || 'bottom'
...@@ -217,13 +219,20 @@ $ -> ...@@ -217,13 +219,20 @@ $ ->
$this = $(this) $this = $(this)
$this.attr 'value', $this.val() $this.attr 'value', $this.val()
$sidebarGutterToggle = $('.js-sidebar-toggle')
$navIconToggle = $('.toggle-nav-collapse')
$(document) $(document)
.off 'breakpoint:change' .off 'breakpoint:change'
.on 'breakpoint:change', (e, breakpoint) -> .on 'breakpoint:change', (e, breakpoint) ->
if breakpoint is 'sm' or breakpoint is 'xs' if breakpoint is 'sm' or breakpoint is 'xs'
$gutterIcon = $('.js-sidebar-toggle').find('i') $gutterIcon = $sidebarGutterToggle.find('i')
if $gutterIcon.hasClass('fa-angle-double-right') if $gutterIcon.hasClass('fa-angle-double-right')
$gutterIcon.closest('a').trigger('click') $sidebarGutterToggle.trigger('click')
$navIcon = $navIconToggle.find('.fa')
if $navIcon.hasClass('fa-angle-left')
$navIconToggle.trigger('click')
$(document) $(document)
.off 'click', '.js-sidebar-toggle' .off 'click', '.js-sidebar-toggle'
......
...@@ -5,7 +5,6 @@ class @Aside ...@@ -5,7 +5,6 @@ class @Aside
e.preventDefault() e.preventDefault()
btn = $(e.currentTarget) btn = $(e.currentTarget)
icon = btn.find('i') icon = btn.find('i')
console.log('1')
if icon.hasClass('fa-angle-left') if icon.hasClass('fa-angle-left')
btn.parent().find('section').hide() btn.parent().find('section').hide()
......
class @AwardsHandler 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) => $(".js-add-award").on "click", (event) =>
event.stopPropagation() event.stopPropagation()
event.preventDefault() event.preventDefault()
...@@ -34,7 +34,7 @@ class @AwardsHandler ...@@ -34,7 +34,7 @@ class @AwardsHandler
$("#emoji_search").focus() $("#emoji_search").focus()
else else
$('.js-add-award').addClass "is-loading" $('.js-add-award').addClass "is-loading"
$.get "/emojis", (response) => $.get @get_emojis_url, (response) =>
$('.js-add-award').removeClass "is-loading" $('.js-add-award').removeClass "is-loading"
$(".js-award-holder").append response $(".js-award-holder").append response
setTimeout => setTimeout =>
...@@ -122,7 +122,7 @@ class @AwardsHandler ...@@ -122,7 +122,7 @@ class @AwardsHandler
nodes = [] nodes = []
nodes.push( 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' title='me'>",
"<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>", "<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>",
"<span class='award-control-text js-counter'>1</span>", "<span class='award-control-text js-counter'>1</span>",
"</button>" "</button>"
......
...@@ -146,15 +146,11 @@ class Dispatcher ...@@ -146,15 +146,11 @@ class Dispatcher
when 'project_members', 'deploy_keys', 'hooks', 'services', 'protected_branches' when 'project_members', 'deploy_keys', 'hooks', 'services', 'protected_branches'
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
# If we haven't installed a custom shortcut handler, install the default one # If we haven't installed a custom shortcut handler, install the default one
if not shortcut_handler if not shortcut_handler
new Shortcuts() new Shortcuts()
initSearch: -> initSearch: ->
opts = $('.search-autocomplete-opts')
path = opts.data('autocomplete-path')
project_id = opts.data('autocomplete-project-id')
project_ref = opts.data('autocomplete-project-ref')
new SearchAutocomplete(path, project_id, project_ref) # Only when search form is present
new SearchAutocomplete() if $('.search').length
class GitLabCrop
# Matches everything but the file name
FILENAMEREGEX = /^.*[\\\/]/
constructor: (input, opts = {}) ->
@fileInput = $(input)
# We should rename to avoid spec to fail
# Form will submit the proper input filed with a file using FormData
@fileInput
.attr('name', "#{@fileInput.attr('name')}-trigger")
.attr('id', "#{@fileInput.attr('id')}-trigger")
# Set defaults
{
@exportWidth = 200
@exportHeight = 200
@cropBoxWidth = 200
@cropBoxHeight = 200
@form = @fileInput.parents('form')
# Required params
@filename
@previewImage
@modalCrop
@pickImageEl
@uploadImageBtn
@modalCropImg
} = opts
# Ensure needed elements are jquery objects
# If selector is provided we will convert them to a jQuery Object
@filename = @getElement(@filename)
@previewImage = @getElement(@previewImage)
@pickImageEl = @getElement(@pickImageEl)
# Modal elements usually are outside the @form element
@modalCrop = if _.isString(@modalCrop) then $(@modalCrop) else @modalCrop
@uploadImageBtn = if _.isString(@uploadImageBtn) then $(@uploadImageBtn) else @uploadImageBtn
@modalCropImg = if _.isString(@modalCropImg) then $(@modalCropImg) else @modalCropImg
@cropActionsBtn = @modalCrop.find('[data-method]')
@bindEvents()
getElement: (selector) ->
$(selector, @form)
bindEvents: ->
_this = @
@fileInput.on 'change', (e) ->
_this.onFileInputChange(e, @)
@pickImageEl.on 'click', @onPickImageClick
@modalCrop.on 'shown.bs.modal', @onModalShow
@modalCrop.on 'hidden.bs.modal', @onModalHide
@uploadImageBtn.on 'click', @onUploadImageBtnClick
@cropActionsBtn.on 'click', (e) ->
btn = @
_this.onActionBtnClick(btn)
@croppedImageBlob = null
onPickImageClick: =>
@fileInput.trigger('click')
onModalShow: =>
_this = @
@modalCropImg.cropper(
viewMode: 1
center: false
aspectRatio: 1
modal: true
scalable: false
rotatable: false
zoomable: true
dragMode: 'move'
guides: false
zoomOnTouch: false
zoomOnWheel: false
cropBoxMovable: false
cropBoxResizable: false
toggleDragModeOnDblclick: false
built: ->
$image = $(@)
container = $image.cropper 'getContainerData'
cropBoxWidth = _this.cropBoxWidth;
cropBoxHeight = _this.cropBoxHeight;
$image.cropper('setCropBoxData',
width: cropBoxWidth,
height: cropBoxHeight,
left: (container.width - cropBoxWidth) / 2,
top: (container.height - cropBoxHeight) / 2
)
)
onModalHide: =>
@modalCropImg
.attr('src', '') # Remove attached image
.cropper('destroy') # Destroy cropper instance
onUploadImageBtnClick: (e) =>
e.preventDefault()
@setBlob()
@setPreview()
@modalCrop.modal('hide')
@fileInput.val('')
onActionBtnClick: (btn) ->
data = $(btn).data()
if @modalCropImg.data('cropper') && data.method
result = @modalCropImg.cropper data.method, data.option
onFileInputChange: (e, input) ->
@readFile(input)
readFile: (input) ->
_this = @
reader = new FileReader
reader.onload = ->
_this.modalCropImg.attr('src', reader.result)
_this.modalCrop.modal('show')
reader.readAsDataURL(input.files[0])
dataURLtoBlob: (dataURL) ->
binary = atob(dataURL.split(',')[1])
array = []
for v, k in binary
array.push(binary.charCodeAt(k))
new Blob([new Uint8Array(array)], type: 'image/png')
setPreview: ->
@previewImage.attr('src', @dataURL)
filename = @fileInput.val().replace(FILENAMEREGEX, '')
@filename.text(filename)
setBlob: ->
@dataURL = @modalCropImg.cropper('getCroppedCanvas',
width: 200
height: 200
).toDataURL('image/png')
@croppedImageBlob = @dataURLtoBlob(@dataURL)
getBlob: ->
@croppedImageBlob
$.fn.glCrop = (opts) ->
return @.each ->
$(@).data('glcrop', new GitLabCrop(@, opts))
#= require jquery.waitforimages
class @IssuableContext class @IssuableContext
constructor: -> constructor: (currentUser) ->
new UsersSelect() @initParticipants()
new UsersSelect(currentUser)
$('select.select2').select2({width: 'resolve', dropdownAutoWidth: true}) $('select.select2').select2({width: 'resolve', dropdownAutoWidth: true})
$(".issuable-sidebar .inline-update").on "change", "select", -> $(".issuable-sidebar .inline-update").on "change", "select", ->
...@@ -10,10 +9,44 @@ class @IssuableContext ...@@ -10,10 +9,44 @@ class @IssuableContext
$(".issuable-sidebar .inline-update").on "change", ".js-assignee", -> $(".issuable-sidebar .inline-update").on "change", ".js-assignee", ->
$(this).submit() $(this).submit()
$(document).on "click",".edit-link", (e) -> $(document).off("click", ".edit-link").on "click",".edit-link", (e) ->
block = $(@).parents('.block') $block = $(@).parents('.block')
block.find('.selectbox').show() $selectbox = $block.find('.selectbox')
block.find('.value').hide() if $selectbox.is(':visible')
block.find('.js-select2').select2("open") $selectbox.hide()
$block.find('.value').show()
else
$selectbox.show()
$block.find('.value').hide()
if $selectbox.is(':visible')
setTimeout (->
$block.find('.dropdown-menu-toggle').trigger 'click'
), 0
$(".right-sidebar").niceScroll() $(".right-sidebar").niceScroll()
initParticipants: ->
_this = @
$(document).on "click", ".js-participants-more", @toggleHiddenParticipants
$(".js-participants-author").each (i) ->
if i >= _this.PARTICIPANTS_ROW_COUNT
$(@)
.addClass "js-participants-hidden"
.hide()
toggleHiddenParticipants: (e) ->
e.preventDefault()
currentText = $(this).text().trim()
lessText = $(this).data("less-text")
originalText = $(this).data("original-text")
if currentText is originalText
$(this).text(lessText)
else
$(this).text(originalText)
$(".js-participants-hidden").toggle()
class @IssuableForm class @IssuableForm
issueMoveConfirmMsg: 'Are you sure you want to move this issue to another project?'
wipRegex: /^\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i wipRegex: /^\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i
constructor: (@form) -> constructor: (@form) ->
GitLab.GfmAutoComplete.setup() GitLab.GfmAutoComplete.setup()
new UsersSelect() new UsersSelect()
...@@ -7,12 +9,13 @@ class @IssuableForm ...@@ -7,12 +9,13 @@ class @IssuableForm
@titleField = @form.find("input[name*='[title]']") @titleField = @form.find("input[name*='[title]']")
@descriptionField = @form.find("textarea[name*='[description]']") @descriptionField = @form.find("textarea[name*='[description]']")
@issueMoveField = @form.find("#move_to_project_id")
return unless @titleField.length && @descriptionField.length return unless @titleField.length && @descriptionField.length
@initAutosave() @initAutosave()
@form.on "submit", @resetAutosave @form.on "submit", @handleSubmit
@form.on "click", ".btn-cancel", @resetAutosave @form.on "click", ".btn-cancel", @resetAutosave
@initWip() @initWip()
...@@ -30,6 +33,12 @@ class @IssuableForm ...@@ -30,6 +33,12 @@ class @IssuableForm
"description" "description"
] ]
handleSubmit: =>
if (parseInt(@issueMoveField?.val()) ? 0) > 0
return false unless confirm(@issueMoveConfirmMsg)
@resetAutosave()
resetAutosave: => resetAutosave: =>
@titleField.data("autosave").reset() @titleField.data("autosave").reset()
@descriptionField.data("autosave").reset() @descriptionField.data("autosave").reset()
......
...@@ -6,26 +6,10 @@ class @Issue ...@@ -6,26 +6,10 @@ class @Issue
constructor: -> constructor: ->
# Prevent duplicate event bindings # Prevent duplicate event bindings
@disableTaskList() @disableTaskList()
@fixAffixScroll()
@initParticipants()
if $('a.btn-close').length if $('a.btn-close').length
@initTaskList() @initTaskList()
@initIssueBtnEventListeners() @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: -> initTaskList: ->
$('.detail-page-description .js-task-list-container').taskList('enable') $('.detail-page-description .js-task-list-container').taskList('enable')
$(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList
...@@ -50,7 +34,7 @@ class @Issue ...@@ -50,7 +34,7 @@ class @Issue
issueStatus = if isClose then 'close' else 'open' issueStatus = if isClose then 'close' else 'open'
new Flash(issueFailMessage, 'alert') new Flash(issueFailMessage, 'alert')
success: (data, textStatus, jqXHR) -> success: (data, textStatus, jqXHR) ->
if data.saved if 'id' of data
$(document).trigger('issuable:change'); $(document).trigger('issuable:change');
if isClose if isClose
$('a.btn-close').addClass('hidden') $('a.btn-close').addClass('hidden')
...@@ -85,27 +69,3 @@ class @Issue ...@@ -85,27 +69,3 @@ class @Issue
type: 'PATCH' type: 'PATCH'
url: $('form.js-issuable-update').attr('action') url: $('form.js-issuable-update').attr('action')
data: patchData data: patchData
initParticipants: ->
_this = @
$(document).on "click", ".js-participants-more", @toggleHiddenParticipants
$(".js-participants-author").each (i) ->
if i >= _this.PARTICIPANTS_ROW_COUNT
$(@)
.addClass "js-participants-hidden"
.hide()
toggleHiddenParticipants: (e) ->
e.preventDefault()
currentText = $(this).text().trim()
lessText = $(this).data("less-text")
originalText = $(this).data("original-text")
if currentText is originalText
$(this).text(lessText)
else
$(this).text(originalText)
$(".js-participants-hidden").toggle()
@Issues = @Issues =
init: -> init: ->
Issues.initSearch() Issues.initSearch()
Issues.initSelects()
Issues.initChecks() Issues.initChecks()
$("body").on "ajax:success", ".close_issue, .reopen_issue", -> $("body").on "ajax:success", ".close_issue, .reopen_issue", ->
...@@ -17,18 +16,9 @@ ...@@ -17,18 +16,9 @@
$(this).html totalIssues - 1 $(this).html totalIssues - 1
reload: -> reload: ->
Issues.initSelects()
Issues.initChecks() Issues.initChecks()
$('#filter_issue_search').val($('#issue_search').val()) $('#filter_issue_search').val($('#issue_search').val())
initSelects: ->
$("select#update_state_event").select2(width: 'resolve', dropdownAutoWidth: true)
$("select#update_assignee_id").select2(width: 'resolve', dropdownAutoWidth: true)
$("select#update_milestone_id").select2(width: 'resolve', dropdownAutoWidth: true)
$("select#label_name").select2(width: 'resolve', dropdownAutoWidth: true)
$("#milestone_id, #assignee_id, #label_name").on "change", ->
$(this).closest("form").submit()
initChecks: -> initChecks: ->
$(".check_all_issues").click -> $(".check_all_issues").click ->
$(".selected_issue").prop("checked", @checked) $(".selected_issue").prop("checked", @checked)
......
...@@ -4,29 +4,83 @@ class @LabelsSelect ...@@ -4,29 +4,83 @@ class @LabelsSelect
$dropdown = $(dropdown) $dropdown = $(dropdown)
projectId = $dropdown.data('project-id') projectId = $dropdown.data('project-id')
labelUrl = $dropdown.data('labels') labelUrl = $dropdown.data('labels')
issueUpdateURL = $dropdown.data('issueUpdate')
selectedLabel = $dropdown.data('selected') selectedLabel = $dropdown.data('selected')
if selectedLabel if selectedLabel?
selectedLabel = selectedLabel.split(',') selectedLabel = selectedLabel.split(',')
newLabelField = $('#new_label_name') newLabelField = $('#new_label_name')
newColorField = $('#new_label_color') newColorField = $('#new_label_color')
showNo = $dropdown.data('show-no') showNo = $dropdown.data('show-no')
showAny = $dropdown.data('show-any') showAny = $dropdown.data('show-any')
defaultLabel = $dropdown.data('default-label') defaultLabel = $dropdown.data('default-label')
abilityName = $dropdown.data('ability-name')
$selectbox = $dropdown.closest('.selectbox')
$block = $selectbox.closest('.block')
$sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon span')
$value = $block.find('.value')
$loading = $block.find('.block-loading').fadeOut()
if newLabelField.length if newLabelField.length
$newLabelCreateButton = $('.js-new-label-btn')
$colorPreview = $('.js-dropdown-label-color-preview')
$newLabelError = $dropdown.parent().find('.js-label-error')
$newLabelError.hide()
# Suggested colors in the dropdown to chose from pre-chosen colors
$('.suggest-colors-dropdown a').on 'click', (e) -> $('.suggest-colors-dropdown a').on 'click', (e) ->
issueURLSplit = issueUpdateURL.split('/') if issueUpdateURL?
if issueUpdateURL
labelHTMLTemplate = _.template(
'<% _.each(labels, function(label){ %>
<a href="<%= ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name=<%= label.title %>">
<span class="label color-label" style="background-color: <%= label.color %>;">
<%= label.title %>
</span>
</a>
<% }); %>'
);
labelNoneHTMLTemplate = _.template('<div class="light">None</div>')
if newLabelField.length and $dropdown.hasClass 'js-extra-options'
$('.suggest-colors-dropdown a').on "click", (e) ->
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
newColorField.val $(this).data('color') newColorField
$('.js-dropdown-label-color-preview') .val($(this).data('color'))
.trigger('change')
$colorPreview
.css 'background-color', $(this).data('color') .css 'background-color', $(this).data('color')
.parent()
.addClass 'is-active' .addClass 'is-active'
$('.js-new-label-btn').on 'click', (e) -> # Cancel button takes back to first page
resetForm = ->
newLabelField
.val ''
.trigger 'change'
newColorField
.val ''
.trigger 'change'
$colorPreview
.css 'background-color', ''
.parent()
.removeClass 'is-active'
$('.dropdown-menu-back').on 'click', ->
resetForm()
$('.js-cancel-label-btn').on 'click', (e) ->
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
resetForm()
$('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
# Listen for change and keyup events on label and color field
# This allows us to enable the button when ready
enableLabelCreateButton = ->
if newLabelField.val() isnt '' and newColorField.val() isnt '' if newLabelField.val() isnt '' and newColorField.val() isnt ''
$newLabelError.hide()
$('.js-new-label-btn').disable() $('.js-new-label-btn').disable()
# Create new label with API # Create new label with API
...@@ -35,41 +89,126 @@ class @LabelsSelect ...@@ -35,41 +89,126 @@ class @LabelsSelect
color: newColorField.val() color: newColorField.val()
}, (label) -> }, (label) ->
$('.js-new-label-btn').enable() $('.js-new-label-btn').enable()
$('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
if label.message?
$newLabelError
.text label.message
.show()
else
$('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
$newLabelCreateButton.enable()
else
$newLabelCreateButton.disable()
newLabelField.on 'keyup change', enableLabelCreateButton
newColorField.on 'keyup change', enableLabelCreateButton
# Send the API call to create the label
$newLabelCreateButton
.disable()
.on 'click', (e) ->
e.preventDefault()
e.stopPropagation()
if newLabelField.val() isnt '' and newColorField.val() isnt ''
$newLabelError.hide()
$('.js-new-label-btn').disable()
# Create new label with API
Api.newLabel projectId, {
name: newLabelField.val()
color: newColorField.val()
}, (label) ->
$('.js-new-label-btn').enable()
if label.message?
$newLabelError
.text label.message
.show()
else
$('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
saveLabelData = ->
selected = $dropdown
.closest('.selectbox')
.find("input[name='#{$dropdown.data('field-name')}']")
.map(->
@value
).get()
data = {}
data[abilityName] = {}
data[abilityName].label_ids = selected
if not selected.length
data[abilityName].label_ids = ['']
$loading.fadeIn()
$dropdown.trigger('loading.gl.dropdown')
$.ajax(
type: 'PUT'
url: issueUpdateURL
dataType: 'JSON'
data: data
).done (data) ->
$loading.fadeOut()
$dropdown.trigger('loaded.gl.dropdown')
$selectbox.hide()
data.issueURLSplit = issueURLSplit
labelCount = 0
if data.labels.length
template = labelHTMLTemplate(data)
labelCount = data.labels.length
else
template = labelNoneHTMLTemplate()
$value
.removeAttr('style')
.html(template)
$sidebarCollapsedValue.text(labelCount)
$value
.find('a')
.each((i) ->
setTimeout(=>
glAnimate($(@), 'pulse')
,200 * i
)
)
$dropdown.glDropdown( $dropdown.glDropdown(
data: (term, callback) -> data: (term, callback) ->
$.ajax( $.ajax(
url: labelUrl url: labelUrl
).done (data) -> ).done (data) ->
if showNo if $dropdown.hasClass 'js-extra-options'
data.unshift( if showNo
id: 0 data.unshift(
title: 'No Label' id: 0
) title: 'No Label'
)
if showAny if showAny
data.unshift( data.unshift(
isAny: true isAny: true
title: 'Any Label' title: 'Any Label'
) )
if data.length > 2
data.splice 2, 0, 'divider'
if data.length > 2
data.splice 2, 0, 'divider'
callback data callback data
renderRow: (label) -> renderRow: (label) ->
if $.isArray(selectedLabel) selectedClass = ''
selected = '' if $selectbox.find("input[type='hidden']\
$.each selectedLabel, (i, selectedLbl) -> [name='#{$dropdown.data('field-name')}']\
selectedLbl = selectedLbl.trim() [value='#{label.id}']").length
if selected is '' and label.title is selectedLbl selectedClass = 'is-active'
selected = 'is-active'
else color = if label.color? then "<span class='dropdown-label-box' style='background-color: #{label.color}'></span>" else ""
selected = if label.title is selectedLabel then 'is-active' else ''
"<li> "<li>
<a href='#' class='#{selected}'> <a href='#' class='#{selectedClass}'>
#{color}
#{label.title} #{label.title}
</a> </a>
</li>" </li>"
...@@ -77,6 +216,7 @@ class @LabelsSelect ...@@ -77,6 +216,7 @@ class @LabelsSelect
search: search:
fields: ['title'] fields: ['title']
selectable: true selectable: true
toggleLabel: (selected) -> toggleLabel: (selected) ->
if selected and selected.title isnt 'Any Label' if selected and selected.title isnt 'Any Label'
selected.title selected.title
...@@ -86,15 +226,33 @@ class @LabelsSelect ...@@ -86,15 +226,33 @@ class @LabelsSelect
id: (label) -> id: (label) ->
if label.isAny? if label.isAny?
'' ''
else else if $dropdown.hasClass "js-filter-submit"
label.title label.title
clicked: -> else
label.id
hidden: ->
$selectbox.hide()
# display:block overrides the hide-collapse rule
$value.removeAttr('style')
if $dropdown.hasClass 'js-multiselect'
saveLabelData()
multiSelect: $dropdown.hasClass 'js-multiselect'
clicked: (label) ->
page = $('body').data 'page' page = $('body').data 'page'
isIssueIndex = page is 'projects:issues:index' isIssueIndex = page is 'projects:issues:index'
isMRIndex = page is page is 'projects:merge_requests:index' isMRIndex = page is page is 'projects:merge_requests:index'
if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex) if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
selectedLabel = label.title
Issues.filterResults $dropdown.closest('form') Issues.filterResults $dropdown.closest('form')
else if $dropdown.hasClass 'js-filter-submit' else if $dropdown.hasClass 'js-filter-submit'
$dropdown.closest('form').submit() $dropdown.closest('form').submit()
else
if $dropdown.hasClass 'js-multiselect'
return
else
saveLabelData()
) )
((w) ->
w.glAnimate = ($el, animation, done) ->
$el
.removeClass()
.addClass(animation + ' animated')
.one 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', ->
$(this).removeClass()
return
return
return
) window
\ No newline at end of file
((w) ->
notificationGranted = (message, opts, onclick) ->
notification = new Notification(message, opts)
if onclick
notification.onclick = onclick
notifyPermissions = ->
if 'Notification' of window
Notification.requestPermission()
notifyMe = (message, body, icon, onclick) ->
opts =
body: body
icon: icon
# Let's check if the browser supports notifications
if !('Notification' of window)
# do nothing
else if Notification.permission == 'granted'
# If it's okay let's create a notification
notificationGranted message, opts, onclick
else if Notification.permission != 'denied'
Notification.requestPermission (permission) ->
# If the user accepts, let's create a notification
if permission == 'granted'
notificationGranted message, opts, onclick
w.notify = notifyMe
w.notifyPermissions = notifyPermissions
) window
...@@ -15,8 +15,6 @@ class @MergeRequest ...@@ -15,8 +15,6 @@ class @MergeRequest
this.$('.show-all-commits').on 'click', => this.$('.show-all-commits').on 'click', =>
this.showAllCommits() this.showAllCommits()
@fixAffixScroll();
@initTabs() @initTabs()
# Prevent duplicate event bindings # Prevent duplicate event bindings
...@@ -30,20 +28,6 @@ class @MergeRequest ...@@ -30,20 +28,6 @@ class @MergeRequest
$: (selector) -> $: (selector) ->
this.$el.find(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: -> initTabs: ->
if @opts.action != 'new' if @opts.action != 'new'
# `MergeRequests#new` has no tab-persisting or lazy-loading behavior # `MergeRequests#new` has no tab-persisting or lazy-loading behavior
......
...@@ -2,13 +2,18 @@ class @MergeRequestWidget ...@@ -2,13 +2,18 @@ class @MergeRequestWidget
# Initialize MergeRequestWidget behavior # Initialize MergeRequestWidget behavior
# #
# check_enable - Boolean, whether to check automerge status # check_enable - Boolean, whether to check automerge status
# url_to_automerge_check - String, URL to use to check automerge status # merge_check_url - String, URL to use to check automerge status
# current_status - String, current automerge status # ci_status_url - String, URL to use to check CI status
# ci_enable - Boolean, whether a CI service is enabled
# url_to_ci_check - String, URL to use to check CI status
# #
constructor: (@opts) -> constructor: (@opts) ->
modal = $('#modal_merge_info').modal(show: false) $('#modal_merge_info').modal(show: false)
@firstCICheck = true
@readyForCICheck = true
clearInterval @fetchBuildStatusInterval
@pollCIStatus()
notifyPermissions()
mergeInProgress: (deleteSourceBranch = false)-> mergeInProgress: (deleteSourceBranch = false)->
$.ajax $.ajax
...@@ -27,18 +32,57 @@ class @MergeRequestWidget ...@@ -27,18 +32,57 @@ class @MergeRequestWidget
dataType: 'json' dataType: 'json'
getMergeStatus: -> getMergeStatus: ->
$.get @opts.url_to_automerge_check, (data) -> $.get @opts.merge_check_url, (data) ->
$('.mr-state-widget').replaceWith(data) $('.mr-state-widget').replaceWith(data)
getCiStatus: -> ciLabelForStatus: (status) ->
if @opts.ci_enable if status == 'success'
$.get @opts.url_to_ci_check, (data) => 'passed'
this.showCiState data.status else
status
pollCIStatus: ->
@fetchBuildStatusInterval = setInterval ( =>
return if not @readyForCICheck
@getCIStatus(true)
@readyForCICheck = false
), 5000
getCIStatus: (showNotification) ->
_this = @
$('.ci-widget-fetching').show()
$.getJSON @opts.ci_status_url, (data) =>
@readyForCICheck = true
if @firstCICheck
@firstCICheck = false
@opts.ci_status = data.status
if data.status isnt @opts.ci_status
@showCIStatus data.status
if data.coverage if data.coverage
this.showCiCoverage data.coverage @showCICoverage data.coverage
, 'json'
if showNotification
message = @opts.ci_message.replace('{{status}}', @ciLabelForStatus(data.status))
message = message.replace('{{sha}}', data.sha)
message = message.replace('{{title}}', data.title)
notify(
"Build #{@ciLabelForStatus(data.status)}",
message,
@opts.gitlab_icon,
->
@close()
Turbolinks.visit _this.opts.builds_path
)
@opts.ci_status = data.status
showCiState: (state) -> showCIStatus: (state) ->
$('.ci_widget').hide() $('.ci_widget').hide()
allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"] allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"]
if state in allowed_states if state in allowed_states
...@@ -52,7 +96,7 @@ class @MergeRequestWidget ...@@ -52,7 +96,7 @@ class @MergeRequestWidget
$('.ci_widget.ci-error').show() $('.ci_widget.ci-error').show()
@setMergeButtonClass('btn-danger') @setMergeButtonClass('btn-danger')
showCiCoverage: (coverage) -> showCICoverage: (coverage) ->
text = 'Coverage ' + coverage + '%' text = 'Coverage ' + coverage + '%'
$('.ci_widget:visible .ci-coverage').text(text) $('.ci_widget:visible .ci-coverage').text(text)
......
class @MilestoneSelect class @MilestoneSelect
constructor: -> constructor: (currentProject) ->
if currentProject?
_this = @
@currentProject = JSON.parse(currentProject)
$('.js-milestone-select').each (i, dropdown) -> $('.js-milestone-select').each (i, dropdown) ->
$dropdown = $(dropdown) $dropdown = $(dropdown)
projectId = $dropdown.data('project-id') projectId = $dropdown.data('project-id')
milestonesUrl = $dropdown.data('milestones') milestonesUrl = $dropdown.data('milestones')
issueUpdateURL = $dropdown.data('issueUpdate')
selectedMilestone = $dropdown.data('selected') selectedMilestone = $dropdown.data('selected')
showNo = $dropdown.data('show-no') showNo = $dropdown.data('show-no')
showAny = $dropdown.data('show-any') showAny = $dropdown.data('show-any')
showUpcoming = $dropdown.data('show-upcoming')
useId = $dropdown.data('use-id') useId = $dropdown.data('use-id')
defaultLabel = $dropdown.data('default-label') defaultLabel = $dropdown.data('default-label')
issuableId = $dropdown.data('issuable-id')
abilityName = $dropdown.data('ability-name')
$selectbox = $dropdown.closest('.selectbox')
$block = $selectbox.closest('.block')
$sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon')
$value = $block.find('.value')
$loading = $block.find('.block-loading').fadeOut()
if issueUpdateURL
milestoneLinkTemplate = _.template(
'<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>"><%= title %></a>'
)
milestoneLinkNoneTemplate = '<div class="light">None</div>'
$dropdown.glDropdown( $dropdown.glDropdown(
data: (term, callback) -> data: (term, callback) ->
$.ajax( $.ajax(
url: milestonesUrl url: milestonesUrl
).done (data) -> ).done (data) ->
extraOptions = []
if showAny
extraOptions.push(
id: 0
name: ''
title: 'Any Milestone'
)
if showNo if showNo
data.unshift( extraOptions.push(
id: '0' id: -1
name: 'No Milestone'
title: 'No Milestone' title: 'No Milestone'
) )
if showAny if showUpcoming
data.unshift( extraOptions.push(
isAny: true id: -2
title: 'Any Milestone' name: '#upcoming'
title: 'Upcoming'
) )
if data.length > 2 if extraOptions.length > 2
data.splice 2, 0, 'divider' extraOptions.push 'divider'
callback(data) callback(extraOptions.concat(data))
filterable: true filterable: true
search: search:
fields: ['title'] fields: ['title']
...@@ -45,21 +74,51 @@ class @MilestoneSelect ...@@ -45,21 +74,51 @@ class @MilestoneSelect
milestone.title milestone.title
id: (milestone) -> id: (milestone) ->
if !useId if !useId
if !milestone.isAny? milestone.name
milestone.title
else
''
else else
milestone.id milestone.id
isSelected: (milestone) -> isSelected: (milestone) ->
milestone.title is selectedMilestone milestone.name is selectedMilestone
clicked: -> hidden: ->
page = $('body').data 'page' $selectbox.hide()
isIssueIndex = page is 'projects:issues:index'
isMRIndex = page is page is 'projects:merge_requests:index'
if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex) # display:block overrides the hide-collapse rule
$value.removeAttr('style')
clicked: (selected) ->
if $dropdown.hasClass 'js-filter-bulk-update'
return
if $dropdown.hasClass('js-filter-submit')
if selected.name?
selectedMilestone = selected.name
else
selectedMilestone = ''
Issues.filterResults $dropdown.closest('form') Issues.filterResults $dropdown.closest('form')
else if $dropdown.hasClass 'js-filter-submit' else
$dropdown.closest('form').submit() selected = $selectbox
.find('input[type="hidden"]')
.val()
data = {}
data[abilityName] = {}
data[abilityName].milestone_id = selected
$loading
.fadeIn()
$dropdown.trigger('loading.gl.dropdown')
$.ajax(
type: 'PUT'
url: issueUpdateURL
data: data
).done (data) ->
$dropdown.trigger('loaded.gl.dropdown')
$loading.fadeOut()
$selectbox.hide()
$value.removeAttr('style')
if data.milestone?
data.milestone.namespace = _this.currentProject.namespace
data.milestone.path = _this.currentProject.path
$value.html(milestoneLinkTemplate(data.milestone))
$sidebarCollapsedValue.find('span').text(data.milestone.title)
else
$value.html(milestoneLinkNoneTemplate)
$sidebarCollapsedValue.find('span').text('No')
) )
...@@ -251,13 +251,11 @@ class @Notes ...@@ -251,13 +251,11 @@ class @Notes
Sets some hidden fields in the form. Sets some hidden fields in the form.
### ###
setupMainTargetNoteForm: -> setupMainTargetNoteForm: ->
# find the form # find the form
form = $(".js-new-note-form") form = $(".js-new-note-form")
# insert the form after the button # Set a global clone of the form for later cloning
form.clone().replaceAll $(".js-main-target-form") @formClone = form.clone()
form = form.prev("form")
# show the form # show the form
@setupNoteForm(form) @setupNoteForm(form)
...@@ -266,9 +264,7 @@ class @Notes ...@@ -266,9 +264,7 @@ class @Notes
form.removeClass "js-new-note-form" form.removeClass "js-new-note-form"
form.addClass "js-main-target-form" form.addClass "js-main-target-form"
# remove unnecessary fields and buttons
form.find("#note_line_code").remove() form.find("#note_line_code").remove()
form.find(".js-close-discussion-note-form").remove()
### ###
General note form setup. General note form setup.
...@@ -297,7 +293,14 @@ class @Notes ...@@ -297,7 +293,14 @@ class @Notes
else else
previewButton.removeClass("turn-on").addClass "turn-off" 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) autosize(textarea)
new Autosave textarea, [ new Autosave textarea, [
"Note" "Note"
form.find("#note_commit_id").val() form.find("#note_commit_id").val()
...@@ -307,7 +310,6 @@ class @Notes ...@@ -307,7 +310,6 @@ class @Notes
] ]
# remove notify commit author checkbox for non-commit notes # remove notify commit author checkbox for non-commit notes
form.find(".js-notify-commit-author").remove() if form.find("#note_noteable_type").val() isnt "Commit"
GitLab.GfmAutoComplete.setup() GitLab.GfmAutoComplete.setup()
new DropzoneInput(form) new DropzoneInput(form)
form.show() form.show()
...@@ -455,15 +457,15 @@ class @Notes ...@@ -455,15 +457,15 @@ class @Notes
Shows the note form below the notes. Shows the note form below the notes.
### ###
replyToDiscussionNote: (e) => replyToDiscussionNote: (e) =>
form = $(".js-new-note-form") form = @formClone.clone()
replyLink = $(e.target).closest(".js-discussion-reply-button") replyLink = $(e.target).closest(".js-discussion-reply-button")
replyLink.hide() replyLink.hide()
# insert the form after the button # insert the form after the button
form.clone().insertAfter replyLink replyLink.after form
# show the form # show the form
@setupDiscussionNoteForm(replyLink, replyLink.next("form")) @setupDiscussionNoteForm(replyLink, form)
### ###
Shows the diff or discussion form and does some setup on it. Shows the diff or discussion form and does some setup on it.
...@@ -488,7 +490,9 @@ class @Notes ...@@ -488,7 +490,9 @@ class @Notes
.text(form.find('.js-close-discussion-note-form').data('cancel-text')) .text(form.find('.js-close-discussion-note-form').data('cancel-text'))
@setupNoteForm form @setupNoteForm form
form.find(".js-note-text").focus() 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. Called when clicking on the "add a comment" button on the side of a diff line.
...@@ -498,9 +502,8 @@ class @Notes ...@@ -498,9 +502,8 @@ class @Notes
### ###
addDiffNote: (e) => addDiffNote: (e) =>
e.preventDefault() e.preventDefault()
link = e.currentTarget $link = $(e.currentTarget)
form = $(".js-new-note-form") row = $link.closest("tr")
row = $(link).closest("tr")
nextRow = row.next() nextRow = row.next()
hasNotes = nextRow.is(".notes_holder") hasNotes = nextRow.is(".notes_holder")
addForm = false addForm = false
...@@ -509,7 +512,7 @@ class @Notes ...@@ -509,7 +512,7 @@ class @Notes
# In parallel view, look inside the correct left/right pane # In parallel view, look inside the correct left/right pane
if @isParallelView() if @isParallelView()
lineType = $(link).data("lineType") lineType = $link.data("lineType")
targetContent += "." + 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>" 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 ...@@ -531,11 +534,11 @@ class @Notes
addForm = true addForm = true
if addForm if addForm
newForm = form.clone() newForm = @formClone.clone()
newForm.appendTo row.next().find(targetContent) newForm.appendTo row.next().find(targetContent)
# show the form # show the form
@setupDiscussionNoteForm $(link), newForm @setupDiscussionNoteForm $link, newForm
### ###
Called in response to "cancel" on a diff note form. Called in response to "cancel" on a diff note form.
...@@ -560,7 +563,6 @@ class @Notes ...@@ -560,7 +563,6 @@ class @Notes
cancelDiscussionForm: (e) => cancelDiscussionForm: (e) =>
e.preventDefault() e.preventDefault()
form = $(".js-new-note-form")
form = $(e.target).closest(".js-discussion-note-form") form = $(e.target).closest(".js-discussion-note-form")
@removeDiscussionNoteForm(form) @removeDiscussionNoteForm(form)
......
class @Profile class @Profile
constructor: -> constructor: (opts = {}) ->
{
@form = $('.edit-user')
} = opts
# Automatically submit the Preferences form when any of its radio buttons change # Automatically submit the Preferences form when any of its radio buttons change
$('.js-preferences-form').on 'change.preference', 'input[type=radio]', -> $('.js-preferences-form').on 'change.preference', 'input[type=radio]', ->
$(this).parents('form').submit() $(this).parents('form').submit()
...@@ -17,14 +21,46 @@ class @Profile ...@@ -17,14 +21,46 @@ class @Profile
$('.update-notifications').on 'ajax:complete', -> $('.update-notifications').on 'ajax:complete', ->
$(this).find('.btn-save').enable() $(this).find('.btn-save').enable()
$('.js-choose-user-avatar-button').bind "click", -> @bindEvents()
form = $(this).closest("form")
form.find(".js-user-avatar-input").click() cropOpts =
filename: '.js-avatar-filename'
previewImage: '.avatar-image .avatar'
modalCrop: '.modal-profile-crop'
pickImageEl: '.js-choose-user-avatar-button'
uploadImageBtn: '.js-upload-user-avatar'
modalCropImg: '.modal-profile-crop-image'
@avatarGlCrop = $('.js-user-avatar-input').glCrop(cropOpts).data 'glcrop'
bindEvents: ->
@form.on 'submit', @onSubmitForm
onSubmitForm: (e) =>
e.preventDefault()
@saveForm()
saveForm: ->
self = @
formData = new FormData(@form[0])
formData.append('user[avatar]', @avatarGlCrop.getBlob(), 'avatar.png')
$('.js-user-avatar-input').bind "change", -> $.ajax
form = $(this).closest("form") url: @form.attr('action')
filename = $(this).val().replace(/^.*[\\\/]/, '') type: @form.attr('method')
form.find(".js-avatar-filename").text(filename) data: formData
dataType: "json"
processData: false
contentType: false
success: (response) ->
new Flash(response.message, 'notice')
error: (jqXHR) ->
new Flash(jqXHR.responseJSON.message, 'alert')
complete: ->
window.scrollTo 0, 0
# Enable submit button after requests ends
self.form.find(':input[disabled]').enable()
$ -> $ ->
# Extract the SSH Key title from its comment # Extract the SSH Key title from its comment
......
class @Sidebar
constructor: (currentUser) ->
@addEventListeners()
addEventListeners: ->
$('aside').on('click', '.sidebar-collapsed-icon', @sidebarCollapseClicked)
$('.dropdown').on('hidden.gl.dropdown', @sidebarDropdownHidden)
$('.dropdown').on('loading.gl.dropdown', @sidebarDropdownLoading)
$('.dropdown').on('loaded.gl.dropdown', @sidebarDropdownLoaded)
sidebarDropdownLoading: (e) ->
$sidebarCollapsedIcon = $(@).closest('.block').find('.sidebar-collapsed-icon')
img = $sidebarCollapsedIcon.find('img')
i = $sidebarCollapsedIcon.find('i')
$loading = $('<i class="fa fa-spinner fa-spin"></i>')
if img.length
img.before($loading)
img.hide()
else if i.length
i.before($loading)
i.hide()
sidebarDropdownLoaded: (e) ->
$sidebarCollapsedIcon = $(@).closest('.block').find('.sidebar-collapsed-icon')
img = $sidebarCollapsedIcon.find('img')
$sidebarCollapsedIcon.find('i.fa-spin').remove()
i = $sidebarCollapsedIcon.find('i')
if img.length
img.show()
else
i.show()
sidebarCollapseClicked: (e) ->
e.preventDefault()
$block = $(@).closest('.block')
$('aside')
.find('.gutter-toggle')
.trigger('click')
$editLink = $block.find('.edit-link')
if $editLink.length
$editLink.trigger('click')
$block.addClass('collapse-after-update')
$('.page-with-sidebar').addClass('with-overlay')
sidebarDropdownHidden: (e) ->
$block = $(@).closest('.block')
if $block.hasClass('collapse-after-update')
$block.removeClass('collapse-after-update')
$('.page-with-sidebar').removeClass('with-overlay')
$('aside')
.find('.gutter-toggle')
.trigger('click')
\ No newline at end of file
class @SearchAutocomplete class @SearchAutocomplete
constructor: (search_autocomplete_path, project_id, project_ref) ->
project_id = '' unless project_id KEYCODE =
project_ref = '' unless project_ref ESCAPE: 27
query = "?project_id=" + project_id + "&project_ref=" + project_ref BACKSPACE: 8
ENTER: 13
$("#search").autocomplete
source: search_autocomplete_path + query constructor: (opts = {}) ->
minLength: 1 {
select: (event, ui) -> @wrap = $('.search')
location.href = ui.item.url
@optsEl = @wrap.find('.search-autocomplete-opts')
@autocompletePath = @optsEl.data('autocomplete-path')
@projectId = @optsEl.data('autocomplete-project-id') || ''
@projectRef = @optsEl.data('autocomplete-project-ref') || ''
} = opts
# Dropdown Element
@dropdown = @wrap.find('.dropdown')
@dropdownContent = @dropdown.find('.dropdown-content')
@locationBadgeEl = @getElement('.search-location-badge')
@locationText = @getElement('.location-text')
@scopeInputEl = @getElement('#scope')
@searchInput = @getElement('.search-input')
@projectInputEl = @getElement('#search_project_id')
@groupInputEl = @getElement('#group_id')
@searchCodeInputEl = @getElement('#search_code')
@repositoryInputEl = @getElement('#repository_ref')
@clearInput = @getElement('.js-clear-input')
@saveOriginalState()
# Only when user is logged in
@createAutocomplete() if gon.current_user_id
@searchInput.addClass('disabled')
@saveTextLength()
@bindEvents()
# Finds an element inside wrapper element
getElement: (selector) ->
@wrap.find(selector)
saveOriginalState: ->
@originalState = @serializeState()
saveTextLength: ->
@lastTextLength = @searchInput.val().length
createAutocomplete: ->
@searchInput.glDropdown
filterInputBlur: false
filterable: true
filterRemote: true
highlight: true
enterCallback: false
filterInput: 'input#search'
search:
fields: ['text']
data: @getData.bind(@)
getData: (term, callback) ->
_this = @
# Do not trigger request if input is empty
return if @searchInput.val() is ''
# Prevent multiple ajax calls
return if @loadingSuggestions
@loadingSuggestions = true
jqXHR = $.get(@autocompletePath, {
project_id: @projectId
project_ref: @projectRef
term: term
}, (response) ->
# Hide dropdown menu if no suggestions returns
if !response.length
_this.disableAutocomplete()
return
data = []
# List results
firstCategory = true
for suggestion in response
# Add group header before list each group
if lastCategory isnt suggestion.category
data.push 'separator' if !firstCategory
firstCategory = false if firstCategory
data.push
header: suggestion.category
lastCategory = suggestion.category
data.push
text: suggestion.label
url: suggestion.url
# Add option to proceed with the search
if data.length
data.push('separator')
data.push
text: "Result name contains \"#{term}\""
url: "/search?\
search=#{term}\
&project_id=#{_this.projectInputEl.val()}\
&group_id=#{_this.groupInputEl.val()}"
callback(data)
).always ->
_this.loadingSuggestions = false
serializeState: ->
{
# Search Criteria
search_project_id: @projectInputEl.val()
group_id: @groupInputEl.val()
search_code: @searchCodeInputEl.val()
repository_ref: @repositoryInputEl.val()
scope: @scopeInputEl.val()
# Location badge
_location: @locationText.text()
}
bindEvents: ->
@searchInput.on 'keydown', @onSearchInputKeyDown
@searchInput.on 'keyup', @onSearchInputKeyUp
@searchInput.on 'click', @onSearchInputClick
@searchInput.on 'focus', @onSearchInputFocus
@searchInput.on 'blur', @onSearchInputBlur
@clearInput.on 'click', @onRemoveLocationClick
enableAutocomplete: ->
# No need to enable anything if user is not logged in
return if !gon.current_user_id
_this = @
@loadingSuggestions = false
@dropdown.addClass('open')
@searchInput.removeClass('disabled')
onSearchInputKeyDown: =>
# Saves last length of the entered text
@saveTextLength()
onSearchInputKeyUp: (e) =>
switch e.keyCode
when KEYCODE.BACKSPACE
# when trying to remove the location badge
if @lastTextLength is 0 and @badgePresent()
@removeLocationBadge()
# When removing the last character and no badge is present
if @lastTextLength is 1
@disableAutocomplete()
# When removing any character from existin value
if @lastTextLength > 1
@enableAutocomplete()
when KEYCODE.ESCAPE
@restoreOriginalState()
else
# Handle the case when deleting the input value other than backspace
# e.g. Pressing ctrl + backspace or ctrl + x
if @searchInput.val() is ''
@disableAutocomplete()
else
# We should display the menu only when input is not empty
@enableAutocomplete()
# Avoid falsy value to be returned
return
onSearchInputClick: (e) =>
# Prevents closing the dropdown menu
e.stopImmediatePropagation()
onSearchInputFocus: =>
@wrap.addClass('search-active')
onRemoveLocationClick: (e) =>
e.preventDefault()
@removeLocationBadge()
@searchInput.val('').focus()
@skipBlurEvent = true
onSearchInputBlur: (e) =>
@skipBlurEvent = false
# 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)
addLocationBadge: (item) ->
category = if item.category? then "#{item.category}: " else ''
value = if item.value? then item.value else ''
html = "<span class='location-badge'>
<i class='location-text'>#{category}#{value}</i>
</span>"
@locationBadgeEl.html(html)
@wrap.addClass('has-location-badge')
restoreOriginalState: ->
inputs = Object.keys @originalState
for input in inputs
@getElement("##{input}").val(@originalState[input])
if @originalState._location is ''
@locationBadgeEl.empty()
else
@addLocationBadge(
value: @originalState._location
)
@dropdown.removeClass 'open'
badgePresent: ->
@locationBadgeEl.children().length
resetSearchState: ->
inputs = Object.keys @originalState
for input in inputs
# _location isnt a input
break if input is '_location'
@getElement("##{input}").val('')
removeLocationBadge: ->
@locationBadgeEl.empty()
# Reset state
@resetSearchState()
@wrap.removeClass('has-location-badge')
disableAutocomplete: ->
@searchInput.addClass('disabled')
@dropdown.removeClass('open')
@restoreMenu()
restoreMenu: ->
html = "<ul>
<li><a class='dropdown-menu-empty-link is-focused'>Loading...</a></li>
</ul>"
@dropdownContent.html(html)
...@@ -4,8 +4,6 @@ expanded = 'page-sidebar-expanded' ...@@ -4,8 +4,6 @@ expanded = 'page-sidebar-expanded'
toggleSidebar = -> toggleSidebar = ->
$('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}") $('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
$('header').toggleClass("header-collapsed header-expanded") $('header').toggleClass("header-collapsed header-expanded")
$('.sidebar-wrapper').toggleClass("sidebar-collapsed sidebar-expanded")
$('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' }) $.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
setTimeout ( -> setTimeout ( ->
......
...@@ -95,4 +95,4 @@ window.ContributorsStatGraphUtil = ...@@ -95,4 +95,4 @@ window.ContributorsStatGraphUtil =
if date_range is null || date_range[0] <= new Date(date) <= date_range[1] if date_range is null || date_range[0] <= new Date(date) <= date_range[1]
true true
else else
false false
\ No newline at end of file
...@@ -6,10 +6,12 @@ class @Todos ...@@ -6,10 +6,12 @@ class @Todos
clearListeners: -> clearListeners: ->
$('.done-todo').off('click') $('.done-todo').off('click')
$('.js-todos-mark-all').off('click') $('.js-todos-mark-all').off('click')
$('.todo').off('click')
initBtnListeners: -> initBtnListeners: ->
$('.done-todo').on('click', @doneClicked) $('.done-todo').on('click', @doneClicked)
$('.js-todos-mark-all').on('click', @allDoneClicked) $('.js-todos-mark-all').on('click', @allDoneClicked)
$('.todo').on('click', @goToTodoUrl)
doneClicked: (e) => doneClicked: (e) =>
e.preventDefault() e.preventDefault()
...@@ -54,3 +56,6 @@ class @Todos ...@@ -54,3 +56,6 @@ class @Todos
updateBadges: (data) -> updateBadges: (data) ->
$('.todos-pending .badge, .todos-pending-count').text data.count $('.todos-pending .badge, .todos-pending-count').text data.count
$('.todos-done .badge').text data.done_count $('.todos-done .badge').text data.done_count
goToTodoUrl: ->
Turbolinks.visit($(this).data('url'))
class @UsersSelect class @UsersSelect
constructor: -> constructor: (currentUser) ->
@usersPath = "/autocomplete/users.json" @usersPath = "/autocomplete/users.json"
@userPath = "/autocomplete/users/:id.json" @userPath = "/autocomplete/users/:id.json"
if currentUser?
@currentUser = JSON.parse(currentUser)
$('.js-user-search').each (i, dropdown) => $('.js-user-search').each (i, dropdown) =>
$dropdown = $(dropdown) $dropdown = $(dropdown)
...@@ -12,6 +14,81 @@ class @UsersSelect ...@@ -12,6 +14,81 @@ class @UsersSelect
firstUser = $dropdown.data('first-user') firstUser = $dropdown.data('first-user')
selectedId = $dropdown.data('selected') selectedId = $dropdown.data('selected')
defaultLabel = $dropdown.data('default-label') defaultLabel = $dropdown.data('default-label')
issueURL = $dropdown.data('issueUpdate')
$selectbox = $dropdown.closest('.selectbox')
$block = $selectbox.closest('.block')
abilityName = $dropdown.data('ability-name')
$value = $block.find('.value')
$collapsedSidebar = $block.find('.sidebar-collapsed-user')
$loading = $block.find('.block-loading').fadeOut()
$block.on('click', '.js-assign-yourself', (e) =>
e.preventDefault()
assignTo(@currentUser.id)
)
assignTo = (selected) ->
data = {}
data[abilityName] = {}
data[abilityName].assignee_id = selected
$loading
.fadeIn()
$dropdown.trigger('loading.gl.dropdown')
$.ajax(
type: 'PUT'
dataType: 'json'
url: issueURL
data: data
).done (data) ->
$dropdown.trigger('loaded.gl.dropdown')
$loading.fadeOut()
$selectbox.hide()
if data.assignee
user =
name: data.assignee.name
username: data.assignee.username
avatar: data.assignee.avatar_url
else
user =
name: 'Unassigned'
username: ''
avatar: ''
$value.html(assigneeTemplate(user))
$collapsedSidebar.html(collapsedAssigneeTemplate(user))
collapsedAssigneeTemplate = _.template(
'<% if( avatar ) { %>
<a class="author_link" href="/u/<%= username %>">
<img width="24" class="avatar avatar-inline s24" alt="" src="<%= avatar %>">
<span class="author">Toni Boehm</span>
</a>
<% } else { %>
<i class="fa fa-user"></i>
<% } %>'
)
assigneeTemplate = _.template(
'<% if (username) { %>
<a class="author_link " href="/u/<%= username %>">
<% if( avatar ) { %>
<img width="32" class="avatar avatar-inline s32" alt="" src="<%= avatar %>">
<% } %>
<span class="author"><%= name %></span>
<span class="username">
@<%= username %>
</span>
</a>
<% } else { %>
<span class="assign-yourself">
No assignee -
<a href="#" class="js-assign-yourself">
assign yourself
</a>
</span>
<% } %>'
)
$dropdown.glDropdown( $dropdown.glDropdown(
data: (term, callback) => data: (term, callback) =>
...@@ -30,6 +107,7 @@ class @UsersSelect ...@@ -30,6 +107,7 @@ class @UsersSelect
if showNullUser if showNullUser
showDivider += 1 showDivider += 1
users.unshift( users.unshift(
beforeDivider: true
name: 'Unassigned', name: 'Unassigned',
id: 0 id: 0
) )
...@@ -39,6 +117,7 @@ class @UsersSelect ...@@ -39,6 +117,7 @@ class @UsersSelect
name = showAnyUser name = showAnyUser
name = 'Any User' if name == true name = 'Any User' if name == true
anyUser = { anyUser = {
beforeDivider: true
name: name, name: name,
id: null id: null
} }
...@@ -55,40 +134,73 @@ class @UsersSelect ...@@ -55,40 +134,73 @@ class @UsersSelect
fields: ['name', 'username'] fields: ['name', 'username']
selectable: true selectable: true
fieldName: $dropdown.data('field-name') fieldName: $dropdown.data('field-name')
toggleLabel: (selected) -> toggleLabel: (selected) ->
if selected && 'id' of selected if selected && 'id' of selected
selected.name selected.name
else else
defaultLabel defaultLabel
clicked: ->
inputId: 'issue_assignee_id'
hidden: (e) ->
$selectbox.hide()
# display:block overrides the hide-collapse rule
$value.removeAttr('style')
clicked: (user) ->
page = $('body').data 'page' page = $('body').data 'page'
isIssueIndex = page is 'projects:issues:index' isIssueIndex = page is 'projects:issues:index'
isMRIndex = page is page is 'projects:merge_requests:index' isMRIndex = page is page is 'projects:merge_requests:index'
if $dropdown.hasClass('js-filter-bulk-update')
return
if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex) if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
selectedId = user.id
Issues.filterResults $dropdown.closest('form') Issues.filterResults $dropdown.closest('form')
else if $dropdown.hasClass 'js-filter-submit' else if $dropdown.hasClass 'js-filter-submit'
$dropdown.closest('form').submit() $dropdown.closest('form').submit()
else
selected = $dropdown
.closest('.selectbox')
.find("input[name='#{$dropdown.data('field-name')}']").val()
assignTo(selected)
renderRow: (user) -> renderRow: (user) ->
username = if user.username then "@#{user.username}" else "" username = if user.username then "@#{user.username}" else ""
avatar = if user.avatar_url then user.avatar_url else false avatar = if user.avatar_url then user.avatar_url else false
selected = if user.id is selectedId then "is-active" else "" selected = if user.id is selectedId then "is-active" else ""
img = "" img = ""
if avatar if user.beforeDivider?
img = "<img src='#{avatar}' class='avatar avatar-inline' width='30' />" "<li>
<a href='#' class='#{selected}'>
#{user.name}
</a>
</li>"
else
if avatar
img = "<img src='#{avatar}' class='avatar avatar-inline' width='30' />"
"<li> # split into three parts so we can remove the username section if nessesary
listWithName = "<li>
<a href='#' class='dropdown-menu-user-link #{selected}'> <a href='#' class='dropdown-menu-user-link #{selected}'>
#{img} #{img}
<strong class='dropdown-menu-user-full-name'> <strong class='dropdown-menu-user-full-name'>
#{user.name} #{user.name}
</strong> </strong>"
<span class='dropdown-menu-user-username'>
listWithUserName = "<span class='dropdown-menu-user-username'>
#{username} #{username}
</span> </span>"
</a> listClosingTags = "</a>
</li>" </li>"
if username is ''
listWithUserName = ''
listWithName + listWithUserName + listClosingTags
) )
$('.ajax-users-select').each (i, select) => $('.ajax-users-select').each (i, select) =>
......
...@@ -42,7 +42,7 @@ class @ZenMode ...@@ -42,7 +42,7 @@ class @ZenMode
$(e.currentTarget).trigger('zen_mode:leave') $(e.currentTarget).trigger('zen_mode:leave')
$(document).on 'zen_mode:enter', (e) => $(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) => $(document).on 'zen_mode:leave', (e) =>
@exit() @exit()
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
*= require_self *= require_self
*= require dropzone/basic *= require dropzone/basic
*= require cal-heatmap *= require cal-heatmap
*= require cropper.css
*= require animate
*/ */
/* /*
......
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
// Toggle between two states. // Toggle between two states.
.js-toggler-container { .js-toggler-container {
.turn-on { display: block; } .turn-on { display: block; }
.turn-off { display: none; } .turn-off { display: none; }
&.on { &.on {
.turn-on { display: none; } .turn-on { display: none; }
.turn-off { display: block; } .turn-off { display: block; }
} }
} }
...@@ -107,10 +107,28 @@ ...@@ -107,10 +107,28 @@
margin: 0; margin: 0;
font-size: 23px; font-size: 23px;
font-weight: normal; font-weight: normal;
margin: 16px 0 5px 0; margin: 16px 0 5px;
color: #4c4e54; color: #4c4e54;
font-size: 23px; font-size: 23px;
line-height: 1.1; line-height: 1.1;
h1 {
color: #313236;
margin-bottom: 6px;
font-size: 23px;
}
.visibility-icon {
display: inline-block;
margin-left: 5px;
font-size: 18px;
color: $gray;
}
p {
padding: 0 $gl-padding;
color: #5c5d5e;
}
} }
.cover-desc { .cover-desc {
......
.calender-block {
@media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) {
overflow-x: scroll;
}
}
.user-calendar-activities { .user-calendar-activities {
.calendar_onclick_hr { .calendar_onclick_hr {
padding: 0; padding: 0;
......
...@@ -121,17 +121,10 @@ p.time { ...@@ -121,17 +121,10 @@ p.time {
text-shadow: none; text-shadow: none;
} }
.thin_area{ .thin_area {
height: 150px; height: 150px;
} }
// Fixes alignment on notes.
.new_note {
label {
text-align: left;
}
}
// Fix issue with notes & lists creating a bunch of bottom borders. // Fix issue with notes & lists creating a bunch of bottom borders.
li.note { li.note {
img { max-width: 100% } img { max-width: 100% }
...@@ -148,7 +141,7 @@ li.note { ...@@ -148,7 +141,7 @@ li.note {
} }
} }
.wiki_content code, .readme code{ .wiki_content code, .readme code {
background-color: inherit; background-color: inherit;
} }
...@@ -292,8 +285,11 @@ table { ...@@ -292,8 +285,11 @@ table {
} }
.btn-sign-in { .btn-sign-in {
margin-top: 10px;
text-shadow: none; text-shadow: none;
@media (min-width: $screen-sm-min) {
margin-top: 11px;
}
} }
.side-filters { .side-filters {
...@@ -375,7 +371,7 @@ table { ...@@ -375,7 +371,7 @@ table {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
width: 250px !important; min-width: 250px;
visibility: hidden; visibility: hidden;
} }
} }
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
font-size: 15px; font-size: 15px;
text-align: left; text-align: left;
border: 1px solid $dropdown-toggle-border-color; border: 1px solid $dropdown-toggle-border-color;
border-radius: 2px; border-radius: $dropdown-border-radius;
outline: 0; outline: 0;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
...@@ -75,12 +75,12 @@ ...@@ -75,12 +75,12 @@
width: 240px; width: 240px;
margin-top: 2px; margin-top: 2px;
margin-bottom: 0; margin-bottom: 0;
padding: 10px 10px; font-size: 15px;
font-size: 14px;
font-weight: normal; font-weight: normal;
padding: 10px 0;
background-color: $dropdown-bg; background-color: $dropdown-bg;
border: 1px solid $dropdown-border-color; border: 1px solid $dropdown-border-color;
border-radius: $border-radius-base; border-radius: $dropdown-border-radius;
box-shadow: 0 2px 4px $dropdown-shadow-color; box-shadow: 0 2px 4px $dropdown-shadow-color;
&.is-loading { &.is-loading {
...@@ -101,9 +101,17 @@ ...@@ -101,9 +101,17 @@
li { li {
text-align: left; text-align: left;
list-style: none; list-style: none;
padding: 0 10px;
} }
.divider { .divider {
height: 1px;
margin: 8px 10px;
padding: 0;
background-color: $dropdown-divider-color;
}
.separator {
width: 100%; width: 100%;
height: 1px; height: 1px;
margin-top: 8px; margin-top: 8px;
...@@ -130,6 +138,27 @@ ...@@ -130,6 +138,27 @@
text-decoration: none; text-decoration: none;
outline: 0; outline: 0;
} }
&.dropdown-menu-empty-link {
&.is-focused {
background-color: $dropdown-empty-row-bg;
}
}
&.dropdown-menu-user-link {
line-height: 16px;
}
}
.dropdown-header {
color: $dropdown-header-color;
font-size: 13px;
line-height: 22px;
padding: 0 10px 10px;
}
.separator + .dropdown-header {
padding-top: 2px;
} }
} }
...@@ -148,6 +177,10 @@ ...@@ -148,6 +177,10 @@
.dropdown-menu-back { .dropdown-menu-back {
display: block; display: block;
} }
.dropdown-content {
padding: 0 10px;
}
} }
} }
...@@ -161,13 +194,13 @@ ...@@ -161,13 +194,13 @@
} }
.dropdown-menu-user-link { .dropdown-menu-user-link {
padding-top: 7px; padding-top: 10px;
padding-bottom: 7px; padding-bottom: 7px;
} }
.dropdown-menu-user-full-name { .dropdown-menu-user-full-name {
display: block; display: block;
font-weight: 600; font-weight: 500;
line-height: 16px; line-height: 16px;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
...@@ -183,7 +216,7 @@ ...@@ -183,7 +216,7 @@
} }
.dropdown-select { .dropdown-select {
width: 280px; width: $dropdown-width;
} }
.dropdown-menu-align-right { .dropdown-menu-align-right {
...@@ -212,20 +245,11 @@ ...@@ -212,20 +245,11 @@
} }
} }
.dropdown-header {
padding-left: 5px;
padding-right: 5px;
color: $dropdown-header-color;
font-size: 13px;
line-height: 22px;
}
.dropdown-title { .dropdown-title {
position: relative; position: relative;
margin-bottom: 10px; padding: 0 0 15px;
padding-left: 30px; margin: 0 10px 10px;
padding-right: 30px;
padding-bottom: 10px;
font-weight: 600; font-weight: 600;
line-height: 1; line-height: 1;
text-align: center; text-align: center;
...@@ -237,7 +261,7 @@ ...@@ -237,7 +261,7 @@
.dropdown-title-button { .dropdown-title-button {
position: absolute; position: absolute;
top: -1px; top: 0;
padding: 0; padding: 0;
color: $dropdown-title-btn-color; color: $dropdown-title-btn-color;
font-size: 14px; font-size: 14px;
...@@ -251,25 +275,49 @@ ...@@ -251,25 +275,49 @@
} }
.dropdown-menu-close { .dropdown-menu-close {
right: 0; right: 7px;
width: 20px;
height: 20px;
top: -1px;
} }
.dropdown-menu-back { .dropdown-menu-back {
left: 0; left: 7px;
top: 2px;
} }
.dropdown-input { .dropdown-input {
position: relative; position: relative;
margin-bottom: 10px; margin-bottom: 10px;
padding: 0 10px;
.fa { .fa {
position: absolute; position: absolute;
top: 10px; top: 10px;
right: 10px; right: 20px;
color: #c7c7c7; color: #c7c7c7;
font-size: 12px; font-size: 12px;
pointer-events: none; pointer-events: none;
} }
.dropdown-input-clear {
display: none;
cursor: pointer;
pointer-events: all;
right: 22px;
top: 9px;
font-size: 14px;
}
&.has-value {
.dropdown-input-clear {
display: block;
}
.dropdown-input-search {
display: none;
}
}
} }
.dropdown-input-field { .dropdown-input-field {
...@@ -286,13 +334,13 @@ ...@@ -286,13 +334,13 @@
border-color: $dropdown-input-focus-border; border-color: $dropdown-input-focus-border;
box-shadow: 0 0 4px $dropdown-input-focus-shadow; box-shadow: 0 0 4px $dropdown-input-focus-shadow;
+ .fa { ~ .fa {
color: $dropdown-link-color; color: $dropdown-link-color;
} }
} }
&:hover { &:hover {
+ .fa { ~ .fa {
color: $dropdown-link-color; color: $dropdown-link-color;
} }
} }
...@@ -338,11 +386,12 @@ ...@@ -338,11 +386,12 @@
} }
} }
.dropdown-menu-labels { .dropdown-label-box {
.label { position: relative;
position: relative; top: 3px;
width: 30px; margin-right: 5px;
margin-right: 5px; display: inline-block;
text-indent: -99999px; width: 15px;
} height: 15px;
border-radius: $border-radius-base;
} }
...@@ -3,12 +3,10 @@ ...@@ -3,12 +3,10 @@
* *
*/ */
.file-holder { .file-holder {
border: none;
border: 1px solid $border-color; border: 1px solid $border-color;
&.readme-holder { &.readme-holder {
margin-top: 10px; margin: $gl-padding-top 0;
border-bottom: 0;
} }
table { table {
...@@ -50,6 +48,10 @@ ...@@ -50,6 +48,10 @@
} }
} }
a {
color: $gl-dark-link-color;
}
.left-options { .left-options {
margin-top: -3px; margin-top: -3px;
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
vertical-align: top; vertical-align: top;
} }
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
.issues-filters, .issues-filters,
.issues_bulk_update { .issues_bulk_update {
.dropdown-menu-toggle { .dropdown-menu-toggle {
...@@ -11,3 +11,11 @@ ...@@ -11,3 +11,11 @@
} }
} }
} }
@media (max-width: $screen-xs-max) {
.filter-item {
display: block;
margin: 0 0 10px;
}
}
// Disabling "SpaceAfterPropertyColon" linter because the linter doesn't like
// the way the `src` property is formatted in this file.
// scss-lint:disable SpaceAfterPropertyColon
/* latin-ext */ /* latin-ext */
@font-face { @font-face {
font-family: 'Source Sans Pro'; font-family: 'Source Sans Pro';
......
...@@ -6,40 +6,6 @@ input { ...@@ -6,40 +6,6 @@ input {
border-radius: $border-radius-base; border-radius: $border-radius-base;
} }
input[type='search'] {
background-color: white;
padding-left: 10px;
}
input[type='search'].search-input {
background-repeat: no-repeat;
background-position: 10px;
background-size: 16px;
background-position-x: 30%;
padding-left: 10px;
background-color: $gray-light;
&.search-input[value=""] {
background-image: url('data:image/png;base64,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');
}
&.search-input::-webkit-input-placeholder {
text-align: center;
}
&.search-input:-moz-placeholder { /* Firefox 18- */
text-align: center;
}
&.search-input::-moz-placeholder { /* Firefox 19+ */
text-align: center;
}
&.search-input:-ms-input-placeholder {
text-align: center;
}
}
input[type='text'].danger { input[type='text'].danger {
background: #f2dede!important; background: #f2dede!important;
border-color: #d66; border-color: #d66;
...@@ -125,7 +91,7 @@ label { ...@@ -125,7 +91,7 @@ label {
} }
.form-control::-webkit-input-placeholder { .form-control::-webkit-input-placeholder {
color: #7f8fa4; color: $gl-placeholder-color;
} }
.input-group { .input-group {
......
...@@ -33,10 +33,15 @@ ...@@ -33,10 +33,15 @@
background: $color; background: $color;
} }
.complex-sidebar .nav-primary {
border-right: 1px solid lighten($color, 3%);
}
.sidebar-wrapper { .sidebar-wrapper {
background: $color-darker; background: $color-darker;
.sidebar-user { .sidebar-user {
border-top: 1px solid lighten($color, 3%);
background: $color-darker; background: $color-darker;
color: $color-light; color: $color-light;
...@@ -62,7 +67,6 @@ ...@@ -62,7 +67,6 @@
.count { .count {
color: $color-light; color: $color-light;
background: $color-dark;
} }
} }
...@@ -117,4 +121,4 @@ body { ...@@ -117,4 +121,4 @@ body {
&.ui_violet { &.ui_violet {
@include gitlab-theme(#98c, $theme-violet, #436, #325); @include gitlab-theme(#98c, $theme-violet, #436, #325);
} }
} }
\ No newline at end of file
...@@ -36,7 +36,7 @@ header { ...@@ -36,7 +36,7 @@ header {
padding: 0; padding: 0;
.nav > li > a { .nav > li > a {
color: #7f8fa4; color: $gl-icon-color;
font-size: 18px; font-size: 18px;
padding: 0; padding: 0;
margin: ($header-height - 28) / 2 0; margin: ($header-height - 28) / 2 0;
...@@ -62,7 +62,7 @@ header { ...@@ -62,7 +62,7 @@ header {
background-color: #eee; background-color: #eee;
} }
&.active { &.active {
color: #7f8fa4; color: $gl-icon-color;
} }
} }
} }
...@@ -70,20 +70,25 @@ header { ...@@ -70,20 +70,25 @@ header {
.header-content { .header-content {
height: $header-height; height: $header-height;
padding-right: 20px;
@media (min-width: $screen-sm-min) {
padding-right: 0;
}
.title { .title {
margin: 0; margin: 0;
font-size: 19px; font-size: 19px;
line-height: $header-height; line-height: $header-height;
font-weight: normal; font-weight: normal;
color: #4c4e54; color: $gl-text-color;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
vertical-align: top; vertical-align: top;
white-space: nowrap; white-space: nowrap;
a { a {
color: #4c4e54; color: $gl-text-color;
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
...@@ -112,37 +117,17 @@ header { ...@@ -112,37 +117,17 @@ header {
} }
} }
.search {
margin-right: 10px;
margin-left: 10px;
margin-top: ($header-height - 36) / 2;
form {
margin: 0;
padding: 0;
}
.search-input {
width: 220px;
&:focus {
@include box-shadow(none);
outline: none;
}
}
}
.impersonation i { .impersonation i {
color: $red-normal; color: $red-normal;
} }
} }
@mixin collapsed-header { @mixin collapsed-header {
margin-left: $sidebar_collapsed_width; margin-left: 40px;
} }
.header-collapsed { .header-collapsed {
margin-left: $sidebar_collapsed_width; margin-left: 40px;
@media (min-width: $screen-md-min) { @media (min-width: $screen-md-min) {
@include collapsed-header; @include collapsed-header;
......
...@@ -16,7 +16,7 @@ body { ...@@ -16,7 +16,7 @@ body {
} }
.container .content { .container .content {
margin: 0 0; margin: 0;
} }
.navless-container { .navless-container {
......
.div-dropzone-wrapper { .div-dropzone-wrapper {
.div-dropzone { .div-dropzone {
position: relative; position: relative;
padding: 0; margin-bottom: -5px;
border: 0;
margin-bottom: 5px;
.div-dropzone-focus { .div-dropzone-focus {
border-color: #66afe9 !important; border-color: #66afe9 !important;
...@@ -25,12 +23,10 @@ ...@@ -25,12 +23,10 @@
.div-dropzone-spinner { .div-dropzone-spinner {
position: absolute; position: absolute;
top: 100%; bottom: 10px;
left: 100%; right: 5px;
margin-top: -1.1em;
margin-left: -1.1em;
opacity: 0; opacity: 0;
font-size: 30px; font-size: 20px;
transition: opacity 200ms ease-in-out; transition: opacity 200ms ease-in-out;
} }
...@@ -65,17 +61,29 @@ ...@@ -65,17 +61,29 @@
position: relative; position: relative;
} }
.md-header {
.nav-links {
.active {
a {
border-bottom-color: #000;
}
}
a {
padding-top: 0;
line-height: 1;
}
}
}
.referenced-users { .referenced-users {
color: #4c4e54; color: #4c4e54;
padding-top: 10px; padding-top: 10px;
} }
.md-preview-holder { .md-preview-holder {
background: #fff; min-height: 167px;
border: 1px solid #ddd; padding: 10px 0;
min-height: 169px;
padding: 5px;
box-shadow: none;
} }
.markdown-area { .markdown-area {
......
/** /**
* Generic mixins * Generic mixins
*/ */
@mixin box-shadow($shadow) { @mixin box-shadow($shadow) {
-webkit-box-shadow: $shadow; -webkit-box-shadow: $shadow;
-moz-box-shadow: $shadow; -moz-box-shadow: $shadow;
-ms-box-shadow: $shadow; -ms-box-shadow: $shadow;
......
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
} }
.page-title { .page-title {
.note_created_ago, .new-issue-link { .note-created-ago, .new-issue-link {
display: none; display: none;
} }
} }
...@@ -116,7 +116,7 @@ ...@@ -116,7 +116,7 @@
display: none; display: none;
} }
aside:not(.right-sidebar){ aside:not(.right-sidebar) {
display: none; display: none;
} }
......
...@@ -56,6 +56,17 @@ ...@@ -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 { .nav-links {
display: inline-block; display: inline-block;
width: 50%; width: 50%;
...@@ -100,13 +111,18 @@ ...@@ -100,13 +111,18 @@
> form { > form {
display: inline-block; display: inline-block;
margin-top: -1px;
}
.icon-label {
display: none;
} }
input { input {
height: 34px; height: 34px;
display: inline-block; display: inline-block;
position: relative; position: relative;
top: 1px; top: 2px;
margin-right: $gl-padding-top; margin-right: $gl-padding-top;
/* Medium devices (desktops, 992px and up) */ /* Medium devices (desktops, 992px and up) */
...@@ -124,9 +140,38 @@ ...@@ -124,9 +140,38 @@
} }
} }
/* Hide on extra small devices (phones) */
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
display: none; padding-bottom: 0;
.btn, form, .dropdown, .dropdown-menu-toggle, .form-control {
margin: 0 0 10px;
display: block;
width: 100%;
}
form {
display: block;
height: auto;
input {
width: 100%;
margin: 0 0 10px;
}
}
.input-short {
width: 100%;
}
.icon-label {
display: inline-block;
}
// Applies on /dashboard/issues
.project-item-select-holder {
display: block;
margin: 0;
}
} }
/* Small devices (tablets, 768px and lower) */ /* Small devices (tablets, 768px and lower) */
......
...@@ -44,13 +44,14 @@ ...@@ -44,13 +44,14 @@
@include box-shadow(rgba(76, 86, 103, 0.247059) 0 0 1px 0, rgba(31, 37, 50, 0.317647) 0 2px 18px 0); @include box-shadow(rgba(76, 86, 103, 0.247059) 0 0 1px 0, rgba(31, 37, 50, 0.317647) 0 2px 18px 0);
@include border-radius ($border-radius-default); @include border-radius ($border-radius-default);
border: none; border: none;
min-width: 175px;
} }
.select2-results .select2-result-label { .select2-results .select2-result-label {
padding: 10px 15px; padding: 10px 15px;
} }
.select2-drop{ .select2-drop {
color: #7f8fa4; color: #7f8fa4;
} }
......
#logo {
z-index: 2;
position: absolute;
width: 58px;
cursor: pointer;
}
.page-with-sidebar { .page-with-sidebar {
padding-top: $header-height; padding-top: $header-height;
transition-duration: .3s; transition-duration: .3s;
...@@ -18,28 +25,10 @@ ...@@ -18,28 +25,10 @@
position: absolute; position: absolute;
left: 0; left: 0;
} }
#logo {
z-index: 2;
position: absolute;
width: 58px;
cursor: pointer;
}
&.right-sidebar-expanded {
/* Extra small devices (phones, less than 768px) */
/* No media query since this is the default in Bootstrap */
padding-right: 0;
/* Small devices (tablets, 768px and up) */
@media (min-width: $screen-sm-min) {
padding-right: $gutter_width;
}
}
} }
.sidebar-wrapper { .sidebar-wrapper {
z-index: 999; z-index: 1000;
background: $background-color; background: $background-color;
} }
...@@ -155,7 +144,7 @@ ...@@ -155,7 +144,7 @@
} }
a { a {
padding: 7px 15px; padding: 7px 12px;
font-size: $gl-font-size; font-size: $gl-font-size;
line-height: 24px; line-height: 24px;
color: $gray; color: $gray;
...@@ -180,10 +169,12 @@ ...@@ -180,10 +169,12 @@
} }
.count { .count {
float: right; &:before {
background: #eee; content: '(';
padding: 0 8px; }
@include border-radius(6px); &:after {
content: ')';
}
} }
&.back-link i { &.back-link i {
...@@ -202,20 +193,54 @@ ...@@ -202,20 +193,54 @@
} }
} }
@mixin expanded-sidebar { .expand-nav a {
padding-left: $sidebar_collapsed_width; color: $gl-icon-color;
width: 60px;
position: fixed;
top: 0;
left: 0;
font-size: 20px;
background: #fff;
height: 59px;
text-align: center;
line-height: 59px;
border-bottom: 1px solid #eee;
transition-duration: .3s;
outline: none;
z-index: 100;
@media (min-width: $screen-md-min) { &:hover {
padding-left: $sidebar_width; text-decoration: none;
} }
}
&.right-sidebar-collapsed { .collapse-nav a {
/* Extra small devices (phones, less than 768px) */ width: $sidebar_width;
padding-right: 0; position: fixed;
/* Small devices (tablets, 768px and up) */ bottom: 0;
@media (min-width: $screen-sm-min) { left: 0;
padding-right: $sidebar_collapsed_width; font-size: 13px;
} background: transparent;
height: 40px;
text-align: center;
line-height: 40px;
transition-duration: .3s;
outline: none;
&:hover {
text-decoration: none;
}
}
.page-sidebar-collapsed {
.sidebar-wrapper {
display: none;
}
}
.page-sidebar-expanded {
@media (min-width: $screen-md-min) {
padding-left: $sidebar_width;
} }
.sidebar-wrapper { .sidebar-wrapper {
...@@ -225,7 +250,7 @@ ...@@ -225,7 +250,7 @@
width: $sidebar_width; width: $sidebar_width;
} }
.nav-sidebar li a{ .nav-sidebar li a {
width: 230px; width: 230px;
&.back-link { &.back-link {
...@@ -237,91 +262,75 @@ ...@@ -237,91 +262,75 @@
} }
} }
@mixin collapsed-sidebar { .right-sidebar-collapsed {
padding-left: $sidebar_collapsed_width; padding-right: 0;
&.right-sidebar-collapsed { @media (min-width: $screen-sm-min) {
/* Extra small devices (phones, less than 768px) */ padding-right: $sidebar_collapsed_width;
padding-right: 0;
/* Small devices (tablets, 768px and up) */
@media (min-width: $screen-sm-min) {
padding-right: $sidebar_collapsed_width;
}
} }
.sidebar-wrapper { .sidebar-collapsed-icon {
width: $sidebar_collapsed_width; cursor: pointer;
}
}
.right-sidebar-expanded {
padding-right: 0;
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
padding-right: $sidebar_collapsed_width;
}
@media (min-width: $screen-md-min) {
padding-right: $gutter_width;
}
&.with-overlay {
padding-right: $sidebar_collapsed_width;
}
}
.complex-sidebar {
display: inline-block;
.nav-primary {
width: 61px;
float: left;
height: 100vh;
.header-logo { .nav-sidebar {
width: $sidebar_collapsed_width; width: 60px;
a { li a {
padding-left: ($sidebar_collapsed_width - 36) / 2; width: 60px;
.gitlab-text-container { span {
display: none; display: none;
} }
} }
} }
}
.nav-secondary {
$nav-secondary-width: 168px;
float: left;
width: $nav-secondary-width;
.nav-sidebar { .nav-sidebar {
width: $sidebar_collapsed_width; width: $nav-secondary-width;
li { li {
width: auto; width: $nav-secondary-width;
a { a {
span { width: $nav-secondary-width;
i {
display: none; 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;
}
}
} }
} }
.collapse-nav a {
width: $sidebar_width;
position: fixed;
bottom: 0;
left: 0;
font-size: 13px;
background: transparent;
height: 40px;
text-align: center;
line-height: 40px;
transition-duration: .3s;
outline: none;
}
.collapse-nav a:hover {
text-decoration: none;
background: #f2f6f7;
}
.page-sidebar-collapsed {
/* Extra small devices (phones, less than 768px) */
@include collapsed-sidebar;
padding-right: 0;
/* Small devices (tablets, 768px and up) */
@media (min-width: $screen-sm-min) {
@include collapsed-sidebar;
}
}
.page-sidebar-expanded {
@include expanded-sidebar;
}
...@@ -56,8 +56,8 @@ $component-active-bg: $brand-info; ...@@ -56,8 +56,8 @@ $component-active-bg: $brand-info;
//## //##
$input-color: $text-color; $input-color: $text-color;
$input-border: #e7e9ed; $input-border: $border-color;
$input-border-focus: #7f8fa4; $input-border-focus: $focus-border-color;
$legend-color: $text-color; $legend-color: $text-color;
......
...@@ -39,8 +39,8 @@ ...@@ -39,8 +39,8 @@
h1 { h1 {
font-size: 1.3em; font-size: 1.3em;
font-weight: 600; font-weight: 600;
margin: 24px 0 12px 0; margin: 24px 0 12px;
padding: 0 0 10px 0; padding: 0 0 10px;
border-bottom: 1px solid #e7e9ed; border-bottom: 1px solid #e7e9ed;
color: #313236; color: #313236;
} }
...@@ -48,27 +48,27 @@ ...@@ -48,27 +48,27 @@
h2 { h2 {
font-size: 1.2em; font-size: 1.2em;
font-weight: 600; font-weight: 600;
margin: 24px 0 12px 0; margin: 24px 0 12px;
color: #313236; color: #313236;
} }
h3 { h3 {
margin: 24px 0 12px 0; margin: 24px 0 12px;
font-size: 1.1em; font-size: 1.1em;
} }
h4 { h4 {
margin: 24px 0 12px 0; margin: 24px 0 12px;
font-size: 0.98em; font-size: 0.98em;
} }
h5 { h5 {
margin: 24px 0 12px 0; margin: 24px 0 12px;
font-size: 0.95em; font-size: 0.95em;
} }
h6 { h6 {
margin: 24px 0 12px 0; margin: 24px 0 12px;
font-size: 0.90em; font-size: 0.90em;
} }
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
color: #7f8fa4; color: #7f8fa4;
font-size: inherit; font-size: inherit;
padding: 8px 21px; padding: 8px 21px;
margin: 12px 0 12px; margin: 12px 0;
border-left: 3px solid #e7e9ed; border-left: 3px solid #e7e9ed;
} }
...@@ -88,13 +88,13 @@ ...@@ -88,13 +88,13 @@
p { p {
color: #5c5d5e; color: #5c5d5e;
margin: 6px 0 0 0; margin: 6px 0 0;
} }
table { table {
@extend .table; @extend .table;
@extend .table-bordered; @extend .table-bordered;
margin: 12px 0 12px 0; margin: 12px 0;
color: #5c5d5e; color: #5c5d5e;
th { th {
background: #f8fafc; background: #f8fafc;
...@@ -102,7 +102,7 @@ ...@@ -102,7 +102,7 @@
} }
pre { pre {
margin: 12px 0 12px 0; margin: 12px 0;
font-size: 13px; font-size: 13px;
line-height: 1.6em; line-height: 1.6em;
overflow-x: auto; overflow-x: auto;
...@@ -138,6 +138,12 @@ ...@@ -138,6 +138,12 @@
} }
} }
a.no-attachment-icon {
&:before {
display: none;
}
}
/* Link to current header. */ /* Link to current header. */
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
position: relative; position: relative;
...@@ -191,7 +197,7 @@ body { ...@@ -191,7 +197,7 @@ body {
line-height: 1.3; line-height: 1.3;
font-size: 1.25em; font-size: 1.25em;
font-weight: 600; font-weight: 600;
margin: 12px 7px 12px 7px; margin: 12px 7px;
} }
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
...@@ -244,7 +250,7 @@ a > code { ...@@ -244,7 +250,7 @@ a > code {
* Textareas intended for GFM * Textareas intended for GFM
* *
*/ */
textarea.js-gfm-input { .js-gfm-input {
font-family: $monospace_font; font-family: $monospace_font;
color: $gl-text-color; color: $gl-text-color;
} }
......
...@@ -11,6 +11,7 @@ $gutter_inner_width: 258px; ...@@ -11,6 +11,7 @@ $gutter_inner_width: 258px;
* UI elements * UI elements
*/ */
$border-color: #efeff1; $border-color: #efeff1;
$focus-border-color: #3aabf0;
$table-border-color: #eef0f2; $table-border-color: #eef0f2;
$background-color: #faf9f9; $background-color: #faf9f9;
...@@ -26,6 +27,7 @@ $gl-text-orange: #d90; ...@@ -26,6 +27,7 @@ $gl-text-orange: #d90;
$gl-link-color: #3084bb; $gl-link-color: #3084bb;
$gl-dark-link-color: #333; $gl-dark-link-color: #333;
$gl-placeholder-color: #8f8f8f; $gl-placeholder-color: #8f8f8f;
$gl-icon-color: $gl-placeholder-color;
$gl-gray: $gl-text-color; $gl-gray: $gl-text-color;
$gl-header-color: $gl-title-color; $gl-header-color: $gl-title-color;
...@@ -66,7 +68,7 @@ $header-height: 58px; ...@@ -66,7 +68,7 @@ $header-height: 58px;
$fixed-layout-width: 1280px; $fixed-layout-width: 1280px;
$gl-avatar-size: 40px; $gl-avatar-size: 40px;
$error-exclamation-point: #e62958; $error-exclamation-point: #e62958;
$border-radius-default: 3px; $border-radius-default: 2px;
$btn-transparent-color: #8f8f8f; $btn-transparent-color: #8f8f8f;
$ssh-key-icon-color: #8f8f8f; $ssh-key-icon-color: #8f8f8f;
$ssh-key-icon-size: 18px; $ssh-key-icon-size: 18px;
...@@ -166,17 +168,20 @@ $regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif ...@@ -166,17 +168,20 @@ $regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif
/* /*
* Dropdowns * Dropdowns
*/ */
$dropdown-border-radius: 2px;
$dropdown-width: 300px;
$dropdown-bg: #fff; $dropdown-bg: #fff;
$dropdown-link-color: #555; $dropdown-link-color: #555;
$dropdown-link-hover-bg: rgba(#000, .04); $dropdown-link-hover-bg: $row-hover;
$dropdown-empty-row-bg: rgba(#000, .04);
$dropdown-border-color: rgba(#000, .1); $dropdown-border-color: rgba(#000, .1);
$dropdown-shadow-color: rgba(#000, .1); $dropdown-shadow-color: rgba(#000, .1);
$dropdown-divider-color: rgba(#000, .1); $dropdown-divider-color: rgba(#000, .1);
$dropdown-header-color: #959494; $dropdown-header-color: #959494;
$dropdown-title-btn-color: #bfbfbf; $dropdown-title-btn-color: #bfbfbf;
$dropdown-input-color: #c7c7c7; $dropdown-input-color: #555;
$dropdown-input-focus-border: rgb(58, 171, 240); $dropdown-input-focus-border: $focus-border-color;
$dropdown-input-focus-shadow: rgba(#000, .2); $dropdown-input-focus-shadow: rgba($dropdown-input-focus-border, .4);
$dropdown-loading-bg: rgba(#fff, .6); $dropdown-loading-bg: rgba(#fff, .6);
$dropdown-toggle-bg: #fff; $dropdown-toggle-bg: #fff;
...@@ -192,3 +197,29 @@ $dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color; ...@@ -192,3 +197,29 @@ $dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color;
$award-emoji-menu-bg: #fff; $award-emoji-menu-bg: #fff;
$award-emoji-menu-border: #f1f2f4; $award-emoji-menu-border: #f1f2f4;
$award-emoji-new-btn-icon-color: #dcdcdc; $award-emoji-new-btn-icon-color: #dcdcdc;
/*
* Search Box
*/
$search-input-border-color: $dropdown-input-focus-border;
$search-input-focus-shadow-color: $dropdown-input-focus-shadow;
$search-input-width: $dropdown-width;
$location-badge-color: #aaa;
$location-badge-bg: $gray-normal;
$location-icon-color: #e7e9ed;
$location-active-color: $gl-text-color;
$location-active-bg: $search-input-border-color;
/*
* Notes
*/
$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;
.zennable { .zen-backdrop {
a.js-zen-enter { &.fullscreen {
color: $gl-gray; background-color: white;
position: absolute; position: fixed;
top: 0; top: 0;
right: 4px; bottom: 0;
line-height: 56px; left: 0;
} right: 0;
z-index: 1031;
a.js-zen-leave { textarea {
display: none; border: none;
color: $gl-text-color; box-shadow: none;
position: absolute; border-radius: 0;
top: 10px; color: #000;
right: 10px; font-size: 20px;
padding: 5px; line-height: 26px;
font-size: 36px; padding: 30px;
display: block;
outline: none;
resize: none;
height: 100vh;
max-width: 900px;
margin: 0 auto;
}
&:hover { .zen-control-leave {
color: #111; display: block;
position: absolute;
top: 0;
} }
} }
}
.zen-backdrop { .zen-cotrol {
&.fullscreen { padding: 0;
background-color: white; color: #555;
position: fixed; background: none;
top: 0; border: 0;
bottom: 0; }
left: 0;
right: 0;
z-index: 1031;
textarea { .zen-control-full {
border: none; color: $note-toolbar-color;
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 { &:hover {
display: none; color: $gl-link-color;
} text-decoration: none;
}
}
a.js-zen-leave { .zen-control-leave {
display: block; display: none;
position: absolute; color: $gl-text-color;
top: 0; position: absolute;
} right: 10px;
} padding: 5px;
font-size: 36px;
&:hover {
color: $zen-control-hover-color;
} }
} }
img {
max-width: 100%;
height: auto;
}
p.details {
font-style: italic;
color: #777
}
.footer p {
font-size: small;
color: #777
}
pre.commit-message {
white-space: pre-wrap;
}
.file-stats a {
text-decoration: none;
}
.file-stats .new-file {
color: #090;
}
.file-stats .deleted-file {
color: #b00;
}
...@@ -34,9 +34,9 @@ ...@@ -34,9 +34,9 @@
background: #fff background: #fff
} }
.visibility-levels { .visibility-levels {
.controls { .controls {
margin-bottom: 9px; margin-bottom: 9px;
} }
i { i {
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
height: 300px; height: 300px;
overflow-y: scroll; overflow-y: scroll;
input.emoji-search{ input.emoji-search {
background-image: url("data:image/png;base64,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"); background-image: url("data:image/png;base64,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");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: right 5px center; background-position: right 5px center;
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
} }
} }
.loading{ .loading {
font-size: 20px; font-size: 20px;
} }
......
.commit-title{ .commit-title {
display: block; display: block;
} }
.commit-author, .commit-committer{ .commit-author, .commit-committer {
display: block; display: block;
color: #999; color: #999;
font-weight: normal; font-weight: normal;
font-style: italic; font-style: italic;
} }
.commit-author strong, .commit-committer strong{ .commit-author strong, .commit-committer strong {
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
color: $gl-text-red; color: $gl-text-red;
} }
} }
.edit-file{ .edit-file {
a { a {
color: $gl-text-color; color: $gl-text-color;
} }
......
.commits-compare-switch{ .commits-compare-switch {
@include btn-default; @include btn-default;
@include btn-white; @include btn-white;
background: image-url("switch_icon.png") no-repeat center center; background: image-url("switch_icon.png") no-repeat center center;
...@@ -93,12 +93,15 @@ li.commit { ...@@ -93,12 +93,15 @@ li.commit {
.commit-row-info { .commit-row-info {
color: $gl-gray; color: $gl-gray;
line-height: 24px; line-height: 24px;
font-size: 13px;
a { a {
color: $gl-gray; color: $gl-gray;
} }
.avatar {
margin-right: 8px;
}
.committed_ago { .committed_ago {
display: inline-block; display: inline-block;
} }
......
...@@ -132,7 +132,7 @@ ...@@ -132,7 +132,7 @@
} }
.image-info { .image-info {
font-size: 12px; font-size: 12px;
margin: 5px 0 0 0; margin: 5px 0 0;
color: grey; color: grey;
} }
......
.file-editor { .file-editor {
#editor{ #editor {
border: none; border: none;
@include border-radius(0); @include border-radius(0);
height: 500px; height: 500px;
......
...@@ -43,10 +43,6 @@ ...@@ -43,10 +43,6 @@
.md { .md {
color: #7f8fa4; color: #7f8fa4;
font-size: $gl-font-size; font-size: $gl-font-size;
iframe.twitter-share-button {
vertical-align: bottom;
}
} }
pre { pre {
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
} }
.issuable-sidebar { .issuable-sidebar {
a {
color: inherit;
}
.block { .block {
@include clearfix; @include clearfix;
padding: $gl-padding 0; padding: $gl-padding 0;
...@@ -89,7 +93,7 @@ ...@@ -89,7 +93,7 @@
} }
.cross-project-reference { .cross-project-reference {
color: $gl-link-color; color: inherit;
span { span {
white-space: nowrap; white-space: nowrap;
...@@ -133,6 +137,12 @@ ...@@ -133,6 +137,12 @@
.value { .value {
line-height: 1; line-height: 1;
.assign-yourself {
margin-top: 10px;
font-weight: normal;
display: block;
}
} }
.bold { .bold {
...@@ -183,7 +193,7 @@ ...@@ -183,7 +193,7 @@
.block { .block {
width: $sidebar_collapsed_width - 1px; width: $sidebar_collapsed_width - 1px;
margin-left: -19px; margin-left: -19px;
padding: 15px 0 0 0; padding: 15px 0 0;
border-bottom: none; border-bottom: none;
overflow: hidden; overflow: hidden;
} }
...@@ -252,6 +262,15 @@ ...@@ -252,6 +262,15 @@
text-decoration: none; text-decoration: none;
} }
} }
.dropdown-menu-toggle {
width: 100%;
padding-top: 6px;
}
.open .dropdown-menu {
width: 100%;
}
} }
.btn-default.gutter-toggle { .btn-default.gutter-toggle {
...@@ -273,12 +292,12 @@ ...@@ -273,12 +292,12 @@
} }
.participants-list { .participants-list {
margin: -5px -5px; margin: -5px;
} }
.participants-author { .participants-author {
display: inline-block; display: inline-block;
padding: 5px 5px; padding: 5px;
.author_link { .author_link {
display: block; display: block;
......
...@@ -9,28 +9,45 @@ ...@@ -9,28 +9,45 @@
} }
&.suggest-colors-dropdown { &.suggest-colors-dropdown {
margin-bottom: 5px; margin-top: 10px;
margin-bottom: 10px;
border-radius: $border-radius-base;
overflow: hidden;
a { a {
@include border-radius(0); @include border-radius(0);
width: 36.7px; width: (100% / 7);
margin-right: 0; margin-right: 0;
margin-bottom: -5px; margin-bottom: -5px;
} }
} }
} }
.dropdown-label-color-preview { .dropdown-new-label {
display: none; .dropdown-content {
margin-top: 5px; max-height: 260px;
width: 100%; }
height: 25px; }
.dropdown-label-color-input {
position: relative;
margin-bottom: 10px;
&.is-active { &.is-active {
display: block; padding-left: 32px;
} }
} }
.dropdown-label-color-preview {
position: absolute;
left: 0;
top: 0;
width: 32px;
height: 32px;
border-top-left-radius: $border-radius-base;
border-bottom-left-radius: $border-radius-base;
}
.label-row { .label-row {
.label { .label {
padding: 9px; padding: 9px;
...@@ -45,3 +62,10 @@ ...@@ -45,3 +62,10 @@
.label-subscription { .label-subscription {
display: inline-block; display: inline-block;
} }
.dropdown-labels-error {
padding: 5px 10px;
margin-bottom: 10px;
background-color: $gl-danger;
color: $white-light;
}
.ci-body { .ci-body {
.incorrect-syntax{ .incorrect-syntax {
font-size: 19px; font-size: 19px;
color: red; color: red;
} }
.correct-syntax{ .correct-syntax {
font-size: 19px; font-size: 19px;
color: #47a447; color: #47a447;
} }
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
} }
} }
.login-box{ .login-box {
background: #fafafa; background: #fafafa;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 0 2px #ccc; box-shadow: 0 0 2px #ccc;
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
.login-heading h3 { .login-heading h3 {
font-weight: 300; font-weight: 300;
line-height: 1.5; line-height: 1.5;
margin: 0 0 10px 0; margin: 0 0 10px;
} }
.login-footer { .login-footer {
......
...@@ -195,38 +195,8 @@ ...@@ -195,38 +195,8 @@
line-height: 31px; line-height: 31px;
} }
.disabled-comment-area { .builds {
padding: 16px 0; .table-holder {
overflow-x: scroll;
.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;
}
}
} }
} }
/** /**
* Note Form * Note Form
*/ */
.comment-btn {
@extend .btn-create;
}
.reply-btn { .reply-btn {
@extend .btn-primary; @extend .btn-primary;
margin: 10px $gl-padding; margin: 10px $gl-padding;
...@@ -17,16 +13,17 @@ ...@@ -17,16 +13,17 @@
} }
.diff-file, .diff-file,
.discussion { .discussion {
.new_note { .new-note {
margin: 0; margin: 0;
border: none; border: none;
} }
} }
.new_note {
.new-note {
display: none; display: none;
} }
.new_note, .note-edit-form { .new-note, .note-edit-form {
.note-form-actions { .note-form-actions {
margin-top: $gl-padding; margin-top: $gl-padding;
} }
...@@ -40,21 +37,18 @@ ...@@ -40,21 +37,18 @@
img { img {
max-width: 100%; max-width: 100%;
} }
}
.note_text { .note-textarea {
width: 100%; padding: 10px 0;
} font-family: $regular_font;
border: 0;
.comment-hints { &:focus {
margin-top: -12px; outline: 0;
} }
} }
/* loading indicator */
.notes-busy {
margin: 18px;
}
.note-image-attach { .note-image-attach {
@extend .col-md-4; @extend .col-md-4;
margin-left: 45px; margin-left: 45px;
...@@ -62,40 +56,29 @@ ...@@ -62,40 +56,29 @@
} }
.common-note-form { .common-note-form {
margin: 0; .md-area {
background: #fff; padding: $gl-padding-top $gl-padding;
padding: $gl-padding; border: 1px solid $note-form-border-color;
margin-left: -$gl-padding; border-radius: $border-radius-base;
margin-right: -$gl-padding;
margin-bottom: -$gl-padding; &.is-focused {
} border-color: $focus-border-color;
box-shadow: 0 0 2px rgba(#000, .2),
.note-form-actions { 0 0 4px rgba($focus-border-color, .4);
background: #fff;
.comment-toolbar,
.note-form-option { .nav-links {
margin-top: 8px; border-color: $focus-border-color;
margin-left: 30px; }
@extend .pull-left;
}
.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;
} }
} }
} }
.discussion-form {
padding: $gl-padding-top $gl-padding;
background-color: #fff;
}
.note-edit-form { .note-edit-form {
display: none; display: none;
font-size: 15px; font-size: 15px;
...@@ -154,11 +137,49 @@ ...@@ -154,11 +137,49 @@
} }
} }
.comment-hints { .comment-toolbar {
color: #999; padding-top: $gl-padding-top;
background: #fff; color: $note-toolbar-color;
padding: 7px; border-top: 1px solid $border-color;
margin-top: -7px; }
border: 1px solid $border-color;
font-size: 13px; .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;
}
} }
This diff is collapsed.
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
} }
.account-well { .account-well {
padding: 10px 10px; padding: 10px;
background-color: $help-well-bg; background-color: $help-well-bg;
border: 1px solid $help-well-border; border: 1px solid $help-well-border;
border-radius: $border-radius-base; border-radius: $border-radius-base;
...@@ -197,3 +197,24 @@ ...@@ -197,3 +197,24 @@
width: 105px; width: 105px;
} }
} }
.modal-profile-crop {
.modal-dialog {
width: 380px;
@media (max-width: $screen-sm-min) {
width: auto;
}
}
.profile-crop-image-container {
height: 300px;
margin: 0 auto;
}
.crop-controls {
padding: 10px 0 0;
text-align: center;
}
}
...@@ -68,28 +68,6 @@ ...@@ -68,28 +68,6 @@
} }
} }
.project-home-desc {
h1 {
color: #313236;
margin: 0;
margin-bottom: 6px;
font-size: 23px;
font-weight: normal;
}
.visibility-icon {
display: inline-block;
margin-left: 5px;
font-size: 18px;
color: $gray;
}
p {
padding: 0 $gl-padding;
color: #5c5d5e;
}
}
.project-repo-buttons { .project-repo-buttons {
margin-top: 20px; margin-top: 20px;
margin-bottom: 0; margin-bottom: 0;
...@@ -184,7 +162,7 @@ ...@@ -184,7 +162,7 @@
margin-right: 12px; margin-right: 12px;
a { a {
margin: -1px !important; margin: -1px;
} }
} }
...@@ -244,13 +222,17 @@ ...@@ -244,13 +222,17 @@
padding: 0; padding: 0;
background: transparent; background: transparent;
border: none; border: none;
line-height: 42px; line-height: 36px;
margin: 0; margin: 0;
> li + li:before { > li + li:before {
padding: 0 3px; padding: 0 3px;
color: #999; color: #999;
} }
a {
color: $gl-dark-link-color;
}
} }
.last-push-widget { .last-push-widget {
...@@ -333,7 +315,7 @@ pre.light-well { ...@@ -333,7 +315,7 @@ pre.light-well {
} }
.git-empty { .git-empty {
margin: 0 7px 0 7px; margin: 0 7px 7px;
h5 { h5 {
color: #5c5d5e; color: #5c5d5e;
...@@ -419,7 +401,7 @@ pre.light-well { ...@@ -419,7 +401,7 @@ pre.light-well {
} }
.commit_short_id { .commit_short_id {
margin-right: 5px; margin: 0 5px;
color: $gl-link-color; color: $gl-link-color;
font-weight: 600; font-weight: 600;
} }
......
This diff is collapsed.
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#contributors { #contributors {
.contributors-list { .contributors-list {
margin: 0 0 10px 0; margin: 0 0 10px;
list-style: none; list-style: none;
padding: 0; padding: 0;
} }
......
This diff is collapsed.
...@@ -6,13 +6,19 @@ ...@@ -6,13 +6,19 @@
.navbar-nav { .navbar-nav {
li { li {
.badge.todos-pending-count { .badge.todos-pending-count {
background-color: #7f8fa4; background-color: $gl-icon-color;
margin-top: -5px; margin-top: -5px;
font-weight: normal; font-weight: normal;
} }
} }
} }
.todo {
&:hover {
cursor: pointer;
}
}
.todo-item { .todo-item {
.todo-title { .todo-title {
@include str-truncated(calc(100% - 174px)); @include str-truncated(calc(100% - 174px));
......
...@@ -21,19 +21,19 @@ ...@@ -21,19 +21,19 @@
$l-white: #fff; $l-white: #fff;
.term-bold { .term-bold {
font-weight: bold; font-weight: bold;
} }
.term-italic { .term-italic {
font-style: italic; font-style: italic;
} }
.term-conceal { .term-conceal {
visibility: hidden; visibility: hidden;
} }
.term-underline { .term-underline {
text-decoration: underline; text-decoration: underline;
} }
.term-cross { .term-cross {
text-decoration: line-through; text-decoration: line-through;
} }
.term-fg-black { .term-fg-black {
......
...@@ -52,7 +52,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -52,7 +52,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:require_two_factor_authentication, :require_two_factor_authentication,
:two_factor_grace_period, :two_factor_grace_period,
:gravatar_enabled, :gravatar_enabled,
:twitter_sharing_enabled,
:sign_in_text, :sign_in_text,
:help_page_text, :help_page_text,
:home_page_url, :home_page_url,
...@@ -61,6 +60,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -61,6 +60,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:session_expire_delay, :session_expire_delay,
:default_project_visibility, :default_project_visibility,
:default_snippet_visibility, :default_snippet_visibility,
:default_group_visibility,
:restricted_signup_domains_raw, :restricted_signup_domains_raw,
:version_check_enabled, :version_check_enabled,
:admin_notification_email, :admin_notification_email,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -6,7 +6,6 @@ module GlobalMilestones ...@@ -6,7 +6,6 @@ module GlobalMilestones
@milestones = MilestonesFinder.new.execute(@projects, params) @milestones = MilestonesFinder.new.execute(@projects, params)
@milestones = GlobalMilestone.build_collection(@milestones) @milestones = GlobalMilestone.build_collection(@milestones)
@milestones = @milestones.sort_by { |x| x.due_date.nil? ? epoch : x.due_date } @milestones = @milestones.sort_by { |x| x.due_date.nil? ? epoch : x.due_date }
@milestones = Kaminari.paginate_array(@milestones).page(params[:page]).per(ApplicationController::PER_PAGE)
end end
def milestone def milestone
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment