Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gitlab-ce
Commits
7e0ef892
Commit
7e0ef892
authored
Apr 20, 2016
by
Alfredo Sumaran
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master' into label-dropdown-fix
parents
a5290ac2
7e6d5906
Changes
58
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
58 changed files
with
3448 additions
and
191 deletions
+3448
-191
CHANGELOG
CHANGELOG
+15
-2
CONTRIBUTING.md
CONTRIBUTING.md
+1
-0
app/assets/javascripts/application.js.coffee
app/assets/javascripts/application.js.coffee
+1
-0
app/assets/javascripts/dispatcher.js.coffee
app/assets/javascripts/dispatcher.js.coffee
+2
-1
app/assets/javascripts/due_date_select.js.coffee
app/assets/javascripts/due_date_select.js.coffee
+64
-0
app/assets/javascripts/gl_dropdown.js.coffee
app/assets/javascripts/gl_dropdown.js.coffee
+4
-4
app/assets/javascripts/issuable.js.coffee
app/assets/javascripts/issuable.js.coffee
+84
-0
app/assets/javascripts/issuable_context.js.coffee
app/assets/javascripts/issuable_context.js.coffee
+0
-1
app/assets/javascripts/issues.js.coffee
app/assets/javascripts/issues.js.coffee
+1
-50
app/assets/javascripts/labels_select.js.coffee
app/assets/javascripts/labels_select.js.coffee
+44
-19
app/assets/javascripts/lib/animate.js.coffee
app/assets/javascripts/lib/animate.js.coffee
+30
-4
app/assets/javascripts/lib/url_utility.js.coffee
app/assets/javascripts/lib/url_utility.js.coffee
+14
-2
app/assets/javascripts/merge_requests.js.coffee
app/assets/javascripts/merge_requests.js.coffee
+0
-35
app/assets/javascripts/milestone_select.js.coffee
app/assets/javascripts/milestone_select.js.coffee
+1
-1
app/assets/javascripts/raven_config.js.coffee
app/assets/javascripts/raven_config.js.coffee
+44
-0
app/assets/javascripts/users_select.js.coffee
app/assets/javascripts/users_select.js.coffee
+1
-1
app/assets/stylesheets/framework/dropdowns.scss
app/assets/stylesheets/framework/dropdowns.scss
+128
-2
app/assets/stylesheets/framework/markdown_area.scss
app/assets/stylesheets/framework/markdown_area.scss
+9
-0
app/assets/stylesheets/framework/variables.scss
app/assets/stylesheets/framework/variables.scss
+5
-0
app/assets/stylesheets/pages/detail_page.scss
app/assets/stylesheets/pages/detail_page.scss
+6
-0
app/assets/stylesheets/pages/diff.scss
app/assets/stylesheets/pages/diff.scss
+3
-2
app/assets/stylesheets/pages/help.scss
app/assets/stylesheets/pages/help.scss
+2
-0
app/assets/stylesheets/pages/issuable.scss
app/assets/stylesheets/pages/issuable.scss
+3
-2
app/assets/stylesheets/pages/note_form.scss
app/assets/stylesheets/pages/note_form.scss
+0
-12
app/assets/stylesheets/pages/notes.scss
app/assets/stylesheets/pages/notes.scss
+4
-17
app/controllers/projects/issues_controller.rb
app/controllers/projects/issues_controller.rb
+4
-3
app/controllers/projects/merge_requests_controller.rb
app/controllers/projects/merge_requests_controller.rb
+3
-2
app/finders/issuable_finder.rb
app/finders/issuable_finder.rb
+40
-1
app/helpers/application_helper.rb
app/helpers/application_helper.rb
+8
-1
app/helpers/issuables_helper.rb
app/helpers/issuables_helper.rb
+19
-0
app/helpers/issues_helper.rb
app/helpers/issues_helper.rb
+13
-1
app/helpers/sorting_helper.rb
app/helpers/sorting_helper.rb
+18
-0
app/models/issue.rb
app/models/issue.rb
+27
-0
app/models/label.rb
app/models/label.rb
+4
-0
app/views/projects/_activity.html.haml
app/views/projects/_activity.html.haml
+4
-1
app/views/projects/issues/_issue.html.haml
app/views/projects/issues/_issue.html.haml
+5
-0
app/views/projects/merge_requests/show/_mr_title.html.haml
app/views/projects/merge_requests/show/_mr_title.html.haml
+2
-2
app/views/shared/_label_row.html.haml
app/views/shared/_label_row.html.haml
+1
-1
app/views/shared/_labels_row.html.haml
app/views/shared/_labels_row.html.haml
+3
-0
app/views/shared/_sort_dropdown.html.haml
app/views/shared/_sort_dropdown.html.haml
+5
-0
app/views/shared/issuable/_filter.html.haml
app/views/shared/issuable/_filter.html.haml
+5
-3
app/views/shared/issuable/_label_dropdown.html.haml
app/views/shared/issuable/_label_dropdown.html.haml
+5
-3
app/views/shared/issuable/_nav.html.haml
app/views/shared/issuable/_nav.html.haml
+5
-5
app/views/shared/issuable/_sidebar.html.haml
app/views/shared/issuable/_sidebar.html.haml
+34
-5
db/migrate/20160310124959_add_due_date_to_issues.rb
db/migrate/20160310124959_add_due_date_to_issues.rb
+6
-0
db/schema.rb
db/schema.rb
+2
-0
features/project/issues/filter_labels.feature
features/project/issues/filter_labels.feature
+1
-0
features/steps/project/issues/filter_labels.rb
features/steps/project/issues/filter_labels.rb
+4
-0
lib/api/internal.rb
lib/api/internal.rb
+1
-1
lib/gitlab/gon_helper.rb
lib/gitlab/gon_helper.rb
+1
-0
lib/gitlab/metrics.rb
lib/gitlab/metrics.rb
+9
-0
spec/features/issues/filter_by_labels_spec.rb
spec/features/issues/filter_by_labels_spec.rb
+172
-0
spec/features/issues/filter_issues_spec.rb
spec/features/issues/filter_issues_spec.rb
+8
-1
spec/features/issues_spec.rb
spec/features/issues_spec.rb
+92
-6
spec/features/merge_requests/filter_by_milestone_spec.rb
spec/features/merge_requests/filter_by_milestone_spec.rb
+6
-0
spec/finders/issues_finder_spec.rb
spec/finders/issues_finder_spec.rb
+16
-0
spec/lib/gitlab/metrics_spec.rb
spec/lib/gitlab/metrics_spec.rb
+24
-0
vendor/assets/javascripts/raven.js
vendor/assets/javascripts/raven.js
+2435
-0
No files found.
CHANGELOG
View file @
7e0ef892
...
@@ -19,6 +19,7 @@ v 8.7.0 (unreleased)
...
@@ -19,6 +19,7 @@ v 8.7.0 (unreleased)
- Load award emoji images separately unless opening the full picker. Saves several hundred KBs of data for most pages. (Connor Shea)
- Load award emoji images separately unless opening the full picker. Saves several hundred KBs of data for most pages. (Connor Shea)
- Do not include award_emojis in issue and merge_request comment_count !3610 (Lucas Charles)
- Do not include award_emojis in issue and merge_request comment_count !3610 (Lucas Charles)
- Restrict user profiles when public visibility level is restricted.
- Restrict user profiles when public visibility level is restricted.
- Add ability set due date to issues, sort and filter issues by due date (Mehmet Beydogan)
- All images in discussions and wikis now link to their source files !3464 (Connor Shea).
- All images in discussions and wikis now link to their source files !3464 (Connor Shea).
- Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu)
- Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu)
- Add setting for customizing the list of trusted proxies !3524
- Add setting for customizing the list of trusted proxies !3524
...
@@ -86,6 +87,10 @@ v 8.7.0 (unreleased)
...
@@ -86,6 +87,10 @@ v 8.7.0 (unreleased)
- Fix repository cache invalidation issue when project is recreated with an empty repo (Stan Hu)
- Fix repository cache invalidation issue when project is recreated with an empty repo (Stan Hu)
- Fix: Allow empty recipients list for builds emails service when pushed is added (Frank Groeneveld)
- Fix: Allow empty recipients list for builds emails service when pushed is added (Frank Groeneveld)
- Improved markdown forms
- Improved markdown forms
- Show JavaScript errors in sentry
- Diff design updates (colors, button styles, etc)
- Copying and pasting a diff no longer pastes the line numbers or +/-
- Add null check to formData when updating profile content to fix Firefox bug
- Delete tags using Rugged for performance reasons (Robert Schilling)
- Delete tags using Rugged for performance reasons (Robert Schilling)
- Add Slack notifications when Wiki is edited (Sebastian Klier)
- Add Slack notifications when Wiki is edited (Sebastian Klier)
- Diffs load at the correct point when linking from from number
- Diffs load at the correct point when linking from from number
...
@@ -107,7 +112,7 @@ v 8.7.0 (unreleased)
...
@@ -107,7 +112,7 @@ v 8.7.0 (unreleased)
- Add RAW build trace output and button on build page
- Add RAW build trace output and button on build page
- Add incremental build trace update into CI API
- Add incremental build trace update into CI API
v 8.6.7
(unreleased)
v 8.6.7
- Fix persistent XSS vulnerability in `commit_person_link` helper
- Fix persistent XSS vulnerability in `commit_person_link` helper
- Fix persistent XSS vulnerability in Label and Milestone dropdowns
- Fix persistent XSS vulnerability in Label and Milestone dropdowns
- Fix vulnerability that made it possible to enumerate private projects belonging to group
- Fix vulnerability that made it possible to enumerate private projects belonging to group
...
@@ -117,7 +122,6 @@ v 8.6.6
...
@@ -117,7 +122,6 @@ v 8.6.6
- Fix error on language detection when repository has no HEAD (e.g., master branch) (Jeroen Bobbeldijk). !3654
- Fix error on language detection when repository has no HEAD (e.g., master branch) (Jeroen Bobbeldijk). !3654
- Fix revoking of authorized OAuth applications (Connor Shea). !3690
- Fix revoking of authorized OAuth applications (Connor Shea). !3690
- Fix error on language detection when repository has no HEAD (e.g., master branch). !3654 (Jeroen Bobbeldijk)
- Fix error on language detection when repository has no HEAD (e.g., master branch). !3654 (Jeroen Bobbeldijk)
- Project switcher uses new dropdown styling
- Issuable header is consistent between issues and merge requests
- Issuable header is consistent between issues and merge requests
- Improved spacing in issuable header on mobile
- Improved spacing in issuable header on mobile
...
@@ -249,6 +253,9 @@ v 8.6.0
...
@@ -249,6 +253,9 @@ v 8.6.0
- Trigger a todo for mentions on commits page
- Trigger a todo for mentions on commits page
- Let project owners and admins soft delete issues and merge requests
- Let project owners and admins soft delete issues and merge requests
v 8.5.11
- Fix persistent XSS vulnerability in `commit_person_link` helper
v 8.5.10
v 8.5.10
- Fix a 2FA authentication spoofing vulnerability.
- Fix a 2FA authentication spoofing vulnerability.
...
@@ -396,6 +403,9 @@ v 8.5.0
...
@@ -396,6 +403,9 @@ v 8.5.0
- Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul)
- Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul)
- Add Todos
- Add Todos
v 8.4.9
- Fix persistent XSS vulnerability in `commit_person_link` helper
v 8.4.8
v 8.4.8
- Fix a 2FA authentication spoofing vulnerability.
- Fix a 2FA authentication spoofing vulnerability.
...
@@ -518,6 +528,9 @@ v 8.4.0
...
@@ -518,6 +528,9 @@ v 8.4.0
- Add IP check against DNSBLs at account sign-up
- Add IP check against DNSBLs at account sign-up
- Added cache:key to .gitlab-ci.yml allowing to fine tune the caching
- Added cache:key to .gitlab-ci.yml allowing to fine tune the caching
v 8.3.8
- Fix persistent XSS vulnerability in `commit_person_link` helper
v 8.3.7
v 8.3.7
- Fix a 2FA authentication spoofing vulnerability.
- Fix a 2FA authentication spoofing vulnerability.
...
...
CONTRIBUTING.md
View file @
7e0ef892
...
@@ -323,6 +323,7 @@ request is as follows:
...
@@ -323,6 +323,7 @@ request is as follows:
[
shell command guidelines
](
doc/development/shell_commands.md
)
[
shell command guidelines
](
doc/development/shell_commands.md
)
1.
If your code creates new files on disk please read the
1.
If your code creates new files on disk please read the
[
shared files guidelines
](
doc/development/shared_files.md
)
.
[
shared files guidelines
](
doc/development/shared_files.md
)
.
1.
When writing commit messages please follow
[
these
](
http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
)
[
guidelines
]
(http://chris.beams.io/posts/git-commit/).
The
**official merge window**
is in the beginning of the month from the 1st to
The
**official merge window**
is in the beginning of the month from the 1st to
the 7th day of the month. This is the best time to submit an MR and get
the 7th day of the month. This is the best time to submit an MR and get
...
...
app/assets/javascripts/application.js.coffee
View file @
7e0ef892
...
@@ -55,6 +55,7 @@
...
@@ -55,6 +55,7 @@
#= require_tree .
#= require_tree .
#= require fuzzaldrin-plus
#= require fuzzaldrin-plus
#= require cropper
#= require cropper
#= require raven
window
.
slugify
=
(
text
)
->
window
.
slugify
=
(
text
)
->
text
.
replace
(
/[^-a-zA-Z0-9]+/g
,
'_'
).
toLowerCase
()
text
.
replace
(
/[^-a-zA-Z0-9]+/g
,
'_'
).
toLowerCase
()
...
...
app/assets/javascripts/dispatcher.js.coffee
View file @
7e0ef892
...
@@ -17,6 +17,7 @@ class Dispatcher
...
@@ -17,6 +17,7 @@ class Dispatcher
switch
page
switch
page
when
'projects:issues:index'
when
'projects:issues:index'
Issues
.
init
()
Issues
.
init
()
Issuable
.
init
()
shortcut_handler
=
new
ShortcutsNavigation
()
shortcut_handler
=
new
ShortcutsNavigation
()
when
'projects:issues:show'
when
'projects:issues:show'
new
Issue
()
new
Issue
()
...
@@ -57,7 +58,7 @@ class Dispatcher
...
@@ -57,7 +58,7 @@ class Dispatcher
new
ZenMode
()
new
ZenMode
()
when
'projects:merge_requests:index'
when
'projects:merge_requests:index'
shortcut_handler
=
new
ShortcutsNavigation
()
shortcut_handler
=
new
ShortcutsNavigation
()
MergeRequests
.
init
()
Issuable
.
init
()
when
'dashboard:activity'
when
'dashboard:activity'
new
Activities
()
new
Activities
()
when
'dashboard:projects:starred'
when
'dashboard:projects:starred'
...
...
app/assets/javascripts/due_date_select.js.coffee
0 → 100644
View file @
7e0ef892
class
@
DueDateSelect
constructor
:
->
$loading
=
$
(
'.js-issuable-update .due_date'
)
.
find
(
'.block-loading'
)
.
hide
()
$
(
'.js-due-date-select'
).
each
(
i
,
dropdown
)
->
$dropdown
=
$
(
dropdown
)
$dropdownParent
=
$dropdown
.
closest
(
'.dropdown'
)
$datePicker
=
$dropdownParent
.
find
(
'.js-due-date-calendar'
)
$block
=
$dropdown
.
closest
(
'.block'
)
$selectbox
=
$dropdown
.
closest
(
'.selectbox'
)
$value
=
$block
.
find
(
'.value'
)
$sidebarValue
=
$
(
'.js-due-date-sidebar-value'
,
$block
)
fieldName
=
$dropdown
.
data
(
'field-name'
)
abilityName
=
$dropdown
.
data
(
'ability-name'
)
issueUpdateURL
=
$dropdown
.
data
(
'issue-update'
)
$dropdown
.
glDropdown
(
hidden
:
->
$selectbox
.
hide
()
$value
.
removeAttr
(
'style'
)
)
addDueDate
=
->
# Create the post date
value
=
$
(
"input[name='
#{
fieldName
}
']"
).
val
()
date
=
new
Date
value
.
replace
(
new
RegExp
(
'-'
,
'g'
),
','
)
mediumDate
=
$
.
datepicker
.
formatDate
'M d, yy'
,
date
data
=
{}
data
[
abilityName
]
=
{}
data
[
abilityName
].
due_date
=
value
$
.
ajax
(
type
:
'PUT'
url
:
issueUpdateURL
data
:
data
beforeSend
:
->
$loading
.
fadeIn
()
$dropdown
.
trigger
(
'loading.gl.dropdown'
)
$selectbox
.
hide
()
$value
.
removeAttr
(
'style'
)
$value
.
html
(
mediumDate
)
$sidebarValue
.
html
(
mediumDate
)
).
done
(
data
)
->
$dropdown
.
trigger
(
'loaded.gl.dropdown'
)
$dropdown
.
dropdown
(
'toggle'
)
$loading
.
fadeOut
()
$datePicker
.
datepicker
(
dateFormat
:
'yy-mm-dd'
,
defaultDate
:
$
(
"input[name='
#{
fieldName
}
']"
).
val
()
altField
:
"input[name='
#{
fieldName
}
']"
onSelect
:
->
addDueDate
()
)
$
(
document
)
.
off
'click'
,
'.ui-datepicker-header a'
.
on
'click'
,
'.ui-datepicker-header a'
,
(
e
)
->
e
.
stopImmediatePropagation
()
app/assets/javascripts/gl_dropdown.js.coffee
View file @
7e0ef892
...
@@ -389,13 +389,13 @@ class GitLabDropdown
...
@@ -389,13 +389,13 @@ class GitLabDropdown
else
else
selectedObject
selectedObject
else
else
if
!
value
?
if
not
@
options
.
multiSelect
or
el
.
hasClass
(
'dropdown-clear-active'
)
field
.
remove
()
if
not
@
options
.
multiSelect
@
dropdown
.
find
(
".
#{
ACTIVE_CLASS
}
"
).
removeClass
ACTIVE_CLASS
@
dropdown
.
find
(
".
#{
ACTIVE_CLASS
}
"
).
removeClass
ACTIVE_CLASS
@
dropdown
.
parent
().
find
(
"input[name='
#{
fieldName
}
']"
).
remove
()
@
dropdown
.
parent
().
find
(
"input[name='
#{
fieldName
}
']"
).
remove
()
if
!
value
?
field
.
remove
()
# Toggle active class for the tick mark
# Toggle active class for the tick mark
el
.
addClass
ACTIVE_CLASS
el
.
addClass
ACTIVE_CLASS
...
...
app/assets/javascripts/issuable.js.coffee
0 → 100644
View file @
7e0ef892
@
Issuable
=
init
:
->
Issuable
.
initTemplates
()
Issuable
.
initSearch
()
initTemplates
:
->
Issuable
.
labelRow
=
_
.
template
(
'<% _.each(labels, function(label){ %>
<span class="label-row">
<a href="#"><span class="label color-label has-tooltip" style="background-color: <%= label.color %>; color: <%= label.text_color %>" title="<%= _.escape(label.description) %>" data-container="body"><%= _.escape(label.title) %></span></a>
</span>
<% }); %>'
)
initSearch
:
->
@
timer
=
null
$
(
'#issue_search'
)
.
off
'keyup'
.
on
'keyup'
,
->
clearTimeout
(
@
timer
)
@
timer
=
setTimeout
(
->
Issuable
.
filterResults
$
(
'#issue_search_form'
)
,
500
)
toggleLabelFilters
:
->
$filteredLabels
=
$
(
'.filtered-labels'
)
if
$filteredLabels
.
find
(
'.label-row'
).
length
>
0
$filteredLabels
.
removeClass
(
'hidden'
)
else
$filteredLabels
.
addClass
(
'hidden'
)
filterResults
:
(
form
)
=>
formData
=
form
.
serialize
()
$
(
'.issues-holder, .merge-requests-holder'
).
css
(
'opacity'
,
'0.5'
)
formAction
=
form
.
attr
(
'action'
)
issuesUrl
=
formAction
issuesUrl
+=
(
"
#{
if
formAction
.
indexOf
(
'?'
)
<
0
then
'?'
else
'&'
}
"
)
issuesUrl
+=
formData
$
.
ajax
type
:
'GET'
url
:
formAction
data
:
formData
complete
:
->
$
(
'.issues-holder, .merge-requests-holder'
).
css
(
'opacity'
,
'1.0'
)
success
:
(
data
)
->
$
(
'.issues-holder, .merge-requests-holder'
).
html
(
data
.
html
)
# Change url so if user reload a page - search results are saved
history
.
replaceState
{
page
:
issuesUrl
},
document
.
title
,
issuesUrl
Issuable
.
reload
()
Issuable
.
updateStateFilters
()
$filteredLabels
=
$
(
'.filtered-labels'
)
if
typeof
Issuable
.
labelRow
is
'function'
$filteredLabels
.
html
(
Issuable
.
labelRow
(
data
))
Issuable
.
toggleLabelFilters
()
dataType
:
"json"
reload
:
->
if
Issues
.
created
Issues
.
initChecks
()
$
(
'#filter_issue_search'
).
val
(
$
(
'#issue_search'
).
val
())
updateStateFilters
:
->
stateFilters
=
$
(
'.issues-state-filters'
)
newParams
=
{}
paramKeys
=
[
'author_id'
,
'milestone_title'
,
'assignee_id'
,
'issue_search'
]
for
paramKey
in
paramKeys
newParams
[
paramKey
]
=
gl
.
utils
.
getParameterValues
(
paramKey
)[
0
]
or
''
if
stateFilters
.
length
stateFilters
.
find
(
'a'
).
each
->
initialUrl
=
gl
.
utils
.
removeParamQueryString
(
$
(
this
).
attr
(
'href'
),
'label_name[]'
)
labelNameValues
=
gl
.
utils
.
getParameterValues
(
'label_name[]'
)
if
labelNameValues
labelNameQueryString
=
(
"label_name[]=
#{
value
}
"
for
value
in
labelNameValues
).
join
(
'&'
)
newUrl
=
"
#{
gl
.
utils
.
mergeUrlParams
(
newParams
,
initialUrl
)
}
&
#{
labelNameQueryString
}
"
else
newUrl
=
gl
.
utils
.
mergeUrlParams
(
newParams
,
initialUrl
)
$
(
this
).
attr
'href'
,
newUrl
app/assets/javascripts/issuable_context.js.coffee
View file @
7e0ef892
...
@@ -33,7 +33,6 @@ class @IssuableContext
...
@@ -33,7 +33,6 @@ class @IssuableContext
$block
.
find
(
'.dropdown-menu-toggle'
).
trigger
'click'
$block
.
find
(
'.dropdown-menu-toggle'
).
trigger
'click'
,
0
,
0
$
(
".right-sidebar"
).
niceScroll
()
$
(
".right-sidebar"
).
niceScroll
()
initParticipants
:
->
initParticipants
:
->
...
...
app/assets/javascripts/issues.js.coffee
View file @
7e0ef892
@
Issues
=
@
Issues
=
init
:
->
init
:
->
Issues
.
initSearch
()
Issues
.
created
=
true
Issues
.
initChecks
()
Issues
.
initChecks
()
$
(
"body"
).
on
"ajax:success"
,
".close_issue, .reopen_issue"
,
->
$
(
"body"
).
on
"ajax:success"
,
".close_issue, .reopen_issue"
,
->
...
@@ -15,10 +15,6 @@
...
@@ -15,10 +15,6 @@
else
else
$
(
this
).
html
totalIssues
-
1
$
(
this
).
html
totalIssues
-
1
reload
:
->
Issues
.
initChecks
()
$
(
'#filter_issue_search'
).
val
(
$
(
'#issue_search'
).
val
())
initChecks
:
->
initChecks
:
->
$
(
".check_all_issues"
).
click
->
$
(
".check_all_issues"
).
click
->
$
(
".selected_issue"
).
prop
(
"checked"
,
@
checked
)
$
(
".selected_issue"
).
prop
(
"checked"
,
@
checked
)
...
@@ -26,51 +22,6 @@
...
@@ -26,51 +22,6 @@
$
(
".selected_issue"
).
bind
"change"
,
Issues
.
checkChanged
$
(
".selected_issue"
).
bind
"change"
,
Issues
.
checkChanged
# Update state filters if present in page
updateStateFilters
:
->
stateFilters
=
$
(
'.issues-state-filters'
)
newParams
=
{}
paramKeys
=
[
'author_id'
,
'label_name'
,
'milestone_title'
,
'assignee_id'
,
'issue_search'
]
for
paramKey
in
paramKeys
newParams
[
paramKey
]
=
gl
.
utils
.
getUrlParameter
(
paramKey
)
or
''
if
stateFilters
.
length
stateFilters
.
find
(
'a'
).
each
->
initialUrl
=
$
(
this
).
attr
'href'
$
(
this
).
attr
'href'
,
gl
.
utils
.
mergeUrlParams
(
newParams
,
initialUrl
)
# Make sure we trigger ajax request only after user stop typing
initSearch
:
->
@
timer
=
null
$
(
"#issue_search"
).
keyup
->
clearTimeout
(
@
timer
)
@
timer
=
setTimeout
(
->
Issues
.
filterResults
$
(
"#issue_search_form"
)
,
500
)
filterResults
:
(
form
)
=>
$
(
'.issues-holder, .merge-requests-holder'
).
css
(
"opacity"
,
'0.5'
)
formAction
=
form
.
attr
(
'action'
)
formData
=
form
.
serialize
()
issuesUrl
=
formAction
issuesUrl
+=
(
"
#{
if
formAction
.
indexOf
(
"?"
)
<
0
then
'?'
else
'&'
}
"
)
issuesUrl
+=
formData
$
.
ajax
type
:
"GET"
url
:
formAction
data
:
formData
complete
:
->
$
(
'.issues-holder, .merge-requests-holder'
).
css
(
"opacity"
,
'1.0'
)
success
:
(
data
)
->
$
(
'.issues-holder, .merge-requests-holder'
).
html
(
data
.
html
)
# Change url so if user reload a page - search results are saved
history
.
replaceState
{
page
:
issuesUrl
},
document
.
title
,
issuesUrl
Issues
.
reload
()
Issues
.
updateStateFilters
()
dataType
:
"json"
checkChanged
:
->
checkChanged
:
->
checked_issues
=
$
(
".selected_issue:checked"
)
checked_issues
=
$
(
".selected_issue:checked"
)
if
checked_issues
.
length
>
0
if
checked_issues
.
length
>
0
...
...
app/assets/javascripts/labels_select.js.coffee
View file @
7e0ef892
...
@@ -6,7 +6,7 @@ class @LabelsSelect
...
@@ -6,7 +6,7 @@ class @LabelsSelect
labelUrl
=
$dropdown
.
data
(
'labels'
)
labelUrl
=
$dropdown
.
data
(
'labels'
)
issueUpdateURL
=
$dropdown
.
data
(
'issueUpdate'
)
issueUpdateURL
=
$dropdown
.
data
(
'issueUpdate'
)
selectedLabel
=
$dropdown
.
data
(
'selected'
)
selectedLabel
=
$dropdown
.
data
(
'selected'
)
if
selectedLabel
?
if
selectedLabel
?
and
not
$dropdown
.
hasClass
'js-multiselect'
selectedLabel
=
selectedLabel
.
split
(
','
)
selectedLabel
=
selectedLabel
.
split
(
','
)
newLabelField
=
$
(
'#new_label_name'
)
newLabelField
=
$
(
'#new_label_name'
)
newColorField
=
$
(
'#new_label_color'
)
newColorField
=
$
(
'#new_label_color'
)
...
@@ -16,6 +16,7 @@ class @LabelsSelect
...
@@ -16,6 +16,7 @@ class @LabelsSelect
abilityName
=
$dropdown
.
data
(
'ability-name'
)
abilityName
=
$dropdown
.
data
(
'ability-name'
)
$selectbox
=
$dropdown
.
closest
(
'.selectbox'
)
$selectbox
=
$dropdown
.
closest
(
'.selectbox'
)
$block
=
$selectbox
.
closest
(
'.block'
)
$block
=
$selectbox
.
closest
(
'.block'
)
$form
=
$dropdown
.
closest
(
'form'
)
$sidebarCollapsedValue
=
$block
.
find
(
'.sidebar-collapsed-icon span'
)
$sidebarCollapsedValue
=
$block
.
find
(
'.sidebar-collapsed-icon span'
)
$value
=
$block
.
find
(
'.value'
)
$value
=
$block
.
find
(
'.value'
)
$newLabelError
=
$
(
'.js-label-error'
)
$newLabelError
=
$
(
'.js-label-error'
)
...
@@ -151,7 +152,7 @@ class @LabelsSelect
...
@@ -151,7 +152,7 @@ class @LabelsSelect
.
find
(
'a'
)
.
find
(
'a'
)
.
each
((
i
)
->
.
each
((
i
)
->
setTimeout
(
=>
setTimeout
(
=>
gl
A
nimate
(
$
(
@
),
'pulse'
)
gl
.
animate
.
a
nimate
(
$
(
@
),
'pulse'
)
,
200
*
i
,
200
*
i
)
)
)
)
...
@@ -180,16 +181,21 @@ class @LabelsSelect
...
@@ -180,16 +181,21 @@ class @LabelsSelect
callback
data
callback
data
renderRow
:
(
label
)
->
renderRow
:
(
label
)
->
selectedClass
=
''
removesAll
=
label
.
id
is
0
or
not
label
.
id
?
if
$selectbox
.
find
(
"input[type='hidden']
\
[name='
#{
$dropdown
.
data
(
'field-name'
)
}
']
\
selectedClass
=
[]
[value='
#{
label
.
id
}
']"
).
length
if
$form
.
find
(
"input[type='hidden']
\
selectedClass
=
'is-active'
[name='
#{
$dropdown
.
data
(
'fieldName'
)
}
']
\
[value='
#{
this
.
id
(
label
)
}
']"
).
length
selectedClass
.
push
'is-active'
if
$dropdown
.
hasClass
(
'js-multiselect'
)
and
removesAll
selectedClass
.
push
'dropdown-clear-active'
color
=
if
label
.
color
?
then
"<span class='dropdown-label-box' style='background-color:
#{
label
.
color
}
'></span>"
else
""
color
=
if
label
.
color
?
then
"<span class='dropdown-label-box' style='background-color:
#{
label
.
color
}
'></span>"
else
""
"<li>
"<li>
<a href='#' class='
#{
selectedClass
}
'>
<a href='#' class='
#{
selectedClass
.
join
(
' '
)
}
'>
#{
color
}
#{
color
}
#{
_
.
escape
(
label
.
title
)
}
#{
_
.
escape
(
label
.
title
)
}
</a>
</a>
...
@@ -199,37 +205,56 @@ class @LabelsSelect
...
@@ -199,37 +205,56 @@ class @LabelsSelect
fields
:
[
'title'
]
fields
:
[
'title'
]
selectable
:
true
selectable
:
true
toggleLabel
:
(
selected
)
->
toggleLabel
:
(
selected
,
el
)
->
selected_labels
=
$
(
'.js-label-select'
).
siblings
(
'.dropdown-menu-labels'
).
find
(
'.is-active'
)
if
selected
and
selected
.
title
?
if
selected
and
selected
.
title
?
selected
.
title
if
selected_labels
.
length
>
1
"
#{
selected
.
title
}
+
#{
selected_labels
.
length
-
1
}
more"
else
selected
.
title
else
if
not
selected
and
selected_labels
.
length
isnt
0
if
selected_labels
.
length
>
1
"
#{
$
(
selected_labels
[
0
]).
text
()
}
+
#{
selected_labels
.
length
-
1
}
more"
else
if
selected_labels
.
length
is
1
$
(
selected_labels
).
text
()
else
else
defaultLabel
defaultLabel
fieldName
:
$dropdown
.
data
(
'field-name'
)
fieldName
:
$dropdown
.
data
(
'field-name'
)
id
:
(
label
)
->
id
:
(
label
)
->
if
label
.
isAny
?
if
$dropdown
.
hasClass
(
"js-filter-submit"
)
and
not
label
.
isAny
?
''
else
if
$dropdown
.
hasClass
"js-filter-submit"
label
.
title
label
.
title
else
else
label
.
id
label
.
id
hidden
:
->
hidden
:
->
page
=
$
(
'body'
).
data
'page'
isIssueIndex
=
page
is
'projects:issues:index'
isMRIndex
=
page
is
'projects:merge_requests:index'
$selectbox
.
hide
()
$selectbox
.
hide
()
# display:block overrides the hide-collapse rule
# display:block overrides the hide-collapse rule
$value
.
removeAttr
(
'style'
)
$value
.
removeAttr
(
'style'
)
if
$dropdown
.
hasClass
'js-multiselect'
if
$dropdown
.
hasClass
'js-multiselect'
saveLabelData
()
if
$dropdown
.
hasClass
(
'js-filter-submit'
)
and
(
isIssueIndex
or
isMRIndex
)
selectedLabels
=
$dropdown
.
closest
(
'form'
)
.
find
(
"input:hidden[name='
#{
$dropdown
.
data
(
'fieldName'
)
}
']"
)
Issuable
.
filterResults
$dropdown
.
closest
(
'form'
)
else
if
$dropdown
.
hasClass
(
'js-filter-submit'
)
$dropdown
.
closest
(
'form'
).
submit
()
else
saveLabelData
()
multiSelect
:
$dropdown
.
hasClass
'js-multiselect'
multiSelect
:
$dropdown
.
hasClass
'js-multiselect'
clicked
:
(
label
)
->
clicked
:
(
label
)
->
page
=
$
(
'body'
).
data
'page'
page
=
$
(
'body'
).
data
'page'
isIssueIndex
=
page
is
'projects:issues:index'
isIssueIndex
=
page
is
'projects:issues:index'
isMRIndex
=
page
is
page
is
'projects:merge_requests:index'
isMRIndex
=
page
is
'projects:merge_requests:index'
if
$dropdown
.
hasClass
(
'js-filter-submit'
)
and
(
isIssueIndex
or
isMRIndex
)
if
$dropdown
.
hasClass
(
'js-filter-submit'
)
and
(
isIssueIndex
or
isMRIndex
)
selectedLabel
=
label
.
title
if
not
$dropdown
.
hasClass
'js-multiselect'
selectedLabel
=
label
.
title
Issues
.
filterResults
$dropdown
.
closest
(
'form'
)
Issuable
.
filterResults
$dropdown
.
closest
(
'form'
)
else
if
$dropdown
.
hasClass
'js-filter-submit'
else
if
$dropdown
.
hasClass
'js-filter-submit'
$dropdown
.
closest
(
'form'
).
submit
()
$dropdown
.
closest
(
'form'
).
submit
()
else
else
...
...
app/assets/javascripts/lib/animate.js.coffee
View file @
7e0ef892
((
w
)
->
((
w
)
->
if
not
w
.
gl
?
then
w
.
gl
=
{}
if
not
gl
.
animate
?
then
gl
.
animate
=
{}
w
.
glAnimate
=
(
$el
,
animation
,
done
)
->
gl
.
animate
.
animate
=
(
$el
,
animation
,
options
,
done
)
->
if
options
?
.
cssStart
?
$el
.
css
(
options
.
cssStart
)
$el
$el
.
removeClass
()
.
removeClass
(
animation
+
' animated'
)
.
addClass
(
animation
+
' animated'
)
.
addClass
(
animation
+
' animated'
)
.
one
'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend'
,
->
.
one
'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend'
,
->
$
(
this
).
removeClass
()
$
(
this
).
removeClass
(
animation
+
' animated'
)
if
done
?
done
()
if
options
?
.
cssEnd
?
$el
.
css
(
options
.
cssEnd
)
return
return
return
return
return
gl
.
animate
.
animateEach
=
(
$els
,
animation
,
time
,
options
,
done
)
->
dfd
=
$
.
Deferred
()
if
not
$els
.
length
dfd
.
resolve
()
$els
.
each
((
i
)
->
setTimeout
(
=>
$this
=
$
(
@
)
gl
.
animate
.
animate
(
$this
,
animation
,
options
,
=>
if
i
is
$els
.
length
-
1
dfd
.
resolve
()
if
done
?
done
()
)
,
time
*
i
)
return
)
return
dfd
.
promise
()
return
)
window
)
window
\ No newline at end of file
app/assets/javascripts/lib/url_utility.js.coffee
View file @
7e0ef892
...
@@ -3,16 +3,20 @@
...
@@ -3,16 +3,20 @@
w
.
gl
?=
{}
w
.
gl
?=
{}
w
.
gl
.
utils
?=
{}
w
.
gl
.
utils
?=
{}
w
.
gl
.
utils
.
getUrlParameter
=
(
sParam
)
->
# Returns an array containing the value(s) of the
# of the key passed as an argument
w
.
gl
.
utils
.
getParameterValues
=
(
sParam
)
->
sPageURL
=
decodeURIComponent
(
window
.
location
.
search
.
substring
(
1
))
sPageURL
=
decodeURIComponent
(
window
.
location
.
search
.
substring
(
1
))
sURLVariables
=
sPageURL
.
split
(
'&'
)
sURLVariables
=
sPageURL
.
split
(
'&'
)
sParameterName
=
undefined
sParameterName
=
undefined
values
=
[]
i
=
0
i
=
0
while
i
<
sURLVariables
.
length
while
i
<
sURLVariables
.
length
sParameterName
=
sURLVariables
[
i
].
split
(
'='
)
sParameterName
=
sURLVariables
[
i
].
split
(
'='
)
if
sParameterName
[
0
]
is
sParam
if
sParameterName
[
0
]
is
sParam
return
if
sParameterName
[
1
]
is
undefined
then
true
else
sParameterName
[
1
]
values
.
push
(
sParameterName
[
1
])
i
++
i
++
values
# #
# #
# @param {Object} params - url keys and value to merge
# @param {Object} params - url keys and value to merge
...
@@ -28,4 +32,12 @@
...
@@ -28,4 +32,12 @@
newUrl
=
"
#{
newUrl
}#{
(
if
newUrl
.
indexOf
(
'?'
)
>
0
then
'&'
else
'?'
)
}#{
paramName
}
=
#{
paramValue
}
"
newUrl
=
"
#{
newUrl
}#{
(
if
newUrl
.
indexOf
(
'?'
)
>
0
then
'&'
else
'?'
)
}#{
paramName
}
=
#{
paramValue
}
"
newUrl
newUrl
# removes parameter query string from url. returns the modified url
w
.
gl
.
utils
.
removeParamQueryString
=
(
url
,
param
)
->
url
=
decodeURIComponent
(
url
)
urlVariables
=
url
.
split
(
'&'
)
(
variables
for
variables
in
urlVariables
when
variables
.
indexOf
(
param
)
is
-
1
).
join
(
'&'
)
)
window
)
window
app/assets/javascripts/merge_requests.js.coffee
deleted
100644 → 0
View file @
a5290ac2
#
# * Filter merge requests
#
@
MergeRequests
=
init
:
->
MergeRequests
.
initSearch
()
# Make sure we trigger ajax request only after user stop typing
initSearch
:
->
@
timer
=
null
$
(
"#issue_search"
).
keyup
->
clearTimeout
(
@
timer
)
@
timer
=
setTimeout
(
MergeRequests
.
filterResults
,
500
)
filterResults
:
=>
form
=
$
(
"#issue_search_form"
)
search
=
$
(
"#issue_search"
).
val
()
$
(
'.merge-requests-holder'
).
css
(
"opacity"
,
'0.5'
)
issues_url
=
form
.
attr
(
'action'
)
+
'?'
+
form
.
serialize
()
$
.
ajax
type
:
"GET"
url
:
form
.
attr
(
'action'
)
data
:
form
.
serialize
()
complete
:
->
$
(
'.merge-requests-holder'
).
css
(
"opacity"
,
'1.0'
)
success
:
(
data
)
->
$
(
'.merge-requests-holder'
).
html
(
data
.
html
)
# Change url so if user reload a page - search results are saved
history
.
replaceState
{
page
:
issues_url
},
document
.
title
,
issues_url
MergeRequests
.
reload
()
dataType
:
"json"
reload
:
->
$
(
'#filter_issue_search'
).
val
(
$
(
'#issue_search'
).
val
())
app/assets/javascripts/milestone_select.js.coffee
View file @
7e0ef892
...
@@ -97,7 +97,7 @@ class @MilestoneSelect
...
@@ -97,7 +97,7 @@ class @MilestoneSelect
selectedMilestone
=
selected
.
name
selectedMilestone
=
selected
.
name
else
else
selectedMilestone
=
''
selectedMilestone
=
''
Issu
es
.
filterResults
$dropdown
.
closest
(
'form'
)
Issu
able
.
filterResults
$dropdown
.
closest
(
'form'
)
else
if
$dropdown
.
hasClass
(
'js-filter-submit'
)
else
if
$dropdown
.
hasClass
(
'js-filter-submit'
)
$dropdown
.
closest
(
'form'
).
submit
()
$dropdown
.
closest
(
'form'
).
submit
()
else
else
...
...
app/assets/javascripts/raven_config.js.coffee
0 → 100644
View file @
7e0ef892
@
raven
=
init
:
->
if
gon
.
sentry_dsn
?
Raven
.
config
(
gon
.
sentry_dsn
,
{
includePaths
:
[
/gon.relative_url_root/
]
ignoreErrors
:
[
# Random plugins/extensions
'top.GLOBALS'
,
# See: http://blog.errorception.com/2012/03/tale-of-unfindable-js-error. html
'originalCreateNotification'
,
'canvas.contentDocument'
,
'MyApp_RemoveAllHighlights'
,
'http://tt.epicplay.com'
,
'Can
\'
t find variable: ZiteReader'
,
'jigsaw is not defined'
,
'ComboSearch is not defined'
,
'http://loading.retry.widdit.com/'
,
'atomicFindClose'
,
# ISP "optimizing" proxy - `Cache-Control: no-transform` seems to
# reduce this. (thanks @acdha)
# See http://stackoverflow.com/questions/4113268
'bmi_SafeAddOnload'
,
'EBCallBackMessageReceived'
,
# See http://toolbar.conduit.com/Developer/HtmlAndGadget/Methods/JSInjection.aspx
'conduitPage'
],
ignoreUrls
:
[
# Chrome extensions
/extensions\//i
,
/^chrome:\/\//i
,
# Other plugins
/127\.0\.0\.1:4001\/isrunning/i
,
# Cacaoweb
/webappstoolbarba\.texthelp\.com\//i
,
/metrics\.itunes\.apple\.com\.edgesuite\.net\//i
]
}).
install
()
if
gon
.
current_user_id
Raven
.
setUserContext
({
id
:
gon
.
current_user_id
})
$
->
raven
.
init
()
app/assets/javascripts/users_select.js.coffee
View file @
7e0ef892
...
@@ -158,7 +158,7 @@ class @UsersSelect
...
@@ -158,7 +158,7 @@ class @UsersSelect
if
$dropdown
.
hasClass
(
'js-filter-submit'
)
and
(
isIssueIndex
or
isMRIndex
)
if
$dropdown
.
hasClass
(
'js-filter-submit'
)
and
(
isIssueIndex
or
isMRIndex
)
selectedId
=
user
.
id
selectedId
=
user
.
id
Issu
es
.
filterResults
$dropdown
.
closest
(
'form'
)
Issu
able
.
filterResults
$dropdown
.
closest
(
'form'
)
else
if
$dropdown
.
hasClass
'js-filter-submit'
else
if
$dropdown
.
hasClass
'js-filter-submit'
$dropdown
.
closest
(
'form'
).
submit
()
$dropdown
.
closest
(
'form'
).
submit
()
else
else
...
...
app/assets/stylesheets/framework/dropdowns.scss
View file @
7e0ef892
...
@@ -248,7 +248,7 @@
...
@@ -248,7 +248,7 @@
.dropdown-title
{
.dropdown-title
{
position
:
relative
;
position
:
relative
;
padding
:
0
25px
1
5
px
;
padding
:
0
25px
1
0
px
;
margin
:
0
10px
10px
;
margin
:
0
10px
10px
;
font-weight
:
600
;
font-weight
:
600
;
line-height
:
1
;
line-height
:
1
;
...
@@ -278,7 +278,7 @@
...
@@ -278,7 +278,7 @@
right
:
5px
;
right
:
5px
;
width
:
20px
;
width
:
20px
;
height
:
20px
;
height
:
20px
;
top
:
-
1
px
;
top
:
-
3
px
;
}
}
.dropdown-menu-back
{
.dropdown-menu-back
{
...
@@ -358,6 +358,13 @@
...
@@ -358,6 +358,13 @@
border-top
:
1px
solid
$dropdown-divider-color
;
border-top
:
1px
solid
$dropdown-divider-color
;
}
}
.dropdown-due-date-footer
{
padding-top
:
0
;
margin-left
:
10px
;
margin-right
:
10px
;
border-top
:
0
;
}
.dropdown-footer-list
{
.dropdown-footer-list
{
font-size
:
14px
;
font-size
:
14px
;
...
@@ -395,3 +402,122 @@
...
@@ -395,3 +402,122 @@
height
:
15px
;
height
:
15px
;
border-radius
:
$border-radius-base
;
border-radius
:
$border-radius-base
;
}
}
.dropdown-menu-due-date
{
.dropdown-content
{
max-height
:
230px
;
}
.ui-widget
{
table
{
margin
:
0
;
}
&
.ui-datepicker-inline
{
padding
:
0
10px
;
border
:
0
;
width
:
100%
;
}
.ui-datepicker-header
{
padding
:
0
8px
10px
;
border
:
0
;
.ui-icon
{
background
:
none
;
font-size
:
20px
;
text-indent
:
0
;
&
:before
{
display
:
block
;
position
:
relative
;
top
:
-2px
;
color
:
$dropdown-title-btn-color
;
font
:
normal
normal
normal
14px
/
1
FontAwesome
;
font-size
:
inherit
;
text-rendering
:
auto
;
-webkit-font-smoothing
:
antialiased
;
-moz-osx-font-smoothing
:
grayscale
;
}
}
}
.ui-state-active
,
.ui-state-hover
{
color
:
$md-link-color
;
background-color
:
$calendar-hover-bg
;
}
.ui-datepicker-prev
,
.ui-datepicker-next
{
top
:
0
;
height
:
15px
;
cursor
:
pointer
;
&
:hover
{
background-color
:
transparent
;
border
:
0
;
.ui-icon
:before
{
color
:
$md-link-color
;
}
}
}
.ui-datepicker-prev
{
left
:
0
;
.ui-icon
:before
{
content
:
'\f104'
;
text-align
:
left
;
}
}
.ui-datepicker-next
{
right
:
0
;
.ui-icon
:before
{
content
:
'\f105'
;
text-align
:
right
;
}
}
td
{
padding
:
0
;
border
:
1px
solid
$calendar-border-color
;
&
:first-child
{
border-left
:
0
;
}
&
:last-child
{
border-right
:
0
;
}
a
{
line-height
:
17px
;
border
:
0
;
border-radius
:
0
;
}
}
.ui-datepicker-title
{
color
:
$gl-gray
;
font-size
:
15px
;
line-height
:
1
;
font-weight
:
normal
;
}
}
th
{
padding
:
2px
0
;
color
:
$calendar-header-color
;
font-weight
:
normal
;
text-transform
:
lowercase
;
border-top
:
1px
solid
$calendar-border-color
;
}
.ui-datepicker-unselectable
{
background-color
:
$calendar-unselectable-bg
;
}
}
app/assets/stylesheets/framework/markdown_area.scss
View file @
7e0ef892
...
@@ -90,3 +90,12 @@
...
@@ -90,3 +90,12 @@
box-shadow
:
none
;
box-shadow
:
none
;
width
:
100%
;
width
:
100%
;
}
}
.md
{
&
.md-preview-holder
{
code
{
white-space
:
pre-wrap
;
word-break
:
break-all
;
}
}
}
app/assets/stylesheets/framework/variables.scss
View file @
7e0ef892
...
@@ -241,3 +241,8 @@ $note-form-border-color: #e5e5e5;
...
@@ -241,3 +241,8 @@ $note-form-border-color: #e5e5e5;
$note-toolbar-color
:
#959494
;
$note-toolbar-color
:
#959494
;
$zen-control-hover-color
:
#111
;
$zen-control-hover-color
:
#111
;
$calendar-header-color
:
#b8b8b8
;
$calendar-hover-bg
:
#ecf3fe
;
$calendar-border-color
:
rgba
(
#000
,
.1
);
$calendar-unselectable-bg
:
#faf9f9
;
app/assets/stylesheets/pages/detail_page.scss
View file @
7e0ef892
...
@@ -36,4 +36,10 @@
...
@@ -36,4 +36,10 @@
}
}
}
}
}
}
.wiki
{
code
{
white-space
:
pre-wrap
;
}
}
}
}
app/assets/stylesheets/pages/diff.scss
View file @
7e0ef892
...
@@ -34,6 +34,7 @@
...
@@ -34,6 +34,7 @@
background
:
#fff
;
background
:
#fff
;
color
:
#333
;
color
:
#333
;
border-radius
:
0
0
3px
3px
;
border-radius
:
0
0
3px
3px
;
-webkit-overflow-scrolling
:
auto
;
.unfold
{
.unfold
{
cursor
:
pointer
;
cursor
:
pointer
;
...
@@ -86,7 +87,7 @@
...
@@ -86,7 +87,7 @@
}
}
span
{
span
{
white-space
:
pre
;
white-space
:
pre
-wrap
;
}
}
}
}
}
}
...
@@ -335,7 +336,7 @@
...
@@ -335,7 +336,7 @@
}
}
.diff-file
.line_content
{
.diff-file
.line_content
{
white-space
:
pre
;
white-space
:
pre
-wrap
;
}
}
.diff-wrap-lines
.line_content
{
.diff-wrap-lines
.line_content
{
...
...
app/assets/stylesheets/pages/help.scss
View file @
7e0ef892
...
@@ -59,8 +59,10 @@
...
@@ -59,8 +59,10 @@
position
:
relative
;
position
:
relative
;
overflow-y
:
auto
;
overflow-y
:
auto
;
padding
:
15px
;
padding
:
15px
;
.form-actions
{
.form-actions
{
margin
:
-
$gl-padding
+
1
;
margin
:
-
$gl-padding
+
1
;
margin-top
:
15px
;
}
}
}
}
...
...
app/assets/stylesheets/pages/issuable.scss
View file @
7e0ef892
...
@@ -128,6 +128,7 @@
...
@@ -128,6 +128,7 @@
top
:
58px
;
top
:
58px
;
bottom
:
0
;
bottom
:
0
;
right
:
0
;
right
:
0
;
z-index
:
10
;
transition
:
width
.3s
;
transition
:
width
.3s
;
background
:
$gray-light
;
background
:
$gray-light
;
padding
:
10px
20px
;
padding
:
10px
20px
;
...
@@ -241,7 +242,7 @@
...
@@ -241,7 +242,7 @@
}
}
}
}
.
btn
{
.
issuable-pager
{
background
:
$gray-normal
;
background
:
$gray-normal
;
border
:
1px
solid
$border-gray-normal
;
border
:
1px
solid
$border-gray-normal
;
&
:hover
{
&
:hover
{
...
@@ -254,7 +255,7 @@
...
@@ -254,7 +255,7 @@
}
}
}
}
a
:not
(
.
btn
)
{
a
:not
(
.
issuable-pager
)
{
&
:hover
{
&
:hover
{
color
:
$md-link-color
;
color
:
$md-link-color
;
text-decoration
:
none
;
text-decoration
:
none
;
...
...
app/assets/stylesheets/pages/note_form.scss
View file @
7e0ef892
...
@@ -84,18 +84,6 @@
...
@@ -84,18 +84,6 @@
border-color
:
$gl-success
;
border-color
:
$gl-success
;
}
}
}
}
p
{
code
{
white-space
:
normal
;
}
pre
{
code
{
white-space
:
pre
;
}
}
}
}
}
}
}
...
...
app/assets/stylesheets/pages/notes.scss
View file @
7e0ef892
...
@@ -81,16 +81,8 @@ ul.notes {
...
@@ -81,16 +81,8 @@ ul.notes {
@include
md-typography
;
@include
md-typography
;
// On diffs code should wrap nicely and not overflow
// On diffs code should wrap nicely and not overflow
p
{
code
{
code
{
white-space
:
pre-wrap
;
white-space
:
normal
;
}
pre
{
code
{
white-space
:
pre
;
}
}
}
}
// Reset ul style types since we're nested inside a ul already
// Reset ul style types since we're nested inside a ul already
...
@@ -137,7 +129,7 @@ ul.notes {
...
@@ -137,7 +129,7 @@ ul.notes {
margin-right
:
10px
;
margin-right
:
10px
;
}
}
.line_content
{
.line_content
{
white-space
:
pre
;
white-space
:
pre
-wrap
;
}
}
}
}
...
@@ -171,11 +163,6 @@ ul.notes {
...
@@ -171,11 +163,6 @@ ul.notes {
&
.parallel
{
&
.parallel
{
border-width
:
1px
;
border-width
:
1px
;
.code
,
code
{
white-space
:
pre-wrap
;
}
}
}
.notes
{
.notes
{
...
@@ -308,7 +295,7 @@ ul.notes {
...
@@ -308,7 +295,7 @@ ul.notes {
padding
:
4px
;
padding
:
4px
;
font-size
:
16px
;
font-size
:
16px
;
color
:
$gl-link-color
;
color
:
$gl-link-color
;
margin-left
:
-
60
px
;
margin-left
:
-
56
px
;
position
:
absolute
;
position
:
absolute
;
z-index
:
10
;
z-index
:
10
;
width
:
32px
;
width
:
32px
;
...
...
app/controllers/projects/issues_controller.rb
View file @
7e0ef892
...
@@ -33,14 +33,15 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -33,14 +33,15 @@ class Projects::IssuesController < Projects::ApplicationController
end
end
@issues
=
@issues
.
page
(
params
[
:page
])
@issues
=
@issues
.
page
(
params
[
:page
])
@label
=
@project
.
labels
.
find_by
(
title:
params
[
:label_name
])
@label
s
=
@project
.
labels
.
where
(
title:
params
[
:label_name
])
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
html
format
.
html
format
.
atom
{
render
layout:
false
}
format
.
atom
{
render
layout:
false
}
format
.
json
do
format
.
json
do
render
json:
{
render
json:
{
html:
view_to_html_string
(
"projects/issues/_issues"
)
html:
view_to_html_string
(
"projects/issues/_issues"
),
labels:
@labels
.
as_json
(
methods: :text_color
)
}
}
end
end
end
end
...
@@ -191,7 +192,7 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -191,7 +192,7 @@ class Projects::IssuesController < Projects::ApplicationController
def
issue_params
def
issue_params
params
.
require
(
:issue
).
permit
(
params
.
require
(
:issue
).
permit
(
:title
,
:assignee_id
,
:position
,
:description
,
:confidential
,
:title
,
:assignee_id
,
:position
,
:description
,
:confidential
,
:milestone_id
,
:state_event
,
:task_num
,
label_ids:
[]
:milestone_id
,
:
due_date
,
:
state_event
,
:task_num
,
label_ids:
[]
)
)
end
end
...
...
app/controllers/projects/merge_requests_controller.rb
View file @
7e0ef892
...
@@ -38,13 +38,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController
...
@@ -38,13 +38,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_requests
=
@merge_requests
.
page
(
params
[
:page
])
@merge_requests
=
@merge_requests
.
page
(
params
[
:page
])
@merge_requests
=
@merge_requests
.
preload
(
:target_project
)
@merge_requests
=
@merge_requests
.
preload
(
:target_project
)
@label
=
@project
.
labels
.
find_by
(
title:
params
[
:label_name
])
@label
s
=
@project
.
labels
.
where
(
title:
params
[
:label_name
])
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
html
format
.
html
format
.
json
do
format
.
json
do
render
json:
{
render
json:
{
html:
view_to_html_string
(
"projects/merge_requests/_merge_requests"
)
html:
view_to_html_string
(
"projects/merge_requests/_merge_requests"
),
labels:
@labels
.
as_json
(
methods: :text_color
)
}
}
end
end
end
end
...
...
app/finders/issuable_finder.rb
View file @
7e0ef892
...
@@ -39,6 +39,7 @@ class IssuableFinder
...
@@ -39,6 +39,7 @@ class IssuableFinder
items
=
by_assignee
(
items
)
items
=
by_assignee
(
items
)
items
=
by_author
(
items
)
items
=
by_author
(
items
)
items
=
by_label
(
items
)
items
=
by_label
(
items
)
items
=
by_due_date
(
items
)
sort
(
items
)
sort
(
items
)
end
end
...
@@ -117,7 +118,7 @@ class IssuableFinder
...
@@ -117,7 +118,7 @@ class IssuableFinder
end
end
def
filter_by_no_label?
def
filter_by_no_label?
labels?
&&
params
[
:label_name
]
==
Label
::
None
.
title
labels?
&&
params
[
:label_name
]
.
include?
(
Label
::
None
.
title
)
end
end
def
labels
def
labels
...
@@ -278,9 +279,47 @@ class IssuableFinder
...
@@ -278,9 +279,47 @@ class IssuableFinder
end
end
end
end
# When filtering by multiple labels we may end up duplicating issues (if one
# has multiple labels). This ensures we only return unique issues.
items
.
distinct
end
def
by_due_date
(
items
)
if
due_date?
if
filter_by_no_due_date?
items
=
items
.
without_due_date
elsif
filter_by_overdue?
items
=
items
.
due_before
(
Date
.
today
)
elsif
filter_by_due_this_week?
items
=
items
.
due_between
(
Date
.
today
.
beginning_of_week
,
Date
.
today
.
end_of_week
)
elsif
filter_by_due_this_month?
items
=
items
.
due_between
(
Date
.
today
.
beginning_of_month
,
Date
.
today
.
end_of_month
)
end
end
items
items
end
end
def
filter_by_no_due_date?
due_date?
&&
params
[
:due_date
]
==
Issue
::
NoDueDate
.
name
end
def
filter_by_overdue?
due_date?
&&
params
[
:due_date
]
==
Issue
::
Overdue
.
name
end
def
filter_by_due_this_week?
due_date?
&&
params
[
:due_date
]
==
Issue
::
DueThisWeek
.
name
end
def
filter_by_due_this_month?
due_date?
&&
params
[
:due_date
]
==
Issue
::
DueThisMonth
.
name
end
def
due_date?
params
[
:due_date
].
present?
&&
klass
.
column_names
.
include?
(
'due_date'
)
end
def
label_names
def
label_names
params
[
:label_name
].
split
(
','
)
params
[
:label_name
].
split
(
','
)
end
end
...
...
app/helpers/application_helper.rb
View file @
7e0ef892
...
@@ -254,11 +254,11 @@ module ApplicationHelper
...
@@ -254,11 +254,11 @@ module ApplicationHelper
def
page_filter_path
(
options
=
{})
def
page_filter_path
(
options
=
{})
without
=
options
.
delete
(
:without
)
without
=
options
.
delete
(
:without
)
add_label
=
options
.
delete
(
:label
)
exist_opts
=
{
exist_opts
=
{
state:
params
[
:state
],
state:
params
[
:state
],
scope:
params
[
:scope
],
scope:
params
[
:scope
],
label_name:
params
[
:label_name
],
milestone_title:
params
[
:milestone_title
],
milestone_title:
params
[
:milestone_title
],
assignee_id:
params
[
:assignee_id
],
assignee_id:
params
[
:assignee_id
],
author_id:
params
[
:author_id
],
author_id:
params
[
:author_id
],
...
@@ -275,6 +275,13 @@ module ApplicationHelper
...
@@ -275,6 +275,13 @@ module ApplicationHelper
path
=
request
.
path
path
=
request
.
path
path
<<
"?
#{
options
.
to_param
}
"
path
<<
"?
#{
options
.
to_param
}
"
if
add_label
if
params
[
:label_name
].
present?
and
params
[
:label_name
].
respond_to?
(
'any?'
)
params
[
:label_name
].
each
do
|
label
|
path
<<
"&label_name[]=
#{
label
}
"
end
end
end
path
path
end
end
...
...
app/helpers/issuables_helper.rb
View file @
7e0ef892
...
@@ -16,6 +16,25 @@ module IssuablesHelper
...
@@ -16,6 +16,25 @@ module IssuablesHelper
base_issuable_scope
(
issuable
).
where
(
'iid > ?'
,
issuable
.
iid
).
last
base_issuable_scope
(
issuable
).
where
(
'iid > ?'
,
issuable
.
iid
).
last
end
end
def
multi_label_name
(
current_labels
,
default_label
)
# current_labels may be a string from before
if
current_labels
.
is_a?
(
Array
)
if
current_labels
.
count
>
1
"
#{
current_labels
[
0
]
}
+
#{
current_labels
.
count
-
1
}
more"
else
current_labels
[
0
]
end
elsif
current_labels
.
is_a?
(
String
)
if
current_labels
.
nil?
||
current_labels
.
empty?
default_label
else
current_labels
end
else
default_label
end
end
def
issuable_json_path
(
issuable
)
def
issuable_json_path
(
issuable
)
project
=
issuable
.
project
project
=
issuable
.
project
...
...
app/helpers/issues_helper.rb
View file @
7e0ef892
...
@@ -131,7 +131,7 @@ module IssuesHelper
...
@@ -131,7 +131,7 @@ module IssuesHelper
class:
"icon emoji-icon emoji-
#{
unicode
}
"
,
class:
"icon emoji-icon emoji-
#{
unicode
}
"
,
title:
name
,
title:
name
,
data:
data
data:
data
else
else
# Emoji icons displayed separately, used for the awards already given
# Emoji icons displayed separately, used for the awards already given
# to an issue or merge request.
# to an issue or merge request.
content_tag
:img
,
""
,
content_tag
:img
,
""
,
...
@@ -172,6 +172,18 @@ module IssuesHelper
...
@@ -172,6 +172,18 @@ module IssuesHelper
end
.
to_h
end
.
to_h
end
end
def
due_date_options
options
=
[
Issue
::
AnyDueDate
,
Issue
::
NoDueDate
,
Issue
::
DueThisWeek
,
Issue
::
DueThisMonth
,
Issue
::
Overdue
]
options_from_collection_for_select
(
options
,
'name'
,
'title'
,
params
[
:due_date
])
end
# Required for Banzai::Filter::IssueReferenceFilter
# Required for Banzai::Filter::IssueReferenceFilter
module_function
:url_for_issue
module_function
:url_for_issue
end
end
app/helpers/sorting_helper.rb
View file @
7e0ef892
...
@@ -8,6 +8,8 @@ module SortingHelper
...
@@ -8,6 +8,8 @@ module SortingHelper
sort_value_oldest_created
=>
sort_title_oldest_created
,
sort_value_oldest_created
=>
sort_title_oldest_created
,
sort_value_milestone_soon
=>
sort_title_milestone_soon
,
sort_value_milestone_soon
=>
sort_title_milestone_soon
,
sort_value_milestone_later
=>
sort_title_milestone_later
,
sort_value_milestone_later
=>
sort_title_milestone_later
,
sort_value_due_date_soon
=>
sort_title_due_date_soon
,
sort_value_due_date_later
=>
sort_title_due_date_later
,
sort_value_largest_repo
=>
sort_title_largest_repo
,
sort_value_largest_repo
=>
sort_title_largest_repo
,
sort_value_recently_signin
=>
sort_title_recently_signin
,
sort_value_recently_signin
=>
sort_title_recently_signin
,
sort_value_oldest_signin
=>
sort_title_oldest_signin
,
sort_value_oldest_signin
=>
sort_title_oldest_signin
,
...
@@ -50,6 +52,14 @@ module SortingHelper
...
@@ -50,6 +52,14 @@ module SortingHelper
'Milestone due later'
'Milestone due later'
end
end
def
sort_title_due_date_soon
'Due soon'
end
def
sort_title_due_date_later
'Due later'
end
def
sort_title_name
def
sort_title_name
'Name'
'Name'
end
end
...
@@ -98,6 +108,14 @@ module SortingHelper
...
@@ -98,6 +108,14 @@ module SortingHelper
'milestone_due_desc'
'milestone_due_desc'
end
end
def
sort_value_due_date_soon
'due_date_asc'
end
def
sort_value_due_date_later
'due_date_desc'
end
def
sort_value_name
def
sort_value_name
'name_asc'
'name_asc'
end
end
...
...
app/models/issue.rb
View file @
7e0ef892
...
@@ -28,6 +28,13 @@ class Issue < ActiveRecord::Base
...
@@ -28,6 +28,13 @@ class Issue < ActiveRecord::Base
include
Sortable
include
Sortable
include
Taskable
include
Taskable
DueDateStruct
=
Struct
.
new
(
:title
,
:name
).
freeze
NoDueDate
=
DueDateStruct
.
new
(
'No Due Date'
,
'0'
).
freeze
AnyDueDate
=
DueDateStruct
.
new
(
'Any Due Date'
,
''
).
freeze
Overdue
=
DueDateStruct
.
new
(
'Overdue'
,
'overdue'
).
freeze
DueThisWeek
=
DueDateStruct
.
new
(
'Due This Week'
,
'week'
).
freeze
DueThisMonth
=
DueDateStruct
.
new
(
'Due This Month'
,
'month'
).
freeze
ActsAsTaggableOn
.
strict_case_match
=
true
ActsAsTaggableOn
.
strict_case_match
=
true
belongs_to
:project
belongs_to
:project
...
@@ -39,6 +46,13 @@ class Issue < ActiveRecord::Base
...
@@ -39,6 +46,13 @@ class Issue < ActiveRecord::Base
scope
:open_for
,
->
(
user
)
{
opened
.
assigned_to
(
user
)
}
scope
:open_for
,
->
(
user
)
{
opened
.
assigned_to
(
user
)
}
scope
:in_projects
,
->
(
project_ids
)
{
where
(
project_id:
project_ids
)
}
scope
:in_projects
,
->
(
project_ids
)
{
where
(
project_id:
project_ids
)
}
scope
:without_due_date
,
->
{
where
(
due_date:
nil
)
}
scope
:due_before
,
->
(
date
)
{
where
(
'issues.due_date < ?'
,
date
)
}
scope
:due_between
,
->
(
from_date
,
to_date
)
{
where
(
'issues.due_date >= ?'
,
from_date
).
where
(
'issues.due_date <= ?'
,
to_date
)
}
scope
:order_due_date_asc
,
->
{
reorder
(
'issues.due_date IS NULL, issues.due_date ASC'
)
}
scope
:order_due_date_desc
,
->
{
reorder
(
'issues.due_date IS NULL, issues.due_date DESC'
)
}
state_machine
:state
,
initial: :opened
do
state_machine
:state
,
initial: :opened
do
event
:close
do
event
:close
do
transition
[
:reopened
,
:opened
]
=>
:closed
transition
[
:reopened
,
:opened
]
=>
:closed
...
@@ -82,6 +96,15 @@ class Issue < ActiveRecord::Base
...
@@ -82,6 +96,15 @@ class Issue < ActiveRecord::Base
@link_reference_pattern
||=
super
(
"issues"
,
/(?<issue>\d+)/
)
@link_reference_pattern
||=
super
(
"issues"
,
/(?<issue>\d+)/
)
end
end
def
self
.
sort
(
method
)
case
method
.
to_s
when
'due_date_asc'
then
order_due_date_asc
when
'due_date_desc'
then
order_due_date_desc
else
super
end
end
def
to_reference
(
from_project
=
nil
)
def
to_reference
(
from_project
=
nil
)
reference
=
"
#{
self
.
class
.
reference_prefix
}#{
iid
}
"
reference
=
"
#{
self
.
class
.
reference_prefix
}#{
iid
}
"
...
@@ -169,4 +192,8 @@ class Issue < ActiveRecord::Base
...
@@ -169,4 +192,8 @@ class Issue < ActiveRecord::Base
self
.
related_branches
(
current_user
).
empty?
&&
self
.
related_branches
(
current_user
).
empty?
&&
self
.
closed_by_merge_requests
(
current_user
).
empty?
self
.
closed_by_merge_requests
(
current_user
).
empty?
end
end
def
overdue?
due_date
.
try
(
:past?
)
||
false
end
end
end
app/models/label.rb
View file @
7e0ef892
...
@@ -113,6 +113,10 @@ class Label < ActiveRecord::Base
...
@@ -113,6 +113,10 @@ class Label < ActiveRecord::Base
template
template
end
end
def
text_color
LabelsHelper
::
text_color_for_bg
(
self
.
color
)
end
private
private
def
label_format_reference
(
format
=
:id
)
def
label_format_reference
(
format
=
:id
)
...
...
app/views/projects/_activity.html.haml
View file @
7e0ef892
...
@@ -9,4 +9,7 @@
...
@@ -9,4 +9,7 @@
=
spinner
=
spinner
:javascript
:javascript
new
Activities
();
var
activity
=
new
Activities
();
$
(
document
).
on
(
'
page:restore
'
,
function
(
event
)
{
activity
.
reloadActivities
()
})
app/views/projects/issues/_issue.html.haml
View file @
7e0ef892
...
@@ -48,6 +48,11 @@
...
@@ -48,6 +48,11 @@
=
link_to
namespace_project_issues_path
(
issue
.
project
.
namespace
,
issue
.
project
,
milestone_title:
issue
.
milestone
.
title
)
do
=
link_to
namespace_project_issues_path
(
issue
.
project
.
namespace
,
issue
.
project
,
milestone_title:
issue
.
milestone
.
title
)
do
=
icon
(
'clock-o'
)
=
icon
(
'clock-o'
)
=
issue
.
milestone
.
title
=
issue
.
milestone
.
title
-
if
issue
.
due_date
%span
{
class:
"#{'cred' if issue.overdue?}"
}
=
icon
(
'calendar'
)
=
issue
.
due_date
.
to_s
(
:medium
)
-
if
issue
.
labels
.
any?
-
if
issue
.
labels
.
any?
-
issue
.
labels
.
each
do
|
label
|
-
issue
.
labels
.
each
do
|
label
|
...
...
app/views/projects/merge_requests/show/_mr_title.html.haml
View file @
7e0ef892
...
@@ -24,9 +24,9 @@
...
@@ -24,9 +24,9 @@
%li
{
class:
issue_button_visibility
(
@merge_request
,
false
)
}
%li
{
class:
issue_button_visibility
(
@merge_request
,
false
)
}
=
link_to
'Reopen'
,
merge_request_path
(
@merge_request
,
merge_request:
{
state_event: :reopen
}),
method: :put
,
class:
'reopen-mr-link'
,
title:
'Reopen merge request'
=
link_to
'Reopen'
,
merge_request_path
(
@merge_request
,
merge_request:
{
state_event: :reopen
}),
method: :put
,
class:
'reopen-mr-link'
,
title:
'Reopen merge request'
%li
%li
=
link_to
'Edit'
,
edit_namespace_project_merge_request_path
(
@project
.
namespace
,
@project
,
@merge_request
),
class:
'issuable-edit'
,
id:
'edit_merge_request'
=
link_to
'Edit'
,
edit_namespace_project_merge_request_path
(
@project
.
namespace
,
@project
,
@merge_request
),
class:
'issuable-edit'
=
link_to
'Close'
,
merge_request_path
(
@merge_request
,
merge_request:
{
state_event: :close
}),
method: :put
,
class:
"hidden-xs hidden-sm btn btn-nr btn-grouped btn-close
#{
issue_button_visibility
(
@merge_request
,
true
)
}
"
,
title:
'Close merge request'
=
link_to
'Close'
,
merge_request_path
(
@merge_request
,
merge_request:
{
state_event: :close
}),
method: :put
,
class:
"hidden-xs hidden-sm btn btn-nr btn-grouped btn-close
#{
issue_button_visibility
(
@merge_request
,
true
)
}
"
,
title:
'Close merge request'
=
link_to
'Reopen'
,
merge_request_path
(
@merge_request
,
merge_request:
{
state_event: :reopen
}),
method: :put
,
class:
"hidden-xs hidden-sm btn btn-nr btn-grouped btn-reopen reopen-mr-link
#{
issue_button_visibility
(
@merge_request
,
false
)
}
"
,
title:
'Reopen merge request'
=
link_to
'Reopen'
,
merge_request_path
(
@merge_request
,
merge_request:
{
state_event: :reopen
}),
method: :put
,
class:
"hidden-xs hidden-sm btn btn-nr btn-grouped btn-reopen reopen-mr-link
#{
issue_button_visibility
(
@merge_request
,
false
)
}
"
,
title:
'Reopen merge request'
=
link_to
edit_namespace_project_merge_request_path
(
@project
.
namespace
,
@project
,
@merge_request
),
class:
"hidden-xs hidden-sm btn btn-nr btn-grouped issuable-edit"
,
id:
'edit_merge_request'
do
=
link_to
edit_namespace_project_merge_request_path
(
@project
.
namespace
,
@project
,
@merge_request
),
class:
"hidden-xs hidden-sm btn btn-nr btn-grouped issuable-edit"
do
=
icon
(
'pencil-square-o'
)
=
icon
(
'pencil-square-o'
)
Edit
Edit
app/views/shared/_label_row.html.haml
View file @
7e0ef892
...
@@ -2,4 +2,4 @@
...
@@ -2,4 +2,4 @@
%span
.label-name
%span
.label-name
=
link_to_label
(
label
,
tooltip:
false
)
=
link_to_label
(
label
,
tooltip:
false
)
%span
.prepend-left-10
%span
.prepend-left-10
=
markdown
(
label
.
description
,
pipeline: :single_line
)
=
markdown
(
label
.
description
,
pipeline: :single_line
)
\ No newline at end of file
app/views/shared/_labels_row.html.haml
0 → 100644
View file @
7e0ef892
-
labels
.
each
do
|
label
|
%span
.label-row
=
link_to_label
(
label
,
tooltip:
false
)
app/views/shared/_sort_dropdown.html.haml
View file @
7e0ef892
...
@@ -20,6 +20,11 @@
...
@@ -20,6 +20,11 @@
=
sort_title_milestone_soon
=
sort_title_milestone_soon
=
link_to
page_filter_path
(
sort:
sort_value_milestone_later
)
do
=
link_to
page_filter_path
(
sort:
sort_value_milestone_later
)
do
=
sort_title_milestone_later
=
sort_title_milestone_later
-
if
controller
.
controller_name
==
'issues'
||
controller
.
action_name
==
'issues'
=
link_to
page_filter_path
(
sort:
sort_value_due_date_soon
)
do
=
sort_title_due_date_soon
=
link_to
page_filter_path
(
sort:
sort_value_due_date_later
)
do
=
sort_title_due_date_later
=
link_to
page_filter_path
(
sort:
sort_value_upvotes
)
do
=
link_to
page_filter_path
(
sort:
sort_value_upvotes
)
do
=
sort_title_upvotes
=
sort_title_upvotes
=
link_to
page_filter_path
(
sort:
sort_value_downvotes
)
do
=
link_to
page_filter_path
(
sort:
sort_value_downvotes
)
do
...
...
app/views/shared/issuable/_filter.html.haml
View file @
7e0ef892
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
.filter-item.inline.labels-filter
.filter-item.inline.labels-filter
=
render
"shared/issuable/label_dropdown"
=
render
"shared/issuable/label_dropdown"
.pull-right
.pull-right
=
render
'shared/sort_dropdown'
=
render
'shared/sort_dropdown'
...
@@ -46,9 +47,10 @@
...
@@ -46,9 +47,10 @@
.filter-item.inline
.filter-item.inline
=
button_tag
"Update issues"
,
class:
"btn update_selected_issues btn-save"
=
button_tag
"Update issues"
,
class:
"btn update_selected_issues btn-save"
-
if
@label
-
if
!
@labels
.
nil?
.gray-content-block.second-block
.gray-content-block.second-block.filtered-labels
{
class:
(
"hidden"
if
!
@labels
.
any?
)
}
=
render
"shared/label_row"
,
label:
@label
-
if
@labels
.
any?
=
render
"shared/labels_row"
,
labels:
@labels
:javascript
:javascript
new
UsersSelect
();
new
UsersSelect
();
...
...
app/views/shared/issuable/_label_dropdown.html.haml
View file @
7e0ef892
-
if
params
[
:label_name
].
present?
-
if
params
[
:label_name
].
present?
=
hidden_field_tag
(
:label_name
,
params
[
:label_name
])
-
if
params
[
:label_name
].
respond_to?
(
'any?'
)
-
params
[
:label_name
].
each
do
|
label
|
=
hidden_field_tag
"label_name[]"
,
label
,
id:
nil
.dropdown
.dropdown
%button
.dropdown-menu-toggle.js-label-select.js-filter-submit.js-
extra-options
{
type:
"button"
,
data:
{
toggle:
"dropdown"
,
field_name:
"label_name
"
,
show_no:
"true"
,
show_any:
"true"
,
selected:
params
[
:label_name
],
project_id:
@project
.
try
(
:id
),
labels:
labels_filter_path
,
default_label:
"Label"
}}
%button
.dropdown-menu-toggle.js-label-select.js-filter-submit.js-
multiselect.js-extra-options
{
type:
"button"
,
data:
{
toggle:
"dropdown"
,
field_name:
"label_name[]
"
,
show_no:
"true"
,
show_any:
"true"
,
selected:
params
[
:label_name
],
project_id:
@project
.
try
(
:id
),
labels:
labels_filter_path
,
default_label:
"Label"
}}
%span
.dropdown-toggle-text
%span
.dropdown-toggle-text
=
h
(
params
[
:label_name
].
presence
||
"Label"
)
=
h
(
multi_label_name
(
params
[
:label_name
],
"Label"
)
)
=
icon
(
'chevron-down'
)
=
icon
(
'chevron-down'
)
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
=
render
partial:
"shared/issuable/label_page_default"
,
locals:
{
title:
"Filter by label"
}
=
render
partial:
"shared/issuable/label_page_default"
,
locals:
{
title:
"Filter by label"
}
...
...
app/views/shared/issuable/_nav.html.haml
View file @
7e0ef892
...
@@ -4,22 +4,22 @@
...
@@ -4,22 +4,22 @@
-
else
-
else
-
page_context_word
=
'issues'
-
page_context_word
=
'issues'
%li
{
class:
(
"active"
if
params
[
:state
]
==
'opened'
)}
%li
{
class:
(
"active"
if
params
[
:state
]
==
'opened'
)}
=
link_to
page_filter_path
(
state:
'opened'
),
title:
"Filter by
#{
page_context_word
}
that are currently opened."
do
=
link_to
page_filter_path
(
state:
'opened'
,
label:
true
),
title:
"Filter by
#{
page_context_word
}
that are currently opened."
do
#{
state_filters_text_for
(
:opened
,
@project
)
}
#{
state_filters_text_for
(
:opened
,
@project
)
}
-
if
defined?
(
type
)
&&
type
==
:merge_requests
-
if
defined?
(
type
)
&&
type
==
:merge_requests
%li
{
class:
(
"active"
if
params
[
:state
]
==
'merged'
)}
%li
{
class:
(
"active"
if
params
[
:state
]
==
'merged'
)}
=
link_to
page_filter_path
(
state:
'merged'
),
title:
'Filter by merge requests that are currently merged.'
do
=
link_to
page_filter_path
(
state:
'merged'
,
label:
true
),
title:
'Filter by merge requests that are currently merged.'
do
#{
state_filters_text_for
(
:merged
,
@project
)
}
#{
state_filters_text_for
(
:merged
,
@project
)
}
%li
{
class:
(
"active"
if
params
[
:state
]
==
'closed'
)}
%li
{
class:
(
"active"
if
params
[
:state
]
==
'closed'
)}
=
link_to
page_filter_path
(
state:
'closed'
),
title:
'Filter by merge requests that are currently closed and unmerged.'
do
=
link_to
page_filter_path
(
state:
'closed'
,
label:
true
),
title:
'Filter by merge requests that are currently closed and unmerged.'
do
#{
state_filters_text_for
(
:closed
,
@project
)
}
#{
state_filters_text_for
(
:closed
,
@project
)
}
-
else
-
else
%li
{
class:
(
"active"
if
params
[
:state
]
==
'closed'
)}
%li
{
class:
(
"active"
if
params
[
:state
]
==
'closed'
)}
=
link_to
page_filter_path
(
state:
'closed'
),
title:
'Filter by issues that are currently closed.'
do
=
link_to
page_filter_path
(
state:
'closed'
,
label:
true
),
title:
'Filter by issues that are currently closed.'
do
#{
state_filters_text_for
(
:closed
,
@project
)
}
#{
state_filters_text_for
(
:closed
,
@project
)
}
%li
{
class:
(
"active"
if
params
[
:state
]
==
'all'
)}
%li
{
class:
(
"active"
if
params
[
:state
]
==
'all'
)}
=
link_to
page_filter_path
(
state:
'all'
),
title:
"Show all
#{
page_context_word
}
."
do
=
link_to
page_filter_path
(
state:
'all'
,
label:
true
),
title:
"Show all
#{
page_context_word
}
."
do
#{
state_filters_text_for
(
:all
,
@project
)
}
#{
state_filters_text_for
(
:all
,
@project
)
}
app/views/shared/issuable/_sidebar.html.haml
View file @
7e0ef892
...
@@ -10,14 +10,14 @@
...
@@ -10,14 +10,14 @@
=
sidebar_gutter_toggle_icon
=
sidebar_gutter_toggle_icon
.issuable-nav.hide-collapsed.pull-right.btn-group
{
role:
'group'
,
"aria-label"
=>
'...'
}
.issuable-nav.hide-collapsed.pull-right.btn-group
{
role:
'group'
,
"aria-label"
=>
'...'
}
-
if
prev_issuable
=
prev_issuable_for
(
issuable
)
-
if
prev_issuable
=
prev_issuable_for
(
issuable
)
=
link_to
'Prev'
,
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
prev_issuable
],
class:
'btn btn-default prev-btn'
=
link_to
'Prev'
,
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
prev_issuable
],
class:
'btn btn-default prev-btn
issuable-pager
'
-
else
-
else
%a
.btn.btn-default.disabled
{
href:
'#'
}
%a
.btn.btn-default.
issuable-pager.
disabled
{
href:
'#'
}
Prev
Prev
-
if
next_issuable
=
next_issuable_for
(
issuable
)
-
if
next_issuable
=
next_issuable_for
(
issuable
)
=
link_to
'Next'
,
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
next_issuable
],
class:
'btn btn-default next-btn'
=
link_to
'Next'
,
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
next_issuable
],
class:
'btn btn-default next-btn
issuable-pager
'
-
else
-
else
%a
.btn.btn-default.disabled
{
href:
'#'
}
%a
.btn.btn-default.
issuable-pager.
disabled
{
href:
'#'
}
Next
Next
=
form_for
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
issuable
],
remote:
true
,
html:
{
class:
'issuable-context-form inline-update js-issuable-update'
}
do
|
f
|
=
form_for
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
issuable
],
remote:
true
,
html:
{
class:
'issuable-context-form inline-update js-issuable-update'
}
do
|
f
|
...
@@ -58,7 +58,7 @@
...
@@ -58,7 +58,7 @@
-
if
issuable
.
milestone
-
if
issuable
.
milestone
=
issuable
.
milestone
.
title
=
issuable
.
milestone
.
title
-
else
-
else
No
No
ne
.title.hide-collapsed
.title.hide-collapsed
Milestone
Milestone
=
icon
(
'spinner spin'
,
class:
'block-loading'
)
=
icon
(
'spinner spin'
,
class:
'block-loading'
)
...
@@ -75,6 +75,34 @@
...
@@ -75,6 +75,34 @@
=
f
.
hidden_field
'milestone_id'
,
value:
issuable
.
milestone_id
,
id:
nil
=
f
.
hidden_field
'milestone_id'
,
value:
issuable
.
milestone_id
,
id:
nil
=
dropdown_tag
(
'Milestone'
,
options:
{
title:
'Assign milestone'
,
toggle_class:
'js-milestone-select js-extra-options'
,
filter:
true
,
dropdown_class:
'dropdown-menu-selectable'
,
placeholder:
'Search milestones'
,
data:
{
show_no:
true
,
field_name:
"
#{
issuable
.
to_ability_name
}
[milestone_id]"
,
project_id:
@project
.
id
,
issuable_id:
issuable
.
id
,
milestones:
namespace_project_milestones_path
(
@project
.
namespace
,
@project
,
:json
),
ability_name:
issuable
.
to_ability_name
,
issue_update:
issuable_json_path
(
issuable
),
use_id:
true
}})
=
dropdown_tag
(
'Milestone'
,
options:
{
title:
'Assign milestone'
,
toggle_class:
'js-milestone-select js-extra-options'
,
filter:
true
,
dropdown_class:
'dropdown-menu-selectable'
,
placeholder:
'Search milestones'
,
data:
{
show_no:
true
,
field_name:
"
#{
issuable
.
to_ability_name
}
[milestone_id]"
,
project_id:
@project
.
id
,
issuable_id:
issuable
.
id
,
milestones:
namespace_project_milestones_path
(
@project
.
namespace
,
@project
,
:json
),
ability_name:
issuable
.
to_ability_name
,
issue_update:
issuable_json_path
(
issuable
),
use_id:
true
}})
-
if
issuable
.
has_attribute?
(
:due_date
)
.block.due_date
.sidebar-collapsed-icon
=
icon
(
'calendar'
)
%span
.js-due-date-sidebar-value
=
issuable
.
due_date
.
try
(
:to_s
,
:medium
)
||
'None'
.title.hide-collapsed
Due date
=
icon
(
'spinner spin'
,
class:
'block-loading'
)
-
if
can?
(
current_user
,
:"admin_
#{
issuable
.
to_ability_name
}
"
,
@project
)
=
link_to
'Edit'
,
'#'
,
class:
'edit-link pull-right'
.value.bold.hide-collapsed
-
if
issuable
.
due_date
=
issuable
.
due_date
.
to_s
(
:medium
)
-
else
.light
None
-
if
can?
(
current_user
,
:"admin_
#{
issuable
.
to_ability_name
}
"
,
@project
)
.selectbox.hide-collapsed
=
f
.
hidden_field
:due_date
,
value:
issuable
.
due_date
.dropdown
%button
.dropdown-menu-toggle.js-due-date-select
{
type:
'button'
,
data:
{
toggle:
'dropdown'
,
field_name:
"#{issuable.to_ability_name}[due_date]"
,
ability_name:
issuable
.
to_ability_name
,
issue_update:
issuable_json_path
(
issuable
)
}
}
%span
.dropdown-toggle-text
Due date
=
icon
(
'chevron-down'
)
.dropdown-menu.dropdown-menu-due-date
=
dropdown_title
(
'Due date'
)
=
dropdown_content
do
.js-due-date-calendar
-
if
issuable
.
project
.
labels
.
any?
-
if
issuable
.
project
.
labels
.
any?
.block.labels
.block.labels
.sidebar-collapsed-icon
.sidebar-collapsed-icon
...
@@ -139,3 +167,4 @@
...
@@ -139,3 +167,4 @@
new
IssuableContext
(
'
#{
escape_javascript
(
current_user
.
to_json
(
only:
[
:username
,
:id
,
:name
]))
}
'
);
new
IssuableContext
(
'
#{
escape_javascript
(
current_user
.
to_json
(
only:
[
:username
,
:id
,
:name
]))
}
'
);
new
Subscription
(
'
.subscription
'
)
new
Subscription
(
'
.subscription
'
)
new
Sidebar
();
new
Sidebar
();
new
DueDateSelect
();
db/migrate/20160310124959_add_due_date_to_issues.rb
0 → 100644
View file @
7e0ef892
class
AddDueDateToIssues
<
ActiveRecord
::
Migration
def
change
add_column
:issues
,
:due_date
,
:date
add_index
:issues
,
:due_date
end
end
db/schema.rb
View file @
7e0ef892
...
@@ -422,6 +422,7 @@ ActiveRecord::Schema.define(version: 20160419120017) do
...
@@ -422,6 +422,7 @@ ActiveRecord::Schema.define(version: 20160419120017) do
t
.
integer
"moved_to_id"
t
.
integer
"moved_to_id"
t
.
boolean
"confidential"
,
default:
false
t
.
boolean
"confidential"
,
default:
false
t
.
datetime
"deleted_at"
t
.
datetime
"deleted_at"
t
.
date
"due_date"
end
end
add_index
"issues"
,
[
"assignee_id"
],
name:
"index_issues_on_assignee_id"
,
using: :btree
add_index
"issues"
,
[
"assignee_id"
],
name:
"index_issues_on_assignee_id"
,
using: :btree
...
@@ -431,6 +432,7 @@ ActiveRecord::Schema.define(version: 20160419120017) do
...
@@ -431,6 +432,7 @@ ActiveRecord::Schema.define(version: 20160419120017) do
add_index
"issues"
,
[
"created_at"
],
name:
"index_issues_on_created_at"
,
using: :btree
add_index
"issues"
,
[
"created_at"
],
name:
"index_issues_on_created_at"
,
using: :btree
add_index
"issues"
,
[
"deleted_at"
],
name:
"index_issues_on_deleted_at"
,
using: :btree
add_index
"issues"
,
[
"deleted_at"
],
name:
"index_issues_on_deleted_at"
,
using: :btree
add_index
"issues"
,
[
"description"
],
name:
"index_issues_on_description_trigram"
,
using: :gin
,
opclasses:
{
"description"
=>
"gin_trgm_ops"
}
add_index
"issues"
,
[
"description"
],
name:
"index_issues_on_description_trigram"
,
using: :gin
,
opclasses:
{
"description"
=>
"gin_trgm_ops"
}
add_index
"issues"
,
[
"due_date"
],
name:
"index_issues_on_due_date"
,
using: :btree
add_index
"issues"
,
[
"milestone_id"
],
name:
"index_issues_on_milestone_id"
,
using: :btree
add_index
"issues"
,
[
"milestone_id"
],
name:
"index_issues_on_milestone_id"
,
using: :btree
add_index
"issues"
,
[
"project_id"
,
"iid"
],
name:
"index_issues_on_project_id_and_iid"
,
unique:
true
,
using: :btree
add_index
"issues"
,
[
"project_id"
,
"iid"
],
name:
"index_issues_on_project_id_and_iid"
,
unique:
true
,
using: :btree
add_index
"issues"
,
[
"project_id"
],
name:
"index_issues_on_project_id"
,
using: :btree
add_index
"issues"
,
[
"project_id"
],
name:
"index_issues_on_project_id"
,
using: :btree
...
...
features/project/issues/filter_labels.feature
View file @
7e0ef892
...
@@ -12,6 +12,7 @@ Feature: Project Issues Filter Labels
...
@@ -12,6 +12,7 @@ Feature: Project Issues Filter Labels
@javascript
@javascript
Scenario
:
I
filter by one label
Scenario
:
I
filter by one label
Given
I click link
"bug"
Given
I click link
"bug"
And
I click
"dropdown close button"
Then
I should see
"Bugfix1"
in issues list
Then
I should see
"Bugfix1"
in issues list
And
I should see
"Bugfix2"
in issues list
And
I should see
"Bugfix2"
in issues list
And
I should not see
"Feature1"
in issues list
And
I should not see
"Feature1"
in issues list
...
...
features/steps/project/issues/filter_labels.rb
View file @
7e0ef892
...
@@ -32,6 +32,10 @@ class Spinach::Features::ProjectIssuesFilterLabels < Spinach::FeatureSteps
...
@@ -32,6 +32,10 @@ class Spinach::Features::ProjectIssuesFilterLabels < Spinach::FeatureSteps
page
.
find
(
'.js-label-select'
).
click
page
.
find
(
'.js-label-select'
).
click
sleep
0.5
sleep
0.5
execute_script
(
"$('.dropdown-menu-labels li:contains(
\"
bug
\"
) a').click()"
)
execute_script
(
"$('.dropdown-menu-labels li:contains(
\"
bug
\"
) a').click()"
)
end
step
'I click "dropdown close button"'
do
page
.
first
(
'.labels-filter .dropdown-title .dropdown-menu-close-icon'
).
click
sleep
2
sleep
2
end
end
...
...
lib/api/internal.rb
View file @
7e0ef892
...
@@ -23,7 +23,7 @@ module API
...
@@ -23,7 +23,7 @@ module API
end
end
post
"/allowed"
do
post
"/allowed"
do
Gitlab
::
Metrics
.
tag_transaction
(
'action'
,
'Grape#/internal/allowed'
)
Gitlab
::
Metrics
.
action
=
'Grape#/internal/allowed'
status
200
status
200
...
...
lib/gitlab/gon_helper.rb
View file @
7e0ef892
...
@@ -7,6 +7,7 @@ module Gitlab
...
@@ -7,6 +7,7 @@ module Gitlab
gon
.
max_file_size
=
current_application_settings
.
max_attachment_size
gon
.
max_file_size
=
current_application_settings
.
max_attachment_size
gon
.
relative_url_root
=
Gitlab
.
config
.
gitlab
.
relative_url_root
gon
.
relative_url_root
=
Gitlab
.
config
.
gitlab
.
relative_url_root
gon
.
user_color_scheme
=
Gitlab
::
ColorSchemes
.
for_user
(
current_user
).
css_class
gon
.
user_color_scheme
=
Gitlab
::
ColorSchemes
.
for_user
(
current_user
).
css_class
gon
.
sentry_dsn
=
ApplicationSetting
.
current
.
sentry_dsn
if
Rails
.
env
.
production?
if
current_user
if
current_user
gon
.
current_user_id
=
current_user
.
id
gon
.
current_user_id
=
current_user
.
id
...
...
lib/gitlab/metrics.rb
View file @
7e0ef892
...
@@ -115,6 +115,15 @@ module Gitlab
...
@@ -115,6 +115,15 @@ module Gitlab
trans
.
add_tag
(
name
,
value
)
if
trans
trans
.
add_tag
(
name
,
value
)
if
trans
end
end
# Sets the action of the current transaction (if any)
#
# action - The name of the action.
def
self
.
action
=
(
action
)
trans
=
current_transaction
trans
.
action
=
action
if
trans
end
# When enabled this should be set before being used as the usual pattern
# When enabled this should be set before being used as the usual pattern
# "@foo ||= bar" is _not_ thread-safe.
# "@foo ||= bar" is _not_ thread-safe.
if
enabled?
if
enabled?
...
...
spec/features/issues/filter_by_labels_spec.rb
0 → 100644
View file @
7e0ef892
require
'rails_helper'
feature
'Issue filtering by Labels'
,
feature:
true
do
let
(
:project
)
{
create
(
:project
,
:public
)
}
let!
(
:user
)
{
create
(
:user
)}
let!
(
:label
)
{
create
(
:label
,
project:
project
)
}
before
do
[
'bug'
,
'feature'
,
'enhancement'
].
each
do
|
title
|
create
(
:label
,
project:
project
,
title:
title
)
end
issue1
=
create
(
:issue
,
title:
"Bugfix1"
,
project:
project
)
issue1
.
labels
<<
project
.
labels
.
find_by
(
title:
'bug'
)
issue2
=
create
(
:issue
,
title:
"Bugfix2"
,
project:
project
)
issue2
.
labels
<<
project
.
labels
.
find_by
(
title:
'bug'
)
issue2
.
labels
<<
project
.
labels
.
find_by
(
title:
'enhancement'
)
issue3
=
create
(
:issue
,
title:
"Feature1"
,
project:
project
)
issue3
.
labels
<<
project
.
labels
.
find_by
(
title:
'feature'
)
project
.
team
<<
[
user
,
:master
]
login_as
(
user
)
visit
namespace_project_issues_path
(
project
.
namespace
,
project
)
end
context
'filter by label bug'
,
js:
true
do
before
do
page
.
find
(
'.js-label-select'
).
click
sleep
0.5
execute_script
(
"$('.dropdown-menu-labels li:contains(
\"
bug
\"
) a').click()"
)
page
.
first
(
'.labels-filter .dropdown-title .dropdown-menu-close-icon'
).
click
sleep
2
end
it
'should show issue "Bugfix1" and "Bugfix2" in issues list'
do
expect
(
page
).
to
have_content
"Bugfix1"
expect
(
page
).
to
have_content
"Bugfix2"
end
it
'should not show "Feature1" in issues list'
do
expect
(
page
).
not_to
have_content
"Feature1"
end
it
'should show label "bug" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
to
have_content
"bug"
end
it
'should not show label "feature" and "enhancement" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
not_to
have_content
"feature"
expect
(
find
(
'.filtered-labels'
)).
not_to
have_content
"enhancement"
end
end
context
'filter by label feature'
,
js:
true
do
before
do
page
.
find
(
'.js-label-select'
).
click
sleep
0.5
execute_script
(
"$('.dropdown-menu-labels li:contains(
\"
feature
\"
) a').click()"
)
page
.
first
(
'.labels-filter .dropdown-title .dropdown-menu-close-icon'
).
click
sleep
2
end
it
'should show issue "Feature1" in issues list'
do
expect
(
page
).
to
have_content
"Feature1"
end
it
'should not show "Bugfix1" and "Bugfix2" in issues list'
do
expect
(
page
).
not_to
have_content
"Bugfix2"
expect
(
page
).
not_to
have_content
"Bugfix1"
end
it
'should show label "feature" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
to
have_content
"feature"
end
it
'should not show label "bug" and "enhancement" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
not_to
have_content
"bug"
expect
(
find
(
'.filtered-labels'
)).
not_to
have_content
"enhancement"
end
end
context
'filter by label enhancement'
,
js:
true
do
before
do
page
.
find
(
'.js-label-select'
).
click
sleep
0.5
execute_script
(
"$('.dropdown-menu-labels li:contains(
\"
enhancement
\"
) a').click()"
)
page
.
first
(
'.labels-filter .dropdown-title .dropdown-menu-close-icon'
).
click
sleep
2
end
it
'should show issue "Bugfix2" in issues list'
do
expect
(
page
).
to
have_content
"Bugfix2"
end
it
'should not show "Feature1" and "Bugfix1" in issues list'
do
expect
(
page
).
not_to
have_content
"Feature1"
expect
(
page
).
not_to
have_content
"Bugfix1"
end
it
'should show label "enhancement" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
to
have_content
"enhancement"
end
it
'should not show label "feature" and "bug" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
not_to
have_content
"bug"
expect
(
find
(
'.filtered-labels'
)).
not_to
have_content
"feature"
end
end
context
'filter by label enhancement or feature'
,
js:
true
do
before
do
page
.
find
(
'.js-label-select'
).
click
sleep
0.5
execute_script
(
"$('.dropdown-menu-labels li:contains(
\"
enhancement
\"
) a').click()"
)
execute_script
(
"$('.dropdown-menu-labels li:contains(
\"
feature
\"
) a').click()"
)
page
.
first
(
'.labels-filter .dropdown-title .dropdown-menu-close-icon'
).
click
sleep
2
end
it
'should show issue "Bugfix2" or "Feature1" in issues list'
do
expect
(
page
).
to
have_content
"Bugfix2"
expect
(
page
).
to
have_content
"Feature1"
end
it
'should not show "Bugfix1" in issues list'
do
expect
(
page
).
not_to
have_content
"Bugfix1"
end
it
'should show label "enhancement" and "feature" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
to
have_content
"enhancement"
expect
(
find
(
'.filtered-labels'
)).
to
have_content
"feature"
end
it
'should not show label "bug" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
not_to
have_content
"bug"
end
end
context
'filter by label enhancement or bug in issues list'
,
js:
true
do
before
do
page
.
find
(
'.js-label-select'
).
click
sleep
0.5
execute_script
(
"$('.dropdown-menu-labels li:contains(
\"
enhancement
\"
) a').click()"
)
execute_script
(
"$('.dropdown-menu-labels li:contains(
\"
bug
\"
) a').click()"
)
page
.
first
(
'.labels-filter .dropdown-title .dropdown-menu-close-icon'
).
click
sleep
2
end
it
'should show issue "Bugfix2" or "Bugfix1" in issues list'
do
expect
(
page
).
to
have_content
"Bugfix2"
expect
(
page
).
to
have_content
"Bugfix1"
end
it
'should not show "Feature1"'
do
expect
(
page
).
not_to
have_content
"Feature1"
end
it
'should show label "bug" and "enhancement" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
to
have_content
"bug"
expect
(
find
(
'.filtered-labels'
)).
to
have_content
"enhancement"
end
it
'should not show label "feature" in filtered-labels'
do
expect
(
find
(
'.filtered-labels'
)).
not_to
have_content
"feature"
end
end
end
spec/features/issues/filter_issues_spec.rb
View file @
7e0ef892
...
@@ -84,14 +84,20 @@ describe 'Filter issues', feature: true do
...
@@ -84,14 +84,20 @@ describe 'Filter issues', feature: true do
it
'should filter by any label'
do
it
'should filter by any label'
do
find
(
'.dropdown-menu-labels a'
,
text:
'Any Label'
).
click
find
(
'.dropdown-menu-labels a'
,
text:
'Any Label'
).
click
page
.
first
(
'.labels-filter .dropdown-title .dropdown-menu-close-icon'
).
click
sleep
2
page
.
within
'.labels-filter'
do
page
.
within
'.labels-filter'
do
expect
(
page
).
to
have_content
'Any Label'
expect
(
page
).
to
have_content
'Any Label'
end
end
expect
(
find
(
'.js-label-select .dropdown-toggle-text'
)).
to
have_content
(
'Label'
)
expect
(
find
(
'.js-label-select .dropdown-toggle-text'
)).
to
have_content
(
'
Any
Label'
)
end
end
it
'should filter by no label'
do
it
'should filter by no label'
do
find
(
'.dropdown-menu-labels a'
,
text:
'No Label'
).
click
find
(
'.dropdown-menu-labels a'
,
text:
'No Label'
).
click
page
.
first
(
'.labels-filter .dropdown-title .dropdown-menu-close-icon'
).
click
sleep
2
page
.
within
'.labels-filter'
do
page
.
within
'.labels-filter'
do
expect
(
page
).
to
have_content
'No Label'
expect
(
page
).
to
have_content
'No Label'
end
end
...
@@ -121,6 +127,7 @@ describe 'Filter issues', feature: true do
...
@@ -121,6 +127,7 @@ describe 'Filter issues', feature: true do
find
(
'.js-label-select'
).
click
find
(
'.js-label-select'
).
click
find
(
'.dropdown-menu-labels .dropdown-content a'
,
text:
label
.
title
).
click
find
(
'.dropdown-menu-labels .dropdown-content a'
,
text:
label
.
title
).
click
page
.
first
(
'.labels-filter .dropdown-title .dropdown-menu-close-icon'
).
click
sleep
2
sleep
2
end
end
...
...
spec/features/issues_spec.rb
View file @
7e0ef892
...
@@ -112,7 +112,7 @@ describe 'Issues', feature: true do
...
@@ -112,7 +112,7 @@ describe 'Issues', feature: true do
end
end
describe
'filter issue'
do
describe
'filter issue'
do
titles
=
[
'foo'
,
'bar'
,
'baz'
]
titles
=
%w[foo bar baz
]
titles
.
each_with_index
do
|
title
,
index
|
titles
.
each_with_index
do
|
title
,
index
|
let!
(
title
.
to_sym
)
do
let!
(
title
.
to_sym
)
do
create
(
:issue
,
title:
title
,
create
(
:issue
,
title:
title
,
...
@@ -153,8 +153,94 @@ describe 'Issues', feature: true do
...
@@ -153,8 +153,94 @@ describe 'Issues', feature: true do
expect
(
first_issue
).
to
include
(
'baz'
)
expect
(
first_issue
).
to
include
(
'baz'
)
end
end
describe
'sorting by due date'
do
before
do
foo
.
update
(
due_date:
1
.
day
.
from_now
)
bar
.
update
(
due_date:
6
.
days
.
from_now
)
end
it
'sorts by recently due date'
do
visit
namespace_project_issues_path
(
project
.
namespace
,
project
,
sort:
sort_value_due_date_soon
)
expect
(
first_issue
).
to
include
(
'foo'
)
end
it
'sorts by least recently due date'
do
visit
namespace_project_issues_path
(
project
.
namespace
,
project
,
sort:
sort_value_due_date_later
)
expect
(
first_issue
).
to
include
(
'bar'
)
end
it
'sorts by least recently due date by excluding nil due dates'
do
bar
.
update
(
due_date:
nil
)
visit
namespace_project_issues_path
(
project
.
namespace
,
project
,
sort:
sort_value_due_date_later
)
expect
(
first_issue
).
to
include
(
'foo'
)
end
end
describe
'filtering by due date'
do
before
do
foo
.
update
(
due_date:
1
.
day
.
from_now
)
bar
.
update
(
due_date:
6
.
days
.
from_now
)
end
it
'filters by none'
do
visit
namespace_project_issues_path
(
project
.
namespace
,
project
,
due_date:
Issue
::
NoDueDate
.
name
)
expect
(
page
).
not_to
have_content
(
'foo'
)
expect
(
page
).
not_to
have_content
(
'bar'
)
expect
(
page
).
to
have_content
(
'baz'
)
end
it
'filters by any'
do
visit
namespace_project_issues_path
(
project
.
namespace
,
project
,
due_date:
Issue
::
AnyDueDate
.
name
)
expect
(
page
).
to
have_content
(
'foo'
)
expect
(
page
).
to
have_content
(
'bar'
)
expect
(
page
).
to
have_content
(
'baz'
)
end
it
'filters by due this week'
do
foo
.
update
(
due_date:
Date
.
today
.
beginning_of_week
+
2
.
days
)
bar
.
update
(
due_date:
Date
.
today
.
end_of_week
)
baz
.
update
(
due_date:
Date
.
today
-
8
.
days
)
visit
namespace_project_issues_path
(
project
.
namespace
,
project
,
due_date:
Issue
::
DueThisWeek
.
name
)
expect
(
page
).
to
have_content
(
'foo'
)
expect
(
page
).
to
have_content
(
'bar'
)
expect
(
page
).
not_to
have_content
(
'baz'
)
end
it
'filters by due this month'
do
foo
.
update
(
due_date:
Date
.
today
.
beginning_of_month
+
2
.
days
)
bar
.
update
(
due_date:
Date
.
today
.
end_of_month
)
baz
.
update
(
due_date:
Date
.
today
-
50
.
days
)
visit
namespace_project_issues_path
(
project
.
namespace
,
project
,
due_date:
Issue
::
DueThisMonth
.
name
)
expect
(
page
).
to
have_content
(
'foo'
)
expect
(
page
).
to
have_content
(
'bar'
)
expect
(
page
).
not_to
have_content
(
'baz'
)
end
it
'filters by overdue'
do
foo
.
update
(
due_date:
Date
.
today
+
2
.
days
)
bar
.
update
(
due_date:
Date
.
today
+
20
.
days
)
baz
.
update
(
due_date:
Date
.
yesterday
)
visit
namespace_project_issues_path
(
project
.
namespace
,
project
,
due_date:
Issue
::
Overdue
.
name
)
expect
(
page
).
not_to
have_content
(
'foo'
)
expect
(
page
).
not_to
have_content
(
'bar'
)
expect
(
page
).
to
have_content
(
'baz'
)
end
end
describe
'sorting by milestone'
do
describe
'sorting by milestone'
do
before
:each
do
before
do
foo
.
milestone
=
newer_due_milestone
foo
.
milestone
=
newer_due_milestone
foo
.
save
foo
.
save
bar
.
milestone
=
later_due_milestone
bar
.
milestone
=
later_due_milestone
...
@@ -177,7 +263,7 @@ describe 'Issues', feature: true do
...
@@ -177,7 +263,7 @@ describe 'Issues', feature: true do
describe
'combine filter and sort'
do
describe
'combine filter and sort'
do
let
(
:user2
)
{
create
(
:user
)
}
let
(
:user2
)
{
create
(
:user
)
}
before
:each
do
before
do
foo
.
assignee
=
user2
foo
.
assignee
=
user2
foo
.
save
foo
.
save
bar
.
assignee
=
user2
bar
.
assignee
=
user2
...
@@ -224,7 +310,7 @@ describe 'Issues', feature: true do
...
@@ -224,7 +310,7 @@ describe 'Issues', feature: true do
let
(
:guest
)
{
create
(
:user
)
}
let
(
:guest
)
{
create
(
:user
)
}
before
:each
do
before
do
project
.
team
<<
[[
guest
],
:guest
]
project
.
team
<<
[[
guest
],
:guest
]
end
end
...
@@ -267,7 +353,7 @@ describe 'Issues', feature: true do
...
@@ -267,7 +353,7 @@ describe 'Issues', feature: true do
context
'by unauthorized user'
do
context
'by unauthorized user'
do
let
(
:guest
)
{
create
(
:user
)
}
let
(
:guest
)
{
create
(
:user
)
}
before
:each
do
before
do
project
.
team
<<
[
guest
,
:guest
]
project
.
team
<<
[
guest
,
:guest
]
issue
.
milestone
=
milestone
issue
.
milestone
=
milestone
issue
.
save
issue
.
save
...
@@ -285,7 +371,7 @@ describe 'Issues', feature: true do
...
@@ -285,7 +371,7 @@ describe 'Issues', feature: true do
describe
'removing assignee'
do
describe
'removing assignee'
do
let
(
:user2
)
{
create
(
:user
)
}
let
(
:user2
)
{
create
(
:user
)
}
before
:each
do
before
do
issue
.
assignee
=
user2
issue
.
assignee
=
user2
issue
.
save
issue
.
save
end
end
...
...
spec/features/merge_requests/filter_by_milestone_spec.rb
View file @
7e0ef892
...
@@ -2,8 +2,14 @@ require 'rails_helper'
...
@@ -2,8 +2,14 @@ require 'rails_helper'
feature
'Merge Request filtering by Milestone'
,
feature:
true
do
feature
'Merge Request filtering by Milestone'
,
feature:
true
do
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let!
(
:user
)
{
create
(
:user
)}
let
(
:milestone
)
{
create
(
:milestone
,
project:
project
)
}
let
(
:milestone
)
{
create
(
:milestone
,
project:
project
)
}
before
do
project
.
team
<<
[
user
,
:master
]
login_as
(
user
)
end
scenario
'filters by no Milestone'
,
js:
true
do
scenario
'filters by no Milestone'
,
js:
true
do
create
(
:merge_request
,
:with_diffs
,
source_project:
project
)
create
(
:merge_request
,
:with_diffs
,
source_project:
project
)
create
(
:merge_request
,
:simple
,
source_project:
project
,
milestone:
milestone
)
create
(
:merge_request
,
:simple
,
source_project:
project
,
milestone:
milestone
)
...
...
spec/finders/issues_finder_spec.rb
View file @
7e0ef892
...
@@ -62,6 +62,22 @@ describe IssuesFinder do
...
@@ -62,6 +62,22 @@ describe IssuesFinder do
expect
(
issues
).
to
eq
([
issue2
])
expect
(
issues
).
to
eq
([
issue2
])
end
end
it
'returns unique issues when filtering by multiple labels'
do
label2
=
create
(
:label
,
project:
project2
)
create
(
:label_link
,
label:
label2
,
target:
issue2
)
params
=
{
scope:
'all'
,
label_name:
[
label
.
title
,
label2
.
title
].
join
(
','
),
state:
'opened'
}
issues
=
IssuesFinder
.
new
(
user
,
params
).
execute
expect
(
issues
).
to
eq
([
issue2
])
end
it
'should filter by no label name'
do
it
'should filter by no label name'
do
params
=
{
scope:
"all"
,
label_name:
Label
::
None
.
title
,
state:
'opened'
}
params
=
{
scope:
"all"
,
label_name:
Label
::
None
.
title
,
state:
'opened'
}
issues
=
IssuesFinder
.
new
(
user
,
params
).
execute
issues
=
IssuesFinder
.
new
(
user
,
params
).
execute
...
...
spec/lib/gitlab/metrics_spec.rb
View file @
7e0ef892
...
@@ -123,4 +123,28 @@ describe Gitlab::Metrics do
...
@@ -123,4 +123,28 @@ describe Gitlab::Metrics do
end
end
end
end
end
end
describe
'.action='
do
context
'without a transaction'
do
it
'does nothing'
do
expect_any_instance_of
(
Gitlab
::
Metrics
::
Transaction
).
not_to
receive
(
:action
=
)
Gitlab
::
Metrics
.
action
=
'foo'
end
end
context
'with a transaction'
do
it
'sets the action of a transaction'
do
trans
=
Gitlab
::
Metrics
::
Transaction
.
new
expect
(
Gitlab
::
Metrics
).
to
receive
(
:current_transaction
).
and_return
(
trans
)
expect
(
trans
).
to
receive
(
:action
=
).
with
(
'foo'
)
Gitlab
::
Metrics
.
action
=
'foo'
end
end
end
end
end
vendor/assets/javascripts/raven.js
0 → 100644
View file @
7e0ef892
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment