Commit ae0d8222 authored by Timothy Andrew's avatar Timothy Andrew

Merge remote-tracking branch 'origin/master' into 2979-personal-access-tokens

parents ffe111c1 07b46517

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

......@@ -4,46 +4,46 @@
.bundle
.chef
.directory
.envrc
.gitlab_shell_secret
/.envrc
/.gitlab_shell_secret
.idea
.rbenv-version
/.rbenv-version
.rbx/
.ruby-gemset
.ruby-version
.rvmrc
/.ruby-gemset
/.ruby-version
/.rvmrc
.sass-cache/
.secret
.vagrant
.byebug_history
Vagrantfile
backups/*
config/aws.yml
config/database.yml
config/gitlab.yml
config/gitlab_ci.yml
config/initializers/rack_attack.rb
config/initializers/smtp_settings.rb
config/initializers/relative_url.rb
config/resque.yml
config/unicorn.rb
config/secrets.yml
config/sidekiq.yml
coverage/*
db/*.sqlite3
db/*.sqlite3-journal
db/data.yml
doc/code/*
dump.rdb
log/*.log*
nohup.out
public/assets/
public/uploads.*
public/uploads/
shared/artifacts/
rails_best_practices_output.html
/.secret
/.vagrant
/.byebug_history
/Vagrantfile
/backups/*
/config/aws.yml
/config/database.yml
/config/gitlab.yml
/config/gitlab_ci.yml
/config/initializers/rack_attack.rb
/config/initializers/smtp_settings.rb
/config/initializers/relative_url.rb
/config/resque.yml
/config/unicorn.rb
/config/secrets.yml
/config/sidekiq.yml
/coverage/*
/db/*.sqlite3
/db/*.sqlite3-journal
/db/data.yml
/doc/code/*
/dump.rdb
/log/*.log*
/nohup.out
/public/assets/
/public/uploads.*
/public/uploads/
/shared/artifacts/
/rails_best_practices_output.html
/tags
tmp/
vendor/bundle/*
builds/*
shared/*
/tmp/*
/vendor/bundle/*
/builds/*
/shared/*
This diff is collapsed.
This diff is collapsed.
......@@ -311,13 +311,11 @@ request is as follows:
1. Create a feature branch
1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code
1. Add your changes to the [CHANGELOG](CHANGELOG)
1. If you are changing the README, some documentation or other things which
have no effect on the tests, add `[ci skip]` somewhere in the commit message
and make sure to read the [documentation styleguide][doc-styleguide]
1. If you are writing documentation, make sure to read the [documentation styleguide][doc-styleguide]
1. If you have multiple commits please combine them into one commit by
[squashing them][git-squash]
1. Push the commit(s) to your fork
1. Submit a merge request (MR) to the master branch
1. Submit a merge request (MR) to the `master` branch
1. The MR title should describe the change you want to make
1. The MR description should give a motive for your change and the method you
used to achieve it, see the [merge request description format]
......
......@@ -18,9 +18,8 @@ gem "mysql2", '~> 0.3.16', group: :mysql
gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries
gem 'devise', '~> 3.5.4'
gem 'devise', '~> 4.0'
gem 'doorkeeper', '~> 3.1'
gem 'devise-async', '~> 0.9.0'
gem 'omniauth', '~> 1.3.1'
gem 'omniauth-auth0', '~> 1.4.1'
gem 'omniauth-azure-oauth2', '~> 0.0.6'
......@@ -36,15 +35,16 @@ gem 'omniauth-shibboleth', '~> 1.2.0'
gem 'omniauth-twitter', '~> 1.2.0'
gem 'omniauth_crowd', '~> 2.2.0'
gem 'rack-oauth2', '~> 1.2.1'
gem 'jwt'
# Spam and anti-bot protection
gem 'recaptcha', require: 'recaptcha/rails'
gem 'akismet', '~> 2.0'
# Two-factor authentication
gem 'devise-two-factor', '~> 2.0.0'
gem 'devise-two-factor', '~> 3.0.0'
gem 'rqrcode-rails3', '~> 0.1.7'
gem 'attr_encrypted', '~> 1.3.4'
gem 'attr_encrypted', '~> 3.0.0'
# Browser detection
gem "browser", '~> 1.0.0'
......@@ -72,7 +72,7 @@ gem 'grape-entity', '~> 0.4.2'
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
# Pagination
gem "kaminari", "~> 0.16.3"
gem "kaminari", "~> 0.17.0"
# HAML
gem "haml-rails", '~> 0.9.0'
......@@ -83,8 +83,14 @@ gem "carrierwave", '~> 0.10.0'
# Drag and Drop UI
gem 'dropzonejs-rails', '~> 0.7.1'
# for backups
gem 'fog-aws', '~> 0.9'
gem 'fog-core', '~> 1.40'
gem 'fog-local', '~> 0.3'
gem 'fog-google', '~> 0.3'
gem 'fog-openstack', '~> 0.1'
# for aws storage
gem "fog", "~> 1.36.0"
gem "unf", '~> 0.1.4'
# Authorization
......@@ -120,7 +126,7 @@ group :unicorn do
end
# State machine
gem "state_machines-activerecord", '~> 0.3.0'
gem "state_machines-activerecord", '~> 0.4.0'
# Run events after state machine commits
gem 'after_commit_queue'
......@@ -177,9 +183,6 @@ gem 'ruby-fogbugz', '~> 0.2.1'
# d3
gem 'd3_rails', '~> 3.5.0'
#cal-heatmap
gem 'cal-heatmap-rails', '~> 3.6.0'
# underscore-rails
gem "underscore-rails", "~> 1.8.0"
......@@ -218,13 +221,13 @@ gem 'gitlab_emoji', '~> 0.3.0'
gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 4.1.0'
gem 'jquery-scrollto-rails', '~> 1.4.3'
gem 'jquery-ui-rails', '~> 5.0.0'
gem 'raphael-rails', '~> 2.1.2'
gem 'request_store', '~> 1.3.0'
gem 'select2-rails', '~> 3.5.9'
gem 'virtus', '~> 1.0.1'
gem 'net-ssh', '~> 3.0.1'
gem 'base32', '~> 0.3.0'
# Sentry integration
gem 'sentry-raven', '~> 0.15'
......@@ -292,7 +295,8 @@ group :development, :test do
gem 'spring-commands-spinach', '~> 1.1.0'
gem 'spring-commands-teaspoon', '~> 0.0.2'
gem 'rubocop', '~> 0.38.0', require: false
gem 'rubocop', '~> 0.40.0', require: false
gem 'rubocop-rspec', '~> 1.5.0', require: false
gem 'scss_lint', '~> 0.47.0', require: false
gem 'coveralls', '~> 0.8.2', require: false
gem 'simplecov', '~> 0.11.0', require: false
......@@ -324,8 +328,7 @@ gem "mail_room", "~> 0.7"
gem 'email_reply_parser', '~> 0.5.8'
## CI
gem 'activerecord-deprecated_finders', '~> 1.0.3'
gem 'activerecord-session_store', '~> 0.1.0'
gem 'activerecord-session_store', '~> 1.0.0'
gem "nested_form", '~> 0.3.2'
# OAuth
......@@ -333,3 +336,6 @@ gem 'oauth2', '~> 1.0.0'
# Soft deletion
gem "paranoia", "~> 2.0"
# Health check
gem 'health_check', '~> 1.5.1'
This diff is collapsed.
# GitLab
[![build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
[![Build Status](https://semaphoreci.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/400484/shields_badge.svg)](https://semaphoreci.com/gitlabhq/gitlabhq)
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
[![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.svg?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master)
## Canonical source
......
8.8.0-pre
8.9.0-pre
@Api =
groups_path: "/api/:version/groups.json"
group_path: "/api/:version/groups/:id.json"
namespaces_path: "/api/:version/namespaces.json"
group_projects_path: "/api/:version/groups/:id/projects.json"
projects_path: "/api/:version/projects.json"
labels_path: "/api/:version/projects/:id/labels"
license_path: "/api/:version/licenses/:key"
groupsPath: "/api/:version/groups.json"
groupPath: "/api/:version/groups/:id.json"
namespacesPath: "/api/:version/namespaces.json"
groupProjectsPath: "/api/:version/groups/:id/projects.json"
projectsPath: "/api/:version/projects.json"
labelsPath: "/api/:version/projects/:id/labels"
licensePath: "/api/:version/licenses/:key"
gitignorePath: "/api/:version/gitignores/:key"
group: (group_id, callback) ->
url = Api.buildUrl(Api.group_path)
url = Api.buildUrl(Api.groupPath)
url = url.replace(':id', group_id)
$.ajax(
......@@ -22,7 +23,7 @@
# Return groups list. Filtered by query
# Only active groups retrieved
groups: (query, skip_ldap, callback) ->
url = Api.buildUrl(Api.groups_path)
url = Api.buildUrl(Api.groupsPath)
$.ajax(
url: url
......@@ -36,7 +37,7 @@
# Return namespaces list. Filtered by query
namespaces: (query, callback) ->
url = Api.buildUrl(Api.namespaces_path)
url = Api.buildUrl(Api.namespacesPath)
$.ajax(
url: url
......@@ -50,7 +51,7 @@
# Return projects list. Filtered by query
projects: (query, order, callback) ->
url = Api.buildUrl(Api.projects_path)
url = Api.buildUrl(Api.projectsPath)
$.ajax(
url: url
......@@ -64,7 +65,7 @@
callback(projects)
newLabel: (project_id, data, callback) ->
url = Api.buildUrl(Api.labels_path)
url = Api.buildUrl(Api.labelsPath)
url = url.replace(':id', project_id)
data.private_token = gon.api_token
......@@ -80,7 +81,7 @@
# Return group projects list. Filtered by query
groupProjects: (group_id, query, callback) ->
url = Api.buildUrl(Api.group_projects_path)
url = Api.buildUrl(Api.groupProjectsPath)
url = url.replace(':id', group_id)
$.ajax(
......@@ -95,7 +96,7 @@
# Return text for a specific license
licenseText: (key, data, callback) ->
url = Api.buildUrl(Api.license_path).replace(':key', key)
url = Api.buildUrl(Api.licensePath).replace(':key', key)
$.ajax(
url: url
......@@ -103,6 +104,12 @@
).done (license) ->
callback(license)
gitignoreText: (key, callback) ->
url = Api.buildUrl(Api.gitignorePath).replace(':key', key)
$.get url, (gitignore) ->
callback(gitignore)
buildUrl: (url) ->
url = gon.relative_url_root + url if gon.relative_url_root?
return url.replace(':version', gon.api_version)
......@@ -18,8 +18,6 @@
#= require jquery.atwho
#= require jquery.scrollTo
#= require jquery.turbolinks
#= require d3
#= require cal-heatmap
#= require turbolinks
#= require autosave
#= require bootstrap/affix
......@@ -52,7 +50,13 @@
#= require shortcuts_network
#= require jquery.nicescroll
#= require date.format
#= require_tree .
#= require_directory ./behaviors
#= require_directory ./blob
#= require_directory ./ci
#= require_directory ./commit
#= require_directory ./extensions
#= require_directory ./lib
#= require_directory .
#= require fuzzaldrin-plus
#= require cropper
......@@ -246,38 +250,6 @@ $ ->
if $navIcon.hasClass('fa-angle-left')
$navIconToggle.trigger('click')
$(document)
.off 'click', '.js-sidebar-toggle'
.on 'click', '.js-sidebar-toggle', (e, triggered) ->
e.preventDefault()
$this = $(this)
$thisIcon = $this.find 'i'
$allGutterToggleIcons = $('.js-sidebar-toggle i')
if $thisIcon.hasClass('fa-angle-double-right')
$allGutterToggleIcons
.removeClass('fa-angle-double-right')
.addClass('fa-angle-double-left')
$('aside.right-sidebar')
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed')
$('.page-with-sidebar')
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed')
else
$allGutterToggleIcons
.removeClass('fa-angle-double-left')
.addClass('fa-angle-double-right')
$('aside.right-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded')
$('.page-with-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded')
if not triggered
$.cookie("collapsed_gutter",
$('.right-sidebar')
.hasClass('right-sidebar-collapsed'), { path: '/' })
fitSidebarForSize = ->
oldBootstrapBreakpoint = bootstrapBreakpoint
bootstrapBreakpoint = bp.getBreakpointSize()
......
class @BlobGitignoreSelector
constructor: (opts) ->
{
@dropdown
@editor
@$wrapper = @dropdown.closest('.gitignore-selector')
@$filenameInput = $('#file_name')
@data = @dropdown.data('filenames')
} = opts
@dropdown.glDropdown(
data: @data,
filterable: true,
selectable: true,
search:
fields: ['name']
clicked: @onClick
text: (gitignore) ->
gitignore.name
)
@toggleGitignoreSelector()
@bindEvents()
bindEvents: ->
@$filenameInput
.on 'keyup blur', (e) =>
@toggleGitignoreSelector()
toggleGitignoreSelector: ->
filename = @$filenameInput.val() or $('.editor-file-name').text().trim()
@$wrapper.toggleClass 'hidden', filename isnt '.gitignore'
onClick: (item, el, e) =>
e.preventDefault()
@requestIgnoreFile(item.name)
requestIgnoreFile: (name) ->
Api.gitignoreText name, @requestIgnoreFileSuccess.bind(@)
requestIgnoreFileSuccess: (gitignore) ->
@editor.setValue(gitignore.content, 1)
@editor.focus()
class @BlobGitignoreSelectors
constructor: (opts) ->
{
@$dropdowns = $('.js-gitignore-selector')
@editor
} = opts
@$dropdowns.each (i, dropdown) =>
$dropdown = $(dropdown)
new BlobGitignoreSelector(
dropdown: $dropdown,
editor: @editor
)
......@@ -13,6 +13,7 @@ class @EditBlob
@initModePanesAndLinks()
new BlobLicenseSelector(@editor)
new BlobGitignoreSelectors(editor: @editor)
initModePanesAndLinks: ->
@$editModePanes = $(".js-edit-mode-pane")
......
class @Calendar
constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
cal = new CalHeatMap()
cal.init
itemName: ["contribution"]
data: timestamps
start: new Date(starting_year, starting_month)
domainLabelFormat: "%b"
id: "cal-heatmap"
domain: "month"
subDomain: "day"
range: 12
tooltip: true
label:
position: "top"
legend: [
0
10
20
30
]
legendCellPadding: 3
cellSize: $('.user-calendar').width() / 73
onClick: (date, count) ->
formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
$.ajax
url: calendar_activities_path
data:
date: formated_date
cache: false
dataType: "html"
success: (data) ->
$(".user-calendar-activities").html data
class CiBuild
@interval: null
@state: null
constructor: (build_url, build_status) ->
constructor: (build_url, build_status, build_state) ->
clearInterval(CiBuild.interval)
@state = build_state
@initScrollButtonAffix()
if build_status == "running" || build_status == "pending"
......@@ -25,15 +28,22 @@ class CiBuild
#
CiBuild.interval = setInterval =>
if window.location.href.split("#").first() is build_url
last_state = @state
$.ajax
url: build_url
url: build_url + "/trace.json?state=" + encodeURIComponent(@state)
dataType: "json"
success: (build) =>
if build.status == "running"
$('#build-trace code').html build.trace_html
success: (log) =>
return unless last_state is @state
if log.state and log.status is "running"
@state = log.state
if log.append
$('.fa-refresh').before log.html
else
$('#build-trace code').html log.html
$('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>'
@checkAutoscroll()
else if build.status != build_status
else if log.status isnt build_status
Turbolinks.visit build_url
, 4000
......
......@@ -16,7 +16,6 @@ class Dispatcher
shortcut_handler = null
switch page
when 'projects:issues:index'
Issues.init()
Issuable.init()
shortcut_handler = new ShortcutsNavigation()
when 'projects:issues:show'
......@@ -119,7 +118,7 @@ class Dispatcher
new UsersSelect()
when 'projects'
new NamespaceSelect()
when 'dashboard'
when 'dashboard', 'root'
shortcut_handler = new ShortcutsDashboardNavigation()
when 'profiles'
new Profile()
......
......@@ -11,6 +11,7 @@ class @DueDateSelect
$block = $dropdown.closest('.block')
$selectbox = $dropdown.closest('.selectbox')
$value = $block.find('.value')
$valueContent = $block.find('.value-content')
$sidebarValue = $('.js-due-date-sidebar-value', $block)
fieldName = $dropdown.data('field-name')
......@@ -23,11 +24,15 @@ class @DueDateSelect
$value.removeAttr('style')
)
addDueDate = ->
addDueDate = (isDropdown) ->
# Create the post date
value = $("input[name='#{fieldName}']").val()
if value isnt ''
date = new Date value.replace(new RegExp('-', 'g'), ',')
mediumDate = $.datepicker.formatDate 'M d, yy', date
else
mediumDate = 'None'
data = {}
data[abilityName] = {}
......@@ -39,23 +44,35 @@ class @DueDateSelect
data: data
beforeSend: ->
$loading.fadeIn()
if isDropdown
$dropdown.trigger('loading.gl.dropdown')
$selectbox.hide()
$value.removeAttr('style')
$value.html(mediumDate)
$valueContent.html(mediumDate)
$sidebarValue.html(mediumDate)
if value isnt ''
$('.js-remove-due-date-holder').removeClass 'hidden'
else
$('.js-remove-due-date-holder').addClass 'hidden'
).done (data) ->
if isDropdown
$dropdown.trigger('loaded.gl.dropdown')
$dropdown.dropdown('toggle')
$loading.fadeOut()
$block.on 'click', '.js-remove-due-date', (e) ->
e.preventDefault()
$("input[name='#{fieldName}']").val ''
addDueDate(false)
$datePicker.datepicker(
dateFormat: 'yy-mm-dd',
defaultDate: $("input[name='#{fieldName}']").val()
altField: "input[name='#{fieldName}']"
onSelect: ->
addDueDate()
addDueDate(true)
)
$(document)
......
......@@ -18,6 +18,10 @@ GitLab.GfmAutoComplete =
Issues:
template: '<li><small>${id}</small> ${title}</li>'
# Milestones
Milestones:
template: '<li>${title}</li>'
# Add GFM auto-completion to all input fields, that accept GFM input.
setup: (wrap) ->
@input = $('.js-gfm-input')
......@@ -81,6 +85,19 @@ GitLab.GfmAutoComplete =
title: sanitize(i.title)
search: "#{i.iid} #{i.title}"
@input.atwho
at: '%'
alias: 'milestones'
searchKey: 'search'
displayTpl: @Milestones.template
insertTpl: '${atwho-at}"${title}"'
callbacks:
beforeSave: (milestones) ->
$.map milestones, (m) ->
id: m.iid
title: sanitize(m.title)
search: "#{m.title}"
@input.atwho
at: '!'
alias: 'mergerequests'
......@@ -105,6 +122,8 @@ GitLab.GfmAutoComplete =
@input.atwho 'load', '@', data.members
# load issues
@input.atwho 'load', 'issues', data.issues
# load milestones
@input.atwho 'load', 'milestones', data.milestones
# load merge requests
@input.atwho 'load', 'mergerequests', data.mergerequests
# load emojis
......
......@@ -60,9 +60,36 @@ class GitLabDropdownFilter
results = data
if search_text isnt ''
# When data is an array of objects therefore [object Array] e.g.
# [
# { prop: 'foo' },
# { prop: 'baz' }
# ]
if _.isArray(data)
results = fuzzaldrinPlus.filter(data, search_text,
key: @options.keys
)
else
# If data is grouped therefore an [object Object]. e.g.
# {
# groupName1: [
# { prop: 'foo' },
# { prop: 'baz' }
# ],
# groupName2: [
# { prop: 'abc' },
# { prop: 'def' }
# ]
# }
if gl.utils.isObject data
results = {}
for key, group of data
tmp = fuzzaldrinPlus.filter(group, search_text,
key: @options.keys
)
if tmp.length
results[key] = tmp.map (item) -> item
@options.callback results
else
......@@ -141,8 +168,9 @@ class GitLabDropdown
searchFields = if @options.search then @options.search.fields else [];
if @options.data
# If data is an array
if _.isArray @options.data
# If we provided data
# data could be an array of objects or a group of arrays
if _.isObject(@options.data) and not _.isFunction(@options.data)
@fullData = @options.data
@parseData @options.data
else
......@@ -230,19 +258,33 @@ class GitLabDropdown
parseData: (data) ->
@renderedData = data
# Render each row
html = $.map data, (obj) =>
return @renderItem(obj)
if @options.filterable and data.length is 0
# render no matching results
html = [@noResults()]
else
# Handle array groups
if gl.utils.isObject data
html = []
for name, groupData of data
# Add header for each group
html.push(@renderItem(header: name, name))
@renderData(groupData, name)
.map (item) ->
html.push item
else
# Render each row
html = @renderData(data)
# Render the full menu
full_html = @renderMenu(html.join(""))
@appendMenu(full_html)
renderData: (data, group = false) ->
data.map (obj, index) =>
return @renderItem(obj, group, index)
shouldPropagate: (e) =>
if @options.multiSelect
$target = $(e.target)
......@@ -299,11 +341,10 @@ class GitLabDropdown
selector = '.dropdown-content'
if @dropdown.find(".dropdown-toggle-page").length
selector = ".dropdown-page-one .dropdown-content"
$(selector, @dropdown).html html
# Render the row
renderItem: (data) ->
renderItem: (data, group = false, index = false) ->
html = ""
# Divider
......@@ -346,8 +387,13 @@ class GitLabDropdown
if @highlight
text = @highlightTextMatches(text, @filterInput.val())
if group
groupAttrs = "data-group='#{group}' data-index='#{index}'"
else
groupAttrs = ''
html = "<li>
<a href='#{url}' class='#{cssClass}'>
<a href='#{url}' #{groupAttrs} class='#{cssClass}'>
#{text}
</a>
</li>"
......@@ -377,9 +423,15 @@ class GitLabDropdown
rowClicked: (el) ->
fieldName = @options.fieldName
selectedIndex = el.parent().index()
if @renderedData
groupName = el.data('group')
if groupName
selectedIndex = el.data('index')
selectedObject = @renderedData[groupName][selectedIndex]
else
selectedIndex = el.closest('li').index()
selectedObject = @renderedData[selectedIndex]
value = if @options.id then @options.id(selectedObject, el) else selectedObject.id
field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']")
if el.hasClass(ACTIVE_CLASS)
......@@ -460,7 +512,7 @@ class GitLabDropdown
return false
if currentKeyCode is 13
@selectRowAtIndex currentIndex
@selectRowAtIndex if currentIndex < 0 then 0 else currentIndex
removeArrayKeyEvent: ->
$('body').off 'keydown'
......
# This is a manifest file that'll be compiled into including all the files listed below.
# Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
# be included in the compiled file accessible from http://example.com/assets/application.js
# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
# the compiled file.
#
#= require_tree .
#= require d3
#= require stat_graph_contributors_util
class @ContributorsStatGraph
init: (log) ->
......
issuable_created = false
@Issuable =
init: ->
unless issuable_created
issuable_created = true
Issuable.initTemplates()
Issuable.initSearch()
Issuable.initChecks()
initTemplates: ->
Issuable.labelRow = _.template(
......@@ -19,7 +23,16 @@
.on 'keyup', ->
clearTimeout(@timer)
@timer = setTimeout( ->
Issuable.filterResults $('#issue_search_form')
$search = $('#issue_search')
$form = $('.js-filter-form')
$input = $("input[name='#{$search.attr('name')}']", $form)
if $input.length is 0
$form.append "<input type='hidden' name='#{$search.attr('name')}' value='#{_.escape($search.val())}'/>"
else
$input.val $search.val()
Issuable.filterResults $form
, 500)
toggleLabelFilters: ->
......@@ -59,15 +72,22 @@
dataType: "json"
reload: ->
if Issues.created
Issues.initChecks()
if Issuable.created
Issuable.initChecks()
$('#filter_issue_search').val($('#issue_search').val())
initChecks: ->
$('.check_all_issues').on 'click', ->
$('.selected_issue').prop('checked', @checked)
Issuable.checkChanged()
$('.selected_issue').on 'change', Issuable.checkChanged
updateStateFilters: ->
stateFilters = $('.issues-state-filters')
stateFilters = $('.issues-state-filters, .dropdown-menu-sort')
newParams = {}
paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search']
paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search', 'issue_search']
for paramKey in paramKeys
newParams[paramKey] = gl.utils.getParameterValues(paramKey)[0] or ''
......@@ -82,3 +102,17 @@
else
newUrl = gl.utils.mergeUrlParams(newParams, initialUrl)
$(this).attr 'href', newUrl
checkChanged: ->
checked_issues = $('.selected_issue:checked')
if checked_issues.length > 0
ids = $.map checked_issues, (value) ->
$(value).data('id')
$('#update_issues_ids').val ids
$('.issues-other-filters').hide()
$('.issues_bulk_update').show()
else
$('#update_issues_ids').val []
$('.issues_bulk_update').hide()
$('.issues-other-filters').show()
......@@ -19,6 +19,16 @@ class @IssuableForm
@form.on "click", ".btn-cancel", @resetAutosave
@initWip()
@initMoveDropdown()
$issuableDueDate = $('#issuable-due-date')
if $issuableDueDate.length
$('.datepicker').datepicker(
dateFormat: 'yy-mm-dd',
onSelect: (dateText, inst) ->
$issuableDueDate.val dateText
).datepicker 'setDate', $.datepicker.parseDate('yy-mm-dd', $issuableDueDate.val())
initAutosave: ->
new Autosave @titleField, [
......@@ -80,3 +90,19 @@ class @IssuableForm
addWip: ->
@titleField.val "WIP: #{@titleField.val()}"
initMoveDropdown: ->
$moveDropdown = $('.js-move-dropdown')
if $moveDropdown.length
$('.js-move-dropdown').select2
ajax:
url: $moveDropdown.data('projects-url')
results: (data) ->
return {
results: data
}
formatResult: (project) ->
project.name_with_namespace
formatSelection: (project) ->
project.name_with_namespace
@Issues =
init: ->
Issues.created = true
Issues.initChecks()
$("body").on "ajax:success", ".close_issue, .reopen_issue", ->
t = $(this)
totalIssues = undefined
reopen = t.hasClass("reopen_issue")
$(".issue_counter").each ->
issue = $(this)
totalIssues = parseInt($(this).html(), 10)
if reopen and issue.closest(".main_menu").length
$(this).html totalIssues + 1
else
$(this).html totalIssues - 1
initChecks: ->
$(".check_all_issues").click ->
$(".selected_issue").prop("checked", @checked)
Issues.checkChanged()
$(".selected_issue").bind "change", Issues.checkChanged
checkChanged: ->
checked_issues = $(".selected_issue:checked")
if checked_issues.length > 0
ids = []
$.each checked_issues, (index, value) ->
ids.push $(value).attr("data-id")
$("#update_issues_ids").val ids
$(".issues-other-filters").hide()
$(".issues_bulk_update").show()
else
$("#update_issues_ids").val []
$(".issues_bulk_update").hide()
$(".issues-other-filters").show()
class @LayoutNav
$ ->
$('.fade-left').addClass('end-scroll')
$('.scrolling-tabs').on 'scroll', (event) ->
$this = $(this)
$el = $(event.target)
currentPosition = $this.scrollLeft()
size = bp.getBreakpointSize()
controlBtnWidth = $('.controls').width()
maxPosition = $this.get(0).scrollWidth - $this.parent().width()
maxPosition += controlBtnWidth if size isnt 'xs' and $('.nav-control').length
$el.find('.fade-left').toggleClass('end-scroll', currentPosition is 0)
$el.find('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition)
((w) ->
w.gl ?= {}
w.gl.utils ?= {}
w.gl.utils.isObject = (obj) ->
obj? and (obj.constructor is Object)
) window
......@@ -26,10 +26,19 @@
newUrl = decodeURIComponent(url)
for paramName, paramValue of params
pattern = new RegExp "\\b(#{paramName}=).*?(&|$)"
if url.search(pattern) >= 0
if not paramValue?
newUrl = newUrl.replace pattern, ''
else if url.search(pattern) isnt -1
newUrl = newUrl.replace pattern, "$1#{paramValue}$2"
else
newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}"
# Remove a trailing ampersand
lastChar = newUrl[newUrl.length - 1]
if lastChar is '&'
newUrl = newUrl.slice 0, -1
newUrl
# removes parameter query string from url. returns the modified url
......
......@@ -75,6 +75,9 @@ class @MergeRequestTabs
@loadDiff($target.attr('href'))
if bp? and bp.getBreakpointSize() isnt 'lg'
@shrinkView()
navBarHeight = $('.navbar-gitlab').outerHeight()
$.scrollTo(".merge-request-details .merge-request-tabs", offset: -navBarHeight)
else if action == 'builds'
@loadBuilds($target.attr('href'))
@expandView()
......
......@@ -10,6 +10,7 @@ class @MergeRequestWidget
$('#modal_merge_info').modal(show: false)
@firstCICheck = true
@readyForCICheck = false
@cancel = false
clearInterval @fetchBuildStatusInterval
@clearEventListeners()
......@@ -21,10 +22,16 @@ class @MergeRequestWidget
clearEventListeners: ->
$(document).off 'page:change.merge_request'
cancelPolling: ->
@cancel = true
addEventListeners: ->
allowedPages = ['show', 'commits', 'builds', 'changes']
$(document).on 'page:change.merge_request', =>
if $('body').data('page') isnt 'projects:merge_requests:show'
page = $('body').data('page').split(':').last()
if allowedPages.indexOf(page) < 0
clearInterval @fetchBuildStatusInterval
@cancelPolling()
@clearEventListeners()
mergeInProgress: (deleteSourceBranch = false)->
......@@ -67,6 +74,7 @@ class @MergeRequestWidget
$('.ci-widget-fetching').show()
$.getJSON @opts.ci_status_url, (data) =>
return if @cancel
@readyForCICheck = true
if data.status is ''
......@@ -106,6 +114,7 @@ class @MergeRequestWidget
@firstCICheck = false
showCIStatus: (state) ->
return if not state?
$('.ci_widget').hide()
allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"]
if state in allowed_states
......@@ -113,7 +122,7 @@ class @MergeRequestWidget
switch state
when "failed", "canceled", "not_found"
@setMergeButtonClass('btn-danger')
when "running", "pending"
when "running"
@setMergeButtonClass('btn-warning')
when "success"
@setMergeButtonClass('btn-create')
......@@ -126,6 +135,6 @@ class @MergeRequestWidget
$('.ci_widget:visible .ci-coverage').text(text)
setMergeButtonClass: (css_class) ->
$('.accept_merge_request')
$('.js-merge-button,.accept-action .dropdown-toggle')
.removeClass('btn-danger btn-warning btn-create')
.addClass(css_class)
......@@ -114,9 +114,9 @@ class @Notes
@refresh()
, @pollingInterval
refresh: ->
refresh: =>
return if @refreshing is true
refreshing = true
@refreshing = true
if not document.hidden and document.URL.indexOf(@noteable_url) is 0
@getContent()
......@@ -134,7 +134,7 @@ class @Notes
@renderDiscussionNote(note)
else
@renderNote(note)
always: =>
.always () =>
@refreshing = false
###
......@@ -285,6 +285,7 @@ class @Notes
form.addClass "js-main-target-form"
form.find("#note_line_code").remove()
form.find("#note_type").remove()
###
General note form setup.
......@@ -328,7 +329,7 @@ class @Notes
@renderDiscussionNote(note)
# cleanup after successfully creating a diff/discussion note
@removeDiscussionNoteForm($("#new-discussion-note-form-#{note.discussion_id}"))
@removeDiscussionNoteForm($(xhr.target))
###
Called in response to the edit note form being submitted
......@@ -472,6 +473,7 @@ class @Notes
setupDiscussionNoteForm: (dataHolder, form) =>
# setup note target
form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}"
form.find("#note_type").val dataHolder.data("noteType")
form.find("#line_type").val dataHolder.data("lineType")
form.find("#note_commit_id").val dataHolder.data("commitId")
form.find("#note_line_code").val dataHolder.data("lineCode")
......
......@@ -10,6 +10,40 @@ class @Sidebar
$('.dropdown').on('loading.gl.dropdown', @sidebarDropdownLoading)
$('.dropdown').on('loaded.gl.dropdown', @sidebarDropdownLoaded)
$(document)
.off 'click', '.js-sidebar-toggle'
.on 'click', '.js-sidebar-toggle', (e, triggered) ->
e.preventDefault()
$this = $(this)
$thisIcon = $this.find 'i'
$allGutterToggleIcons = $('.js-sidebar-toggle i')
if $thisIcon.hasClass('fa-angle-double-right')
$allGutterToggleIcons
.removeClass('fa-angle-double-right')
.addClass('fa-angle-double-left')
$('aside.right-sidebar')
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed')
$('.page-with-sidebar')
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed')
else
$allGutterToggleIcons
.removeClass('fa-angle-double-left')
.addClass('fa-angle-double-right')
$('aside.right-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded')
$('.page-with-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded')
if not triggered
$.cookie("collapsed_gutter",
$('.right-sidebar')
.hasClass('right-sidebar-collapsed'), { path: '/' })
sidebarDropdownLoading: (e) ->
$sidebarCollapsedIcon = $(@).closest('.block').find('.sidebar-collapsed-icon')
img = $sidebarCollapsedIcon.find('img')
......@@ -76,7 +110,7 @@ class @Sidebar
@triggerOpenSidebar() if not @isOpen()
if action is 'hide'
@triggerOpenSidebar() is @isOpen()
@triggerOpenSidebar() if @isOpen()
isOpen: ->
@sidebar.is('.right-sidebar-expanded')
......
......@@ -20,8 +20,7 @@ class @SearchAutocomplete
@dropdown = @wrap.find('.dropdown')
@dropdownContent = @dropdown.find('.dropdown-content')
@locationBadgeEl = @getElement('.search-location-badge')
@locationText = @getElement('.location-text')
@locationBadgeEl = @getElement('.location-badge')
@scopeInputEl = @getElement('#scope')
@searchInput = @getElement('.search-input')
@projectInputEl = @getElement('#search_project_id')
......@@ -133,7 +132,7 @@ class @SearchAutocomplete
scope: @scopeInputEl.val()
# Location badge
_location: @locationText.text()
_location: @locationBadgeEl.text()
}
bindEvents: ->
......@@ -143,12 +142,14 @@ class @SearchAutocomplete
@searchInput.on 'click', @onSearchInputClick
@searchInput.on 'focus', @onSearchInputFocus
@clearInput.on 'click', @onClearInputClick
@locationBadgeEl.on 'click', =>
@searchInput.focus()
onDocumentClick: (e) =>
# If clicking outside the search box
# And search input is not focused
# And we are not clicking inside a suggestion
if not $.contains(@dropdown[0], e.target) and @isFocused and not $(e.target).parents('ul').length
if not $.contains(@dropdown[0], e.target) and @isFocused and not $(e.target).closest('.search-form').length
@onSearchInputBlur()
enableAutocomplete: ->
......@@ -221,10 +222,8 @@ class @SearchAutocomplete
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)
badgeText = "#{category}#{value}"
@locationBadgeEl.text(badgeText).show()
@wrap.addClass('has-location-badge')
restoreOriginalState: ->
......@@ -233,9 +232,8 @@ class @SearchAutocomplete
for input in inputs
@getElement("##{input}").val(@originalState[input])
if @originalState._location is ''
@locationBadgeEl.empty()
@locationBadgeEl.hide()
else
@addLocationBadge(
value: @originalState._location
......@@ -244,7 +242,7 @@ class @SearchAutocomplete
@dropdown.removeClass 'open'
badgePresent: ->
@locationBadgeEl.children().length
@locationBadgeEl.length
resetSearchState: ->
inputs = Object.keys @originalState
......@@ -257,7 +255,7 @@ class @SearchAutocomplete
@getElement("##{input}").val('')
removeLocationBadge: ->
@locationBadgeEl.empty()
@locationBadgeEl.hide()
# Reset state
@resetSearchState()
......
......@@ -3,10 +3,10 @@
class @ShortcutsDashboardNavigation extends Shortcuts
constructor: ->
super()
Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-activity'))
Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-issues'))
Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-merge_requests'))
Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-projects'))
Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-activity'))
Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-issues'))
Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-merge_requests'))
Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-projects'))
@findAndFollowLink: (selector) ->
link = $(selector).attr('href')
......
......@@ -26,6 +26,10 @@
# Personal projects
# </a>
# </li>
# <li class="snippets-tab">
# <a data-action="snippets" data-target="#snippets" data-toggle="tab" href="/u/username/snippets">
# </a>
# </li>
# </ul>
#
# <div class="tab-content">
......@@ -41,6 +45,9 @@
# <div class="tab-pane" id="projects">
# Projects content
# </div>
# <div class="tab-pane" id="snippets">
# Snippets content
# </div>
# </div>
#
# <div class="loading-status">
......@@ -100,7 +107,7 @@ class @UserTabs
if action is 'activity'
@loadActivities(source)
if action in ['groups', 'contributed', 'projects']
if action in ['groups', 'contributed', 'projects', 'snippets']
@loadTab(source, action)
loadTab: (source, action) ->
......
# This is a manifest file that'll be compiled into including all the files listed below.
# Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
# be included in the compiled file accessible from http://example.com/assets/application.js
# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
# the compiled file.
#
#= require d3
#= require_tree .
class @Calendar
constructor: (timestamps, @calendar_activities_path) ->
@currentSelectedDate = ''
@daySpace = 1
@daySize = 15
@daySizeWithSpace = @daySize + (@daySpace * 2)
@monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
@months = []
@highestValue = 0
# Get the highest value from the timestampes
_.each timestamps, (count) =>
if count > @highestValue
@highestValue = count
# Loop through the timestamps to create a group of objects
# The group of objects will be grouped based on the day of the week they are
@timestampsTmp = []
i = 0
group = 0
_.each timestamps, (count, date) =>
newDate = new Date parseInt(date) * 1000
day = newDate.getDay()
# Create a new group array if this is the first day of the week
# or if is first object
if (day is 0 and i isnt 0) or i is 0
@timestampsTmp.push []
group++
innerArray = @timestampsTmp[group-1]
# Push to the inner array the values that will be used to render map
innerArray.push
count: count
date: newDate
day: day
i++
# Init color functions
@color = @initColor()
@colorKey = @initColorKey()
# Init the svg element
@renderSvg(group)
@renderDays()
@renderMonths()
@renderDayTitles()
@renderKey()
@initTooltips()
renderSvg: (group) ->
@svg = d3.select '.js-contrib-calendar'
.append 'svg'
.attr 'width', (group + 1) * @daySizeWithSpace
.attr 'height', 167
.attr 'class', 'contrib-calendar'
renderDays: ->
@svg.selectAll 'g'
.data @timestampsTmp
.enter()
.append 'g'
.attr 'transform', (group, i) =>
_.each group, (stamp, a) =>
if a is 0 and stamp.day is 0
month = stamp.date.getMonth()
x = (@daySizeWithSpace * i + 1) + @daySizeWithSpace
lastMonth = _.last(@months)
if lastMonth?
lastMonthX = lastMonth.x
if !lastMonth?
@months.push
month: month
x: x
else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX
@months.push
month: month
x: x
"translate(#{(@daySizeWithSpace * i + 1) + @daySizeWithSpace}, 18)"
.selectAll 'rect'
.data (stamp) ->
stamp
.enter()
.append 'rect'
.attr 'x', '0'
.attr 'y', (stamp, i) =>
(@daySizeWithSpace * stamp.day)
.attr 'width', @daySize
.attr 'height', @daySize
.attr 'title', (stamp) =>
contribText = 'No contributions'
if stamp.count > 0
contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}"
date = dateFormat(stamp.date, 'mmm d, yyyy')
"#{contribText}<br />#{date}"
.attr 'class', 'user-contrib-cell js-tooltip'
.attr 'fill', (stamp) =>
if stamp.count isnt 0
@color(stamp.count)
else
'#ededed'
.attr 'data-container', 'body'
.on 'click', @clickDay
renderDayTitles: ->
days = [{
text: 'M'
y: 29 + (@daySizeWithSpace * 1)
}, {
text: 'W'
y: 29 + (@daySizeWithSpace * 3)
}, {
text: 'F'
y: 29 + (@daySizeWithSpace * 5)
}]
@svg.append 'g'
.selectAll 'text'
.data days
.enter()
.append 'text'
.attr 'text-anchor', 'middle'
.attr 'x', 8
.attr 'y', (day) ->
day.y
.text (day) ->
day.text
.attr 'class', 'user-contrib-text'
renderMonths: ->
@svg.append 'g'
.selectAll 'text'
.data @months
.enter()
.append 'text'
.attr 'x', (date) ->
date.x
.attr 'y', 10
.attr 'class', 'user-contrib-text'
.text (date) =>
@monthNames[date.month]
renderKey: ->
keyColors = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)]
@svg.append 'g'
.attr 'transform', "translate(18, #{@daySizeWithSpace * 8 + 16})"
.selectAll 'rect'
.data keyColors
.enter()
.append 'rect'
.attr 'width', @daySize
.attr 'height', @daySize
.attr 'x', (color, i) =>
@daySizeWithSpace * i
.attr 'y', 0
.attr 'fill', (color) ->
color
initColor: ->
d3.scale
.linear()
.range(['#acd5f2', '#254e77'])
.domain([0, @highestValue])
initColorKey: ->
d3.scale
.linear()
.range(['#acd5f2', '#254e77'])
.domain([0, 3])
clickDay: (stamp) =>
if @currentSelectedDate isnt stamp.date
@currentSelectedDate = stamp.date
formatted_date = @currentSelectedDate.getFullYear() + "-" + (@currentSelectedDate.getMonth()+1) + "-" + @currentSelectedDate.getDate()
$.ajax
url: @calendar_activities_path
data:
date: formatted_date
cache: false
dataType: 'html'
beforeSend: ->
$('.user-calendar-activities').html '<div class="text-center"><i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i></div>'
success: (data) ->
$('.user-calendar-activities').html data
else
$('.user-calendar-activities').html ''
initTooltips: ->
$('.js-contrib-calendar .js-tooltip').tooltip
html: true
......@@ -93,7 +93,9 @@ class @UsersSelect
$dropdown.glDropdown(
data: (term, callback) =>
@users term, (users) =>
isAuthorFilter = $('.js-author-search')
@users term, term is '' and isAuthorFilter, (users) =>
if term.length is 0
showDivider = 0
......@@ -138,7 +140,7 @@ class @UsersSelect
toggleLabel: (selected) ->
if selected && 'id' of selected
selected.name
if selected.text then selected.text else selected.name
else
defaultLabel
......@@ -219,7 +221,7 @@ class @UsersSelect
multiple: $(select).hasClass('multiselect')
minimumInputLength: 0
query: (query) =>
@users query.term, (users) =>
@users query.term, @projectId?, (users) =>
data = { results: users }
if query.term.length == 0
......@@ -302,7 +304,7 @@ class @UsersSelect
# Return users list. Filtered by query
# Only active users retrieved
users: (query, callback) =>
users: (query, fromProject, callback) =>
url = @buildUrl(@usersPath)
$.ajax(
......@@ -311,7 +313,7 @@ class @UsersSelect
search: query
per_page: 20
active: true
project_id: @projectId
project_id: @projectId if fromProject
group_id: @groupId
current_user: @showCurrentUser
author_id: @authorId
......
......@@ -8,9 +8,7 @@
*= require select2
*= require_self
*= require dropzone/basic
*= require cal-heatmap
*= require cropper.css
*= require animate
*/
/*
......
......@@ -5,6 +5,7 @@
@import 'framework/tw_bootstrap';
@import "framework/layout";
@import "framework/animations.scss";
@import "framework/avatar.scss";
@import "framework/blocks.scss";
@import "framework/buttons.scss";
......
// This file is based off animate.css 3.5.1, available here:
// https://github.com/daneden/animate.css/blob/3.5.1/animate.css
//
// animate.css - http://daneden.me/animate
// Version - 3.5.1
// Licensed under the MIT license - http://opensource.org/licenses/MIT
//
// Copyright (c) 2016 Daniel Eden
.animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.animated.infinite {
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.animated.hinge {
-webkit-animation-duration: 2s;
animation-duration: 2s;
}
.animated.flipOutX,
.animated.flipOutY,
.animated.bounceIn,
.animated.bounceOut {
-webkit-animation-duration: .75s;
animation-duration: .75s;
}
@-webkit-keyframes pulse {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes pulse {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.pulse {
-webkit-animation-name: pulse;
animation-name: pulse;
}
......@@ -45,6 +45,7 @@
&.s32 { font-size: 20px; line-height: 32px; }
&.s40 { font-size: 16px; line-height: 40px; }
&.s60 { font-size: 32px; line-height: 60px; }
&.s70 { font-size: 34px; line-height: 70px; }
&.s90 { font-size: 36px; line-height: 90px; }
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
&.s140 { font-size: 72px; line-height: 140px; }
......
......@@ -24,8 +24,8 @@
background-color: $background-color;
padding: $gl-padding;
margin-bottom: 0;
border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color;
border-top: 1px solid $white-dark;
border-bottom: 1px solid $white-dark;
color: $gl-gray;
&.oneline-block {
......@@ -110,9 +110,9 @@
.cover-title {
color: $gl-header-color;
margin: 0;
font-size: 23px;
font-size: 24px;
font-weight: normal;
margin: 16px 0 5px;
margin-bottom: 5px;
color: #4c4e54;
font-size: 23px;
line-height: 1.1;
......@@ -137,7 +137,6 @@
}
.cover-desc {
padding: 0 $gl-padding 3px;
color: $gl-text-color;
&.username:last-child {
......@@ -205,7 +204,7 @@
.content-block {
padding: $gl-padding 0;
border-bottom: 1px solid $border-color;
border-bottom: 1px solid $white-dark;
&.oneline-block {
line-height: 36px;
......
......@@ -16,6 +16,19 @@
@include btn-default;
}
@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border) {
background-color: $background;
color: $text;
border-color: $border;
&:hover,
&:focus {
background-color: $hover-background;
color: $hover-text;
border-color: $hover-border;;
}
}
@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
background-color: $light;
border-color: $border-light;
......@@ -106,11 +119,14 @@
@include btn-blue;
}
&.btn-close,
&.btn-warning {
@include btn-orange;
}
&.btn-close {
@include btn-outline($white-light, $orange-normal, $orange-normal, $orange-light, $white-light, $orange-light);
}
&.btn-danger,
&.btn-remove,
&.btn-red {
......
.calender-block {
padding-left: 0;
padding-right: 0;
@media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) {
overflow-x: scroll;
}
}
.user-calendar-activities {
.calendar_onclick_hr {
padding: 0;
margin: 10px 0;
}
.str-truncated {
max-width: 70%;
}
.text-expander {
background: #eee;
color: #555;
padding: 0 5px;
cursor: pointer;
margin-left: 4px;
&:hover {
background-color: #ddd;
}
.user-calendar-activities-loading {
font-size: 24px;
}
}
/**
* This overwrites the default values of the cal-heatmap gem
*/
.calendar {
.qi {
fill: #fff;
}
.q1 {
fill: #ededed !important;
}
.q2 {
fill: #acd5f2 !important;
}
.q3 {
fill: #7fa8d1 !important;
}
.q4 {
fill: #49729b !important;
}
.user-calendar {
text-align: center;
.q5 {
fill: #254e77 !important;
.calendar {
display: inline-block;
}
}
.future {
visibility: hidden;
.user-contrib-cell {
&:hover {
cursor: pointer;
stroke: #000;
}
}
.domain-background {
fill: none;
shape-rendering: crispedges;
}
.user-contrib-text {
font-size: 12px;
fill: #959494;
}
.ch-tooltip {
padding: 3px;
font-weight: 550;
}
.calendar-hint {
margin-top: -23px;
float: right;
font-size: 12px;
}
......@@ -289,7 +289,7 @@ table {
text-shadow: none;
@media (min-width: $screen-sm-min) {
margin-top: 11px;
margin-top: 8px;
}
}
......
......@@ -154,7 +154,7 @@
color: $dropdown-header-color;
font-size: 13px;
line-height: 22px;
padding: 0 10px 10px;
padding: 0 10px;
}
.separator + .dropdown-header {
......@@ -162,6 +162,10 @@
}
}
.dropdown-menu-full-width {
width: 100%;
}
.dropdown-menu-paging {
.dropdown-page-two,
.dropdown-menu-back {
......
......@@ -5,6 +5,10 @@
.file-holder {
border: 1px solid $border-color;
&.file-holder-no-border {
border: 0;
}
&.readme-holder {
margin: $gl-padding-top 0;
}
......@@ -23,8 +27,17 @@
word-wrap: break-word;
border-radius: 3px 3px 0 0;
&.file-title-clear {
padding-left: 0;
padding-right: 0;
background-color: transparent;
.file-actions {
right: 0;
}
}
.file-actions {
float: right;
position: absolute;
top: 5px;
right: 15px;
......@@ -36,22 +49,6 @@
}
}
.filename {
&.old {
display: inline-block;
span.idiff {
background-color: #f8cbcb;
}
}
&.new {
display: inline-block;
span.idiff {
background-color: #a6f3a6;
}
}
}
a:not(.btn) {
color: $gl-dark-link-color;
}
......
......@@ -28,10 +28,6 @@ input[type='text'].danger {
}
label {
&.control-label {
@extend .col-sm-2;
}
&.inline-label {
margin: 0;
}
......@@ -41,6 +37,10 @@ label {
}
}
.control-label {
@extend .col-sm-2;
}
.inline-input-group {
width: 250px;
}
......
......@@ -9,8 +9,7 @@
@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) {
.page-with-sidebar {
.header-logo {
background-color: $color;
border-color: $color;
background: $color-darker;
a {
color: $color-light;
......@@ -21,7 +20,7 @@
}
&:hover {
background-color: $color-darker;
background-color: $color-dark;
a {
color: #fff;
......@@ -91,8 +90,8 @@
}
$theme-blue: #2980b9;
$theme-charcoal: #333c47;
$theme-graphite: #888;
$theme-charcoal: #3d454d;
$theme-graphite: #666;
$theme-gray: #373737;
$theme-green: #019875;
$theme-violet: #548;
......@@ -103,11 +102,11 @@ body {
}
&.ui_charcoal {
@include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272d);
@include gitlab-theme(#d6d7d9, #485157, $theme-charcoal, #353b41);
}
&.ui_graphite {
@include gitlab-theme(#ccc, $theme-graphite, #777, #666);
@include gitlab-theme(#ccc, #777, $theme-graphite, #555);
}
&.ui_gray {
......
......@@ -6,12 +6,12 @@ header {
transition-duration: .3s;
&.navbar-empty {
height: 58px;
height: $header-height;
background: #fff;
border-bottom: 1px solid $btn-gray-hover;
.center-logo {
margin: 11px 0;
margin: 8px 0;
text-align: center;
#tanuki-logo, img {
......
......@@ -48,10 +48,6 @@
display: block;
}
.project-home-desc {
font-size: 21px;
}
.project-repo-buttons,
.git-clone-holder {
display: none;
......
@mixin fade($gradient-direction, $rgba, $gradient-color) {
visibility: visible;
opacity: 1;
position: absolute;
bottom: 12px;
width: 43px;
height: 30px;
transition-duration: .3s;
-webkit-transform: translateZ(0);
background: -webkit-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
background: -o-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
background: -moz-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
background: linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
&.end-scroll {
visibility: hidden;
opacity: 0;
transition-duration: .3s;
}
}
@mixin scrolling-links() {
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
}
.nav-links {
padding: 0;
margin: 0;
......@@ -119,7 +150,7 @@
}
input {
height: 34px;
height: 35px;
display: inline-block;
position: relative;
top: 2px;
......@@ -196,7 +227,7 @@
position: fixed;
top: $header-height;
width: 100%;
z-index: 1;
z-index: 11;
background: $background-color;
border-bottom: 1px solid $border-color;
transition-duration: .3s;
......@@ -209,6 +240,10 @@
float: right;
padding: 7px 0 0;
@media (max-width: $screen-xs-max) {
display: none;
}
i {
color: $layout-link-gray;
}
......@@ -225,14 +260,31 @@
.dropdown {
margin-left: 7px;
@media (max-width: $screen-xs-min) {
margin-left: 0;
}
li.active {
font-weight: bold;
}
}
}
.nav-links {
@include scrolling-links();
border-bottom: none;
height: 51px;
white-space: nowrap;
overflow-x: auto;
.fade-right {
@include fade(left, rgba(250, 250, 250, 0.4), $background-color);
right: 0;
}
.fade-left {
@include fade(right, rgba(250, 250, 250, 0.4), $background-color);
left: 0;
}
li {
......@@ -256,8 +308,62 @@
}
}
.nav-control {
.fade-right {
@media (min-width: $screen-xs-max) {
right: 67px;
}
@media (max-width: $screen-xs-min) {
right: 0;
}
}
}
}
.nav-block {
position: relative;
.nav-links {
@include scrolling-links();
.fade-right {
@include fade(left, rgba(255, 255, 255, 0.4), $white-light);
right: 0;
}
.fade-left {
@include fade(right, rgba(255, 255, 255, 0.4), $white-light);
left: 0;
}
&.event-filter {
.fade-right {
visibility: hidden;
@media (max-width: $screen-xs-max) {
visibility: visible;
}
}
}
}
}
.page-with-layout-nav {
margin-top: 50px;
margin-top: $header-height + 2;
.right-sidebar {
top: ($header-height * 2) + 2;
}
}
.activities {
.nav-block {
border-bottom: 1px solid $border-color;
.nav-links {
border-bottom: none;
}
}
}
......@@ -312,7 +312,7 @@
}
.nav-sidebar li a {
width: 230px;
width: $sidebar_width;
&.back-link {
i {
......@@ -324,7 +324,7 @@
.layout-nav {
@media (max-width: $screen-xs-min) {
padding-right: 0;;
padding-right: 0;
}
@media (min-width: $screen-xs-min) and (max-width: $screen-md-min) {
......
......@@ -269,3 +269,11 @@ h1, h2, h3, h4 {
text-align: right;
}
}
.idiff.deletion {
background: $line-removed-dark;
}
.idiff.addition {
background: $line-added-dark;
}
......@@ -2,7 +2,7 @@
* Layout
*/
$sidebar_collapsed_width: 62px;
$sidebar_width: 230px;
$sidebar_width: 220px;
$gutter_collapsed_width: 62px;
$gutter_width: 290px;
$gutter_inner_width: 258px;
......@@ -12,7 +12,7 @@ $gutter_inner_width: 258px;
*/
$border-color: #e5e5e5;
$focus-border-color: #3aabf0;
$table-border-color: #ececec;
$table-border-color: #f0f0f0;
$background-color: #fafafa;
/*
......@@ -63,7 +63,8 @@ $gl-padding-top: 10px;
/*
* Misc
*/
$row-hover: #f4f8fe;
$row-hover: #f7faff;
$row-hover-border: #b2d7ff;
$progress-color: #c0392b;
$avatar_radius: 50%;
$header-height: 50px;
......@@ -104,7 +105,7 @@ $blue-medium-light: #3498cb;
$blue-medium: #2f8ebf;
$blue-medium-dark: #2d86b4;
$orange-light: rgba(252, 109, 38, 0.80);
$orange-light: #fc8a51;
$orange-normal: #e75e40;
$orange-dark: #ce5237;
......@@ -119,8 +120,8 @@ $border-white-light: #f1f2f4;
$border-white-normal: #d6dae2;
$border-white-dark: #c6cacf;
$border-gray-light: rgba(0, 0, 0, 0.06);
$border-gray-normal: rgba(0, 0, 0, 0.10);;
$border-gray-light: #dcdcdc;
$border-gray-normal: rgba(0, 0, 0, 0.10);
$border-gray-dark: #c6cacf;
$border-green-light: #2faa60;
......@@ -178,6 +179,7 @@ $table-border-gray: #f0f0f0;
$line-target-blue: #eaf3fc;
$line-select-yellow: #fcf8e7;
$line-select-yellow-dark: #f0e2bd;
/*
* Fonts
*/
......
......@@ -32,7 +32,7 @@
}
}
.zen-cotrol {
.zen-control {
padding: 0;
color: #555;
background: none;
......
// NOTE: This stylesheet is for the exclusive use of the `devise_mailer` layout
// used for Devise email templates, and _should not_ be included in any
// application stylesheets.
//
// Styles defined here are embedded directly into the resulting email HTML via
// the `premailer` gem.
$body-background-color: #363636;
$message-background-color: #fafafa;
$header-color: #6b4fbb;
$body-color: #444;
$cta-color: #e14329;
$footer-link-color: #7e7e7e;
$font-family: Helvetica, Arial, sans-serif;
body {
background-color: $body-background-color;
font-family: $font-family;
margin: 0;
padding: 0;
}
table {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
border: 0;
border-collapse: separate;
&#wrapper {
background-color: $body-background-color;
width: 100%;
}
&#header {
margin: 0 auto;
text-align: left;
width: 600px;
}
&#body {
background-color: $message-background-color;
border: 1px solid #000;
border-radius: 4px;
margin: 0 auto;
width: 600px;
}
&#footer {
color: $footer-link-color;
font-size: 14px;
text-align: center;
width: 100%;
}
td {
&#body-container {
padding: 20px 40px;
}
}
}
.center {
text-align: center;
}
#logo {
border: none;
outline: none;
min-height: 88px;
width: 134px;
}
#content {
h2 {
color: $header-color;
font-size: 30px;
font-weight: 400;
line-height: 34px;
margin-top: 0;
}
p {
color: $body-color;
font-size: 17px;
line-height: 24px;
margin-bottom: 0;
}
}
#cta {
border: 1px solid $cta-color;
border-radius: 3px;
display: inline-block;
margin: 20px 0;
padding: 12px 24px;
a {
background-color: $message-background-color;
color: $cta-color;
display: inline-block;
text-decoration: none;
}
}
#tanuki {
padding: 40px 0 0;
img {
border: none;
outline: none;
width: 37px;
min-height: 36px;
}
}
#tagline {
font-size: 22px;
font-weight: 100;
padding: 4px 0 40px;
}
#social {
padding: 0 10px 20px;
width: 600px;
word-spacing: 20px;
a {
color: $footer-link-color;
text-decoration: none;
}
}
@import "framework/variables";
table.code {
width: 100%;
font-family: monospace;
border: none;
border-collapse: separate;
margin: 0;
padding: 0;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
td {
line-height: $code_line_height;
font-family: monospace;
font-size: $code_font_size;
}
td.diff-line-num {
margin: 0;
padding: 0;
border: none;
background: $background-color;
color: rgba(0, 0, 0, 0.3);
padding: 0 5px;
border-right: 1px solid $border-color;
text-align: right;
min-width: 35px;
max-width: 50px;
width: 35px;
}
td.line_content {
display: block;
margin: 0;
padding: 0 0.5em;
border: none;
white-space: pre;
}
}
@import "highlight/white";
......@@ -26,8 +26,28 @@
.commit-info-row {
margin-bottom: 10px;
&.commit-info-row-header {
line-height: 34px;
@media (min-width: $screen-sm-min) {
margin-bottom: 0;
}
.commit-options-dropdown-caret {
@media (max-width: $screen-sm) {
margin-left: 0;
}
}
}
.avatar {
@extend .avatar-inline;
margin-left: 0;
@media (min-width: $screen-sm-min) {
margin-left: 4px;
}
}
.commit-committer-link,
.commit-author-link {
......@@ -35,10 +55,6 @@
font-weight: bold;
}
.time_ago {
margin-left: 8px;
}
.fa-clipboard {
color: $dropdown-title-btn-color;
}
......
......@@ -29,8 +29,6 @@
margin-top: 6px;
p {
overflow-x: auto;
&:last-child {
margin-bottom: 0;
}
......
......@@ -23,7 +23,7 @@
.file-title {
@extend .monospace;
line-height: 42px;
line-height: 35px;
padding-top: 7px;
padding-bottom: 7px;
......@@ -59,7 +59,22 @@
}
.encoding-selector,
.license-selector {
.license-selector,
.gitignore-selector {
display: inline-block;
vertical-align: top;
font-family: $regular_font;
}
.gitignore-selector {
.dropdown {
line-height: 21px;
}
.dropdown-menu-toggle {
vertical-align: top;
width: 220px;
}
}
}
......@@ -125,7 +125,7 @@
.right-sidebar {
position: fixed;
top: 58px;
top: $header-height;
bottom: 0;
right: 0;
z-index: 10;
......@@ -150,6 +150,10 @@
font-weight: 600;
}
.light {
font-weight: normal;
}
.sidebar-collapsed-icon {
display: none;
}
......
......@@ -40,11 +40,6 @@
}
}
.issue-search-form {
margin: 0;
height: 24px;
}
form.edit-issue {
margin: 0;
}
......@@ -96,8 +91,3 @@ form.edit-issue {
.issue-form .select2-container {
width: 250px !important;
}
.issue-closed-by-widget {
color: $gl-text-color;
margin-left: 52px;
}
......@@ -41,7 +41,7 @@
margin: 0;
margin-left: 20px;
padding: 5px;
padding-top: 12px;
padding-top: 8px;
line-height: 20px;
&.right {
......@@ -110,6 +110,29 @@
p:last-child {
margin-bottom: 0;
}
@media (max-width: $screen-sm-max) {
h4 {
font-size: 15px;
}
p {
font-size: 13px;
}
.btn,
.btn-group,
.accept-action {
width: 100%;
margin-bottom: 4px;
}
.accept-control {
width: 100%;
text-align: center;
margin: 0;
}
}
}
.mr-widget-footer {
......@@ -280,11 +303,5 @@
background-color: $white-light;
color: $gl-placeholder-color;
}
th,
td {
padding: 16px;
}
}
}
......@@ -226,8 +226,7 @@ ul.notes {
}
}
.note-action-button,
.discussion-action-button {
.note-action-button {
display: inline-block;
margin-left: 10px;
line-height: 24px;
......
.pipelines {
.stage {
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.duration, .finished_at {
margin: 4px 0;
}
.commit-title {
margin: 0;
}
.controls {
white-space: nowrap;
}
.btn {
margin: 4px;
}
}
......@@ -66,12 +66,6 @@
}
}
.calendar-hint {
margin-top: -12px;
float: right;
font-size: 12px;
}
.profile-link-holder {
display: inline;
......@@ -134,14 +128,6 @@
}
}
.change-username-title {
color: $gl-warning;
}
.remove-account-title {
color: $gl-danger;
}
.provider-btn-group {
display: inline-block;
margin-right: 10px;
......
......@@ -7,10 +7,10 @@
}
.no-ssh-key-message, .project-limit-message {
background-color: #f28d35;
margin-bottom: 16px;
margin-bottom: 0;
}
.new_project,
.edit_project {
.edit-project {
fieldset.features {
.control-label {
font-weight: normal;
......@@ -26,8 +26,13 @@
}
.project-home-panel {
padding-bottom: 40px;
border-bottom: 1px solid $border-color;
background: $white-light;
text-align: left;
padding: 24px 0;
.container-fluid {
position: relative;
}
.cover-controls {
.project-settings-dropdown {
......@@ -43,21 +48,55 @@
}
}
.project-identicon-holder {
margin-bottom: 16px;
.cover-title {
margin-bottom: 0;
}
.project-image-container {
@include make-sm-column(1);
max-width: 86px;
min-width: 86px;
padding-right: 0;
margin: 11px 0;
.avatar, .identicon {
margin: 0 auto;
float: none;
@media (max-width: $screen-md-max) {
padding-left: 0;
margin: 0 0 10px;
max-width: none;
min-width: none;
.avatar.s70 {
margin: auto;
}
}
}
.project-info {
@include make-sm-column(10);
h1 {
font-size: 24px;
font-weight: normal;
margin: 0;
}
.project-home-desc {
p {
margin: 0;
}
}
}
.identicon {
float: left;
@include border-radius(50%);
}
.avatar {
float: none;
}
.notifications-btn {
margin-top: -28px;
.fa-bell {
margin-right: 6px;
......@@ -69,28 +108,45 @@
}
.project-repo-buttons {
margin-top: 20px;
margin-bottom: 0;
font-size: 0;
.count-buttons {
display: block;
margin-bottom: 20px;
.btn {
@include btn-gray;
padding: 3px 10px;
text-transform: none;
background-color: $background-color;
.fa {
color: $layout-link-gray;
}
.clone-row {
.split-repo-buttons,
.project-clone-holder {
display: inline-block;
.fa-caret-down {
margin-left: 3px;
}
}
.split-repo-buttons {
margin: 0 12px;
.btn-group:not(:first-child):not(:last-child) > .btn {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
form {
margin-left: 10px;
}
.btn {
@include btn-gray;
text-transform: none;
.count-buttons {
display: inline-block;
vertical-align: top;
margin-top: 16px;
}
.project-clone-holder {
display: inline-block;
margin-top: 16px;
input {
height: 29px;
}
}
.count-with-arrow {
......@@ -140,14 +196,18 @@
line-height: 13px;
padding: $gl-vert-padding $gl-padding;
letter-spacing: .4px;
padding: 10px 14px;
padding: 7px 14px;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
white-space: nowrap;
margin: 0 11px 0 4px;
margin: 0 10px 0 4px;
a {
color: inherit;
}
&:hover {
background: #fff;
......@@ -155,13 +215,37 @@
}
}
}
.project-right-buttons {
position: absolute;
right: 16px;
bottom: 0;
.btn {
padding: 3px 10px;
background-color: $background-color;
}
@media (max-width: 1304px) {
top: 0;
}
}
@media (max-width: $screen-md-max) {
text-align: center;
.project-info,
.project-image-container {
width: 100%;
}
}
}
.split-one {
display: inline-table;
margin-right: 12px;
a {
> a {
margin: -1px;
}
}
......@@ -285,11 +369,11 @@ a.deploy-project-label {
}
.project-stats {
text-align: center;
margin-top: $gl-padding;
margin-bottom: 0;
padding-top: 10px;
padding-bottom: 4px;
padding: 16px 0;
background-color: $white-light;
font-size: 0;
ul.nav {
display: inline-block;
......@@ -300,12 +384,11 @@ a.deploy-project-label {
}
.nav > li > a {
@include btn-default;
@include btn-gray;
background-color: transparent;
border: 1px solid #f7f8fa;
margin-left: 12px;
margin-right: 12px;
padding: 0 10px;
font-size: 15px;
color: $notes-light-color;
}
li {
......@@ -325,6 +408,10 @@ a.deploy-project-label {
background-color: #f0f2f5;
}
}
&.row-content-block.second-block {
margin-top: 0;
}
}
pre.light-well {
......@@ -442,9 +529,14 @@ pre.light-well {
border-top: 0;
.edit-project-readme {
z-index: 100;
z-index: 2;
position: relative;
}
.wiki h1 {
border-bottom: none;
padding: 0;
}
}
.git-clone-holder {
......
......@@ -28,6 +28,7 @@
}
.search-input {
padding-right: 20px;
border: none;
font-size: 14px;
outline: none;
......@@ -47,6 +48,7 @@
display: inline-block;
background-color: $location-badge-bg;
vertical-align: top;
cursor: default;
}
.search-input-container {
......@@ -55,7 +57,7 @@
position: relative;
}
.search-location-badge, .search-input-wrap {
.search-input-wrap {
// Fallback if flexbox is not supported
display: inline-block;
}
......
......@@ -12,3 +12,11 @@
border: 1px solid $warning-message-border;
border-radius: $border-radius-base;
}
.warning-title {
color: $gl-warning;
}
.danger-title {
color: $gl-danger;
}
......@@ -16,19 +16,6 @@
}
}
.snippet-box {
@include border-radius(2px);
display: block;
float: left;
padding: 0 $gl-padding;
font-weight: normal;
margin-right: 10px;
font-size: $gl-font-size;
border: 1px solid;
line-height: 32px;
}
.markdown-snippet-copy {
position: fixed;
top: -10px;
......@@ -36,3 +23,34 @@
max-height: 0;
max-width: 0;
}
.file-holder.snippet-file-content {
padding-bottom: $gl-padding;
border-bottom: 1px solid $border-color;
.file-title {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
}
.file-actions {
top: 12px;
}
.file-content {
border-left: 1px solid $border-color;
border-right: 1px solid $border-color;
border-bottom: 1px solid $border-color;
}
}
.snippet-title {
font-size: 24px;
font-weight: normal;
}
.snippet-actions {
@media (min-width: $screen-sm-min) {
float: right;
}
}
......@@ -29,6 +29,17 @@
.todo-item {
.todo-title {
@include str-truncated(calc(100% - 174px));
overflow: visible;
}
.status-box {
margin: 0;
float: none;
display: inline-block;
font-weight: normal;
padding: 0 5px;
line-height: inherit;
font-size: 14px;
}
.todo-body {
......@@ -76,12 +87,11 @@
@media (max-width: $screen-xs-max) {
.todo-item {
padding-left: $gl-padding;
.todo-title {
white-space: normal;
overflow: visible;
max-width: 100%;
margin-bottom: 10px;
}
.avatar {
......
......@@ -15,16 +15,23 @@
margin-bottom: 0;
tr {
> td, > th {
border-bottom: 1px solid $table-border-gray;
border-top: 1px solid $table-border-gray;
td, th {
line-height: 23px;
}
&:hover {
cursor: pointer;
td {
background: $row-hover;
background-color: $row-hover;
border-top: 1px solid $row-hover-border;
border-bottom: 1px solid $row-hover-border;
}
cursor: pointer;
}
&.selected {
td {
background: $gray-dark;
......
......@@ -9,6 +9,6 @@ class Admin::AbuseReportsController < Admin::ApplicationController
abuse_report.remove_user(deleted_by: current_user) if params[:remove_user]
abuse_report.destroy
render nothing: true
head :ok
end
end
......@@ -19,6 +19,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
redirect_to admin_runners_path
end
def reset_health_check_token
@application_setting.reset_health_check_access_token!
flash[:notice] = 'New health check access token has been generated!'
redirect_to :back
end
def clear_repository_check_states
RepositoryCheck::ClearWorker.perform_async
......@@ -53,6 +59,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
end
end
enabled_oauth_sign_in_sources = params[:application_setting].delete(:enabled_oauth_sign_in_sources)
params[:application_setting][:disabled_oauth_sign_in_sources] =
AuthHelper.button_based_providers.map(&:to_s) -
Array(enabled_oauth_sign_in_sources)
params.require(:application_setting).permit(
:default_projects_limit,
:default_branch_protection,
......@@ -94,8 +106,11 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:email_author_in_body,
:repository_checks_enabled,
:metrics_packet_size,
:send_user_confirmation_email,
:container_registry_token_expire_delay,
restricted_visibility_levels: [],
import_sources: []
import_sources: [],
disabled_oauth_sign_in_sources: []
)
end
end
......@@ -32,7 +32,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
respond_to do |format|
format.html { redirect_back_or_default(default: { action: 'index' }) }
format.js { render nothing: true }
format.js { head :ok }
end
end
......
class Admin::HealthCheckController < Admin::ApplicationController
def show
@errors = HealthCheck::Utils.process_checks('standard')
end
end
......@@ -6,7 +6,7 @@ class Admin::KeysController < Admin::ApplicationController
respond_to do |format|
format.html
format.js { render nothing: true }
format.js { head :ok }
end
end
......
......@@ -9,24 +9,19 @@ class Admin::RunnersController < Admin::ApplicationController
end
def show
@builds = @runner.builds.order('id DESC').first(30)
@projects =
if params[:search].present?
::Project.search(params[:search])
else
Project.all
end
@projects = @projects.where.not(id: @runner.projects.select(:id)) if @runner.projects.any?
@projects = @projects.page(params[:page]).per(30)
assign_builds_and_projects
end
def update
@runner.update_attributes(runner_params)
if @runner.update_attributes(runner_params)
respond_to do |format|
format.js
format.html { redirect_to admin_runner_path(@runner) }
end
else
assign_builds_and_projects
render 'show'
end
end
def destroy
......@@ -58,6 +53,18 @@ class Admin::RunnersController < Admin::ApplicationController
end
def runner_params
params.require(:runner).permit(:token, :description, :tag_list, :active)
params.require(:runner).permit(Ci::Runner::FORM_EDITABLE)
end
def assign_builds_and_projects
@builds = runner.builds.order('id DESC').first(30)
@projects =
if params[:search].present?
::Project.search(params[:search])
else
Project.all
end
@projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any?
@projects = @projects.page(params[:page]).per(30)
end
end
......@@ -11,7 +11,7 @@ class Admin::SpamLogsController < Admin::ApplicationController
redirect_to admin_spam_logs_path, notice: "User #{spam_log.user.username} was successfully removed."
else
spam_log.destroy
render nothing: true
head :ok
end
end
end
......@@ -119,6 +119,7 @@ class Admin::UsersController < Admin::ApplicationController
user_params_with_pass.merge!(
password: params[:user][:password],
password_confirmation: params[:user][:password_confirmation],
password_expires_at: Time.now
)
end
......@@ -153,7 +154,7 @@ class Admin::UsersController < Admin::ApplicationController
respond_to do |format|
format.html { redirect_back_or_admin_user(notice: "Successfully removed email.") }
format.js { render nothing: true }
format.js { head :ok }
end
end
......
......@@ -222,7 +222,7 @@ class ApplicationController < ActionController::Base
end
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :login, :remember_me, :otp_attempt) }
devise_parameter_sanitizer.permit(:sign_in, keys: [:username, :email, :password, :login, :remember_me, :otp_attempt])
end
def hexdigest(string)
......@@ -253,7 +253,7 @@ class ApplicationController < ActionController::Base
# internal repos where you are not a member. Enable this filter
# or improve current implementation to filter only issues you
# created or assigned or mentioned
#@filter_params[:authorized_only] = true
# @filter_params[:authorized_only] = true
end
@filter_params
......
......@@ -31,6 +31,24 @@ class AutocompleteController < ApplicationController
render json: @user, only: [:name, :username, :id], methods: [:avatar_url]
end
def projects
project = Project.find_by_id(params[:project_id])
projects = current_user.authorized_projects
projects = projects.select do |project|
current_user.can?(:admin_issue, project)
end
no_project = {
id: 0,
name_with_namespace: 'No project',
}
projects.unshift(no_project)
projects.delete(project)
render json: projects.to_json(only: [:id, :name_with_namespace], methods: :name_with_namespace)
end
private
def find_users
......
......@@ -6,7 +6,7 @@ module ToggleSubscriptionAction
subscribable_resource.toggle_subscription(current_user)
render nothing: true
head :ok
end
private
......
......@@ -28,7 +28,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
end
def starred
@projects = current_user.starred_projects.sorted_by_activity
@projects = current_user.viewable_starred_projects.sorted_by_activity
@projects = filter_projects(@projects)
@projects = @projects.includes(:namespace, :forked_from_project, :tags)
@projects = @projects.sort(@sort = params[:sort])
......
......@@ -12,7 +12,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
respond_to do |format|
format.html { redirect_to dashboard_todos_path, notice: todo_notice }
format.js { render nothing: true }
format.js { head :ok }
format.json do
render json: { count: @todos.size, done_count: current_user.todos.done.count }
end
......@@ -24,7 +24,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
respond_to do |format|
format.html { redirect_to dashboard_todos_path, notice: 'All todos were marked as done.' }
format.js { render nothing: true }
format.js { head :ok }
format.json do
find_todos
render json: { count: @todos.size, done_count: current_user.todos.done.count }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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