Merge remote-tracking branch 'origin/master' into rename-ci-commit
This commit is contained in:
commit
c5d3ca3ecb
8 changed files with 274 additions and 18 deletions
|
@ -44,6 +44,7 @@ v 8.8.4 (unreleased)
|
|||
- Fix issue with arrow keys not working in search autocomplete dropdown
|
||||
- Fix todos page throwing errors when you have a project pending deletion
|
||||
- Reduce number of SQL queries when rendering user references
|
||||
- Upgrade to jQuery 2
|
||||
|
||||
v 8.8.3
|
||||
- Fix 404 page when viewing TODOs that contain milestones or labels in different projects. !4312
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# 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 jquery
|
||||
#= require jquery2
|
||||
#= require jquery-ui/autocomplete
|
||||
#= require jquery-ui/datepicker
|
||||
#= require jquery-ui/draggable
|
||||
|
|
|
@ -21,7 +21,7 @@ class @DueDateSelect
|
|||
$dropdown.glDropdown(
|
||||
hidden: ->
|
||||
$selectbox.hide()
|
||||
$value.removeAttr('style')
|
||||
$value.css('display', '')
|
||||
)
|
||||
|
||||
addDueDate = (isDropdown) ->
|
||||
|
@ -42,12 +42,13 @@ class @DueDateSelect
|
|||
type: 'PUT'
|
||||
url: issueUpdateURL
|
||||
data: data
|
||||
dataType: 'json'
|
||||
beforeSend: ->
|
||||
$loading.fadeIn()
|
||||
if isDropdown
|
||||
$dropdown.trigger('loading.gl.dropdown')
|
||||
$selectbox.hide()
|
||||
$value.removeAttr('style')
|
||||
$value.css('display', '')
|
||||
|
||||
$valueContent.html(mediumDate)
|
||||
$sidebarValue.html(mediumDate)
|
||||
|
|
|
@ -83,7 +83,7 @@ class @MilestoneSelect
|
|||
$selectbox.hide()
|
||||
|
||||
# display:block overrides the hide-collapse rule
|
||||
$value.removeAttr('style')
|
||||
$value.css('display', '')
|
||||
clicked: (selected) ->
|
||||
page = $('body').data 'page'
|
||||
isIssueIndex = page is 'projects:issues:index'
|
||||
|
@ -118,7 +118,7 @@ class @MilestoneSelect
|
|||
$dropdown.trigger('loaded.gl.dropdown')
|
||||
$loading.fadeOut()
|
||||
$selectbox.hide()
|
||||
$value.removeAttr('style')
|
||||
$value.css('display', '')
|
||||
if data.milestone?
|
||||
data.milestone.namespace = _this.currentProject.namespace
|
||||
data.milestone.path = _this.currentProject.path
|
||||
|
|
|
@ -149,7 +149,7 @@ class @UsersSelect
|
|||
hidden: (e) ->
|
||||
$selectbox.hide()
|
||||
# display:block overrides the hide-collapse rule
|
||||
$value.removeAttr('style')
|
||||
$value.css('display', '')
|
||||
|
||||
clicked: (user) ->
|
||||
page = $('body').data 'page'
|
||||
|
|
|
@ -365,13 +365,9 @@ describe 'Issues', feature: true do
|
|||
|
||||
page.within('.assignee') do
|
||||
expect(page).to have_content "#{@user.name}"
|
||||
end
|
||||
|
||||
find('.block.assignee .edit-link').click
|
||||
sleep 2 # wait for ajax stuff to complete
|
||||
first('.dropdown-menu-user-link').click
|
||||
sleep 2
|
||||
page.within('.assignee') do
|
||||
click_link 'Edit'
|
||||
click_link 'Unassigned'
|
||||
expect(page).to have_content 'No assignee'
|
||||
end
|
||||
|
||||
|
|
|
@ -9,14 +9,14 @@ describe("ContributorsStatGraphUtil", function () {
|
|||
{author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 6, deletions: 1},
|
||||
{author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 19, deletions: 3},
|
||||
{author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 29, deletions: 3}]
|
||||
|
||||
|
||||
var correct_parsed_log = {
|
||||
total: [
|
||||
{date: "2013-05-09", additions: 471, deletions: 0, commits: 1},
|
||||
{date: "2013-05-08", additions: 54, deletions: 7, commits: 3}],
|
||||
by_author:
|
||||
[
|
||||
{
|
||||
{
|
||||
author_name: "Karlo Soriano", author_email: "karlo@email.com",
|
||||
"2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
|
||||
},
|
||||
|
@ -132,8 +132,8 @@ describe("ContributorsStatGraphUtil", function () {
|
|||
total: [{date: "2013-05-09", additions: 471, deletions: 0, commits: 1},
|
||||
{date: "2013-05-08", additions: 54, deletions: 7, commits: 3}],
|
||||
by_author:[
|
||||
{
|
||||
author: "Karlo Soriano",
|
||||
{
|
||||
author: "Karlo Soriano",
|
||||
"2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
|
||||
},
|
||||
{
|
||||
|
@ -161,11 +161,11 @@ describe("ContributorsStatGraphUtil", function () {
|
|||
it("returns the log by author sorted by specified field", function () {
|
||||
var fake_parsed_log = {
|
||||
total: [
|
||||
{date: "2013-05-09", additions: 471, deletions: 0, commits: 1},
|
||||
{date: "2013-05-09", additions: 471, deletions: 0, commits: 1},
|
||||
{date: "2013-05-08", additions: 54, deletions: 7, commits: 3}
|
||||
],
|
||||
by_author: [
|
||||
{
|
||||
{
|
||||
author_name: "Karlo Soriano", author_email: "karlo@email.com",
|
||||
"2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
|
||||
},
|
||||
|
|
258
vendor/assets/javascripts/task_list.js.coffee
vendored
Normal file
258
vendor/assets/javascripts/task_list.js.coffee
vendored
Normal file
|
@ -0,0 +1,258 @@
|
|||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2014 GitHub, Inc.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
# TaskList Behavior
|
||||
#
|
||||
#= provides tasklist:enabled
|
||||
#= provides tasklist:disabled
|
||||
#= provides tasklist:change
|
||||
#= provides tasklist:changed
|
||||
#
|
||||
#
|
||||
# Enables Task List update behavior.
|
||||
#
|
||||
# ### Example Markup
|
||||
#
|
||||
# <div class="js-task-list-container">
|
||||
# <ul class="task-list">
|
||||
# <li class="task-list-item">
|
||||
# <input type="checkbox" class="js-task-list-item-checkbox" disabled />
|
||||
# text
|
||||
# </li>
|
||||
# </ul>
|
||||
# <form>
|
||||
# <textarea class="js-task-list-field">- [ ] text</textarea>
|
||||
# </form>
|
||||
# </div>
|
||||
#
|
||||
# ### Specification
|
||||
#
|
||||
# TaskLists MUST be contained in a `(div).js-task-list-container`.
|
||||
#
|
||||
# TaskList Items SHOULD be an a list (`UL`/`OL`) element.
|
||||
#
|
||||
# Task list items MUST match `(input).task-list-item-checkbox` and MUST be
|
||||
# `disabled` by default.
|
||||
#
|
||||
# TaskLists MUST have a `(textarea).js-task-list-field` form element whose
|
||||
# `value` attribute is the source (Markdown) to be udpated. The source MUST
|
||||
# follow the syntax guidelines.
|
||||
#
|
||||
# TaskList updates trigger `tasklist:change` events. If the change is
|
||||
# successful, `tasklist:changed` is fired. The change can be canceled.
|
||||
#
|
||||
# jQuery is required.
|
||||
#
|
||||
# ### Methods
|
||||
#
|
||||
# `.taskList('enable')` or `.taskList()`
|
||||
#
|
||||
# Enables TaskList updates for the container.
|
||||
#
|
||||
# `.taskList('disable')`
|
||||
#
|
||||
# Disables TaskList updates for the container.
|
||||
#
|
||||
## ### Events
|
||||
#
|
||||
# `tasklist:enabled`
|
||||
#
|
||||
# Fired when the TaskList is enabled.
|
||||
#
|
||||
# * **Synchronicity** Sync
|
||||
# * **Bubbles** Yes
|
||||
# * **Cancelable** No
|
||||
# * **Target** `.js-task-list-container`
|
||||
#
|
||||
# `tasklist:disabled`
|
||||
#
|
||||
# Fired when the TaskList is disabled.
|
||||
#
|
||||
# * **Synchronicity** Sync
|
||||
# * **Bubbles** Yes
|
||||
# * **Cancelable** No
|
||||
# * **Target** `.js-task-list-container`
|
||||
#
|
||||
# `tasklist:change`
|
||||
#
|
||||
# Fired before the TaskList item change takes affect.
|
||||
#
|
||||
# * **Synchronicity** Sync
|
||||
# * **Bubbles** Yes
|
||||
# * **Cancelable** Yes
|
||||
# * **Target** `.js-task-list-field`
|
||||
#
|
||||
# `tasklist:changed`
|
||||
#
|
||||
# Fired once the TaskList item change has taken affect.
|
||||
#
|
||||
# * **Synchronicity** Sync
|
||||
# * **Bubbles** Yes
|
||||
# * **Cancelable** No
|
||||
# * **Target** `.js-task-list-field`
|
||||
#
|
||||
# ### NOTE
|
||||
#
|
||||
# Task list checkboxes are rendered as disabled by default because rendered
|
||||
# user content is cached without regard for the viewer.
|
||||
|
||||
incomplete = "[ ]"
|
||||
complete = "[x]"
|
||||
|
||||
# Escapes the String for regular expression matching.
|
||||
escapePattern = (str) ->
|
||||
str.
|
||||
replace(/([\[\]])/g, "\\$1"). # escape square brackets
|
||||
replace(/\s/, "\\s"). # match all white space
|
||||
replace("x", "[xX]") # match all cases
|
||||
|
||||
incompletePattern = ///
|
||||
#{escapePattern(incomplete)}
|
||||
///
|
||||
completePattern = ///
|
||||
#{escapePattern(complete)}
|
||||
///
|
||||
|
||||
# Pattern used to identify all task list items.
|
||||
# Useful when you need iterate over all items.
|
||||
itemPattern = ///
|
||||
^
|
||||
(?: # prefix, consisting of
|
||||
\s* # optional leading whitespace
|
||||
(?:>\s*)* # zero or more blockquotes
|
||||
(?:[-+*]|(?:\d+\.)) # list item indicator
|
||||
)
|
||||
\s* # optional whitespace prefix
|
||||
( # checkbox
|
||||
#{escapePattern(complete)}|
|
||||
#{escapePattern(incomplete)}
|
||||
)
|
||||
\s+ # is followed by whitespace
|
||||
(?!
|
||||
\(.*?\) # is not part of a [foo](url) link
|
||||
)
|
||||
(?= # and is followed by zero or more links
|
||||
(?:\[.*?\]\s*(?:\[.*?\]|\(.*?\))\s*)*
|
||||
(?:[^\[]|$) # and either a non-link or the end of the string
|
||||
)
|
||||
///
|
||||
|
||||
# Used to filter out code fences from the source for comparison only.
|
||||
# http://rubular.com/r/x5EwZVrloI
|
||||
# Modified slightly due to issues with JS
|
||||
codeFencesPattern = ///
|
||||
^`{3} # ```
|
||||
(?:\s*\w+)? # followed by optional language
|
||||
[\S\s] # whitespace
|
||||
.* # code
|
||||
[\S\s] # whitespace
|
||||
^`{3}$ # ```
|
||||
///mg
|
||||
|
||||
# Used to filter out potential mismatches (items not in lists).
|
||||
# http://rubular.com/r/OInl6CiePy
|
||||
itemsInParasPattern = ///
|
||||
^
|
||||
(
|
||||
#{escapePattern(complete)}|
|
||||
#{escapePattern(incomplete)}
|
||||
)
|
||||
.+
|
||||
$
|
||||
///g
|
||||
|
||||
# Given the source text, updates the appropriate task list item to match the
|
||||
# given checked value.
|
||||
#
|
||||
# Returns the updated String text.
|
||||
updateTaskListItem = (source, itemIndex, checked) ->
|
||||
clean = source.replace(/\r/g, '').replace(codeFencesPattern, '').
|
||||
replace(itemsInParasPattern, '').split("\n")
|
||||
index = 0
|
||||
result = for line in source.split("\n")
|
||||
if line in clean && line.match(itemPattern)
|
||||
index += 1
|
||||
if index == itemIndex
|
||||
line =
|
||||
if checked
|
||||
line.replace(incompletePattern, complete)
|
||||
else
|
||||
line.replace(completePattern, incomplete)
|
||||
line
|
||||
result.join("\n")
|
||||
|
||||
# Updates the $field value to reflect the state of $item.
|
||||
# Triggers the `tasklist:change` event before the value has changed, and fires
|
||||
# a `tasklist:changed` event once the value has changed.
|
||||
updateTaskList = ($item) ->
|
||||
$container = $item.closest '.js-task-list-container'
|
||||
$field = $container.find '.js-task-list-field'
|
||||
index = 1 + $container.find('.task-list-item-checkbox').index($item)
|
||||
checked = $item.prop 'checked'
|
||||
|
||||
event = $.Event 'tasklist:change'
|
||||
$field.trigger event, [index, checked]
|
||||
|
||||
unless event.isDefaultPrevented()
|
||||
$field.val updateTaskListItem($field.val(), index, checked)
|
||||
$field.trigger 'change'
|
||||
$field.trigger 'tasklist:changed', [index, checked]
|
||||
|
||||
# When the task list item checkbox is updated, submit the change
|
||||
$(document).on 'change', '.task-list-item-checkbox', ->
|
||||
updateTaskList $(this)
|
||||
|
||||
# Enables TaskList item changes.
|
||||
enableTaskList = ($container) ->
|
||||
if $container.find('.js-task-list-field').length > 0
|
||||
$container.
|
||||
find('.task-list-item').addClass('enabled').
|
||||
find('.task-list-item-checkbox').attr('disabled', null)
|
||||
$container.addClass('is-task-list-enabled').
|
||||
trigger 'tasklist:enabled'
|
||||
|
||||
# Enables a collection of TaskList containers.
|
||||
enableTaskLists = ($containers) ->
|
||||
for container in $containers
|
||||
enableTaskList $(container)
|
||||
|
||||
# Disable TaskList item changes.
|
||||
disableTaskList = ($container) ->
|
||||
$container.
|
||||
find('.task-list-item').removeClass('enabled').
|
||||
find('.task-list-item-checkbox').attr('disabled', 'disabled')
|
||||
$container.removeClass('is-task-list-enabled').
|
||||
trigger 'tasklist:disabled'
|
||||
|
||||
# Disables a collection of TaskList containers.
|
||||
disableTaskLists = ($containers) ->
|
||||
for container in $containers
|
||||
disableTaskList $(container)
|
||||
|
||||
$.fn.taskList = (method) ->
|
||||
$container = $(this).closest('.js-task-list-container')
|
||||
|
||||
methods =
|
||||
enable: enableTaskLists
|
||||
disable: disableTaskLists
|
||||
|
||||
methods[method || 'enable']($container)
|
Loading…
Reference in a new issue