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
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
9aed32b1
Commit
9aed32b1
authored
Feb 01, 2018
by
Winnie Hellmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleanup new branch/merge request form in issues
parent
a6b9eb5d
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
135 additions
and
139 deletions
+135
-139
app/assets/javascripts/create_merge_request_dropdown.js
app/assets/javascripts/create_merge_request_dropdown.js
+1
-0
app/assets/javascripts/droplab/constants.js
app/assets/javascripts/droplab/constants.js
+0
-2
app/assets/javascripts/droplab/drop_down.js
app/assets/javascripts/droplab/drop_down.js
+8
-5
app/assets/stylesheets/framework/common.scss
app/assets/stylesheets/framework/common.scss
+2
-0
app/assets/stylesheets/framework/dropdowns.scss
app/assets/stylesheets/framework/dropdowns.scss
+0
-4
app/assets/stylesheets/framework/forms.scss
app/assets/stylesheets/framework/forms.scss
+1
-0
app/assets/stylesheets/pages/issues.scss
app/assets/stylesheets/pages/issues.scss
+11
-65
app/views/projects/issues/_new_branch.html.haml
app/views/projects/issues/_new_branch.html.haml
+30
-27
changelogs/unreleased/winh-new-branch-dropdown-style.yml
changelogs/unreleased/winh-new-branch-dropdown-style.yml
+5
-0
spec/javascripts/droplab/drop_down_spec.js
spec/javascripts/droplab/drop_down_spec.js
+77
-36
No files found.
app/assets/javascripts/create_merge_request_dropdown.js
View file @
9aed32b1
...
...
@@ -180,6 +180,7 @@ export default class CreateMergeRequestDropdown {
valueAttribute
:
'
data-text
'
,
},
],
hideOnClick
:
false
,
};
}
...
...
app/assets/javascripts/droplab/constants.js
View file @
9aed32b1
...
...
@@ -3,7 +3,6 @@ const DATA_DROPDOWN = 'data-dropdown';
const
SELECTED_CLASS
=
'
droplab-item-selected
'
;
const
ACTIVE_CLASS
=
'
droplab-item-active
'
;
const
IGNORE_CLASS
=
'
droplab-item-ignore
'
;
const
IGNORE_HIDING_CLASS
=
'
droplab-item-ignore-hiding
'
;
// Matches `{{anything}}` and `{{ everything }}`.
const
TEMPLATE_REGEX
=
/
\{\{(
.+
?)\}\}
/g
;
...
...
@@ -14,5 +13,4 @@ export {
ACTIVE_CLASS
,
TEMPLATE_REGEX
,
IGNORE_CLASS
,
IGNORE_HIDING_CLASS
,
};
app/assets/javascripts/droplab/drop_down.js
View file @
9aed32b1
import
utils
from
'
./utils
'
;
import
{
SELECTED_CLASS
,
IGNORE_CLASS
,
IGNORE_HIDING_CLASS
}
from
'
./constants
'
;
import
{
SELECTED_CLASS
,
IGNORE_CLASS
}
from
'
./constants
'
;
class
DropDown
{
constructor
(
list
,
config
=
{})
{
constructor
(
list
,
config
=
{
})
{
this
.
currentIndex
=
0
;
this
.
hidden
=
true
;
this
.
list
=
typeof
list
===
'
string
'
?
document
.
querySelector
(
list
)
:
list
;
this
.
items
=
[];
this
.
eventWrapper
=
{};
this
.
hideOnClick
=
config
.
hideOnClick
!==
false
;
if
(
config
.
addActiveClassToDropdownButton
)
{
this
.
dropdownToggle
=
this
.
list
.
parentNode
.
querySelector
(
'
.js-dropdown-toggle
'
);
...
...
@@ -37,15 +38,17 @@ class DropDown {
clickEvent
(
e
)
{
if
(
e
.
target
.
tagName
===
'
UL
'
)
return
;
if
(
e
.
target
.
cl
assList
.
contains
(
IGNORE_CLASS
))
return
;
if
(
e
.
target
.
cl
osest
(
`.
${
IGNORE_CLASS
}
`
))
return
;
const
selected
=
utils
.
closest
(
e
.
target
,
'
LI
'
);
const
selected
=
e
.
target
.
closest
(
'
li
'
);
if
(
!
selected
)
return
;
this
.
addSelectedClass
(
selected
);
e
.
preventDefault
();
if
(
!
e
.
target
.
classList
.
contains
(
IGNORE_HIDING_CLASS
))
this
.
hide
();
if
(
this
.
hideOnClick
)
{
this
.
hide
();
}
const
listEvent
=
new
CustomEvent
(
'
click.dl
'
,
{
detail
:
{
...
...
app/assets/stylesheets/framework/common.scss
View file @
9aed32b1
...
...
@@ -449,9 +449,11 @@ img.emoji {
.prepend-top-10
{
margin-top
:
10px
;
}
.prepend-top-15
{
margin-top
:
15px
;
}
.prepend-top-default
{
margin-top
:
$gl-padding
!
important
;
}
.prepend-top-16
{
margin-top
:
16px
;
}
.prepend-top-20
{
margin-top
:
20px
;
}
.prepend-left-4
{
margin-left
:
4px
;
}
.prepend-left-5
{
margin-left
:
5px
;
}
.prepend-left-8
{
margin-left
:
8px
;
}
.prepend-left-10
{
margin-left
:
10px
;
}
.prepend-left-default
{
margin-left
:
$gl-padding
;
}
.prepend-left-20
{
margin-left
:
20px
;
}
...
...
app/assets/stylesheets/framework/dropdowns.scss
View file @
9aed32b1
...
...
@@ -736,10 +736,6 @@
}
}
.droplab-item-ignore
{
pointer-events
:
none
;
}
.pika-single.animate-picker.is-bound
,
.pika-single.animate-picker.is-bound.is-hidden
{
/*
...
...
app/assets/stylesheets/framework/forms.scss
View file @
9aed32b1
...
...
@@ -182,6 +182,7 @@ label {
.help-block
{
margin-bottom
:
0
;
margin-top
:
#{
$grid-size
/
2
}
;
}
.gl-field-error
{
...
...
app/assets/stylesheets/pages/issues.scss
View file @
9aed32b1
...
...
@@ -181,11 +181,6 @@ ul.related-merge-requests > li {
}
.create-mr-dropdown-wrap
{
.branch-message
,
.ref-message
{
display
:
none
;
}
.
ref
:
:
selection
{
color
:
$placeholder-text-color
;
}
...
...
@@ -216,6 +211,17 @@ ul.related-merge-requests > li {
transform
:
translateY
(
0
);
display
:
none
;
margin-top
:
4px
;
// override dropdown item styles
.btn.btn-success
{
@include
btn-default
;
@include
btn-green
;
border-style
:
solid
;
border-width
:
1px
;
line-height
:
$line-height-base
;
width
:
auto
;
}
}
.create-merge-request-dropdown-toggle
{
...
...
@@ -225,66 +231,6 @@ ul.related-merge-requests > li {
margin-left
:
0
;
}
}
.droplab-item-ignore
{
pointer-events
:
auto
;
}
.create-item
{
cursor
:
pointer
;
margin
:
0
1px
;
&
:hover
,
&
:focus
{
background-color
:
$dropdown-item-hover-bg
;
color
:
$gl-text-color
;
}
}
li
.divider
{
margin
:
8px
10px
;
}
li
:not
(
.divider
)
{
padding
:
8px
9px
;
&
:last-child
{
padding-bottom
:
8px
;
}
&
.droplab-item-selected
{
.icon-container
{
i
{
visibility
:
visible
;
}
}
.description
{
display
:
block
;
}
}
&
.droplab-item-ignore
{
padding-top
:
8px
;
}
.icon-container
{
float
:
left
;
i
{
visibility
:
hidden
;
}
}
.description
{
padding-left
:
22px
;
}
input
,
span
{
margin
:
4px
0
0
;
}
}
}
.discussion-reply-holder
.note-edit-form
{
...
...
app/views/projects/issues/_new_branch.html.haml
View file @
9aed32b1
...
...
@@ -21,30 +21,33 @@
%button
.btn.create-merge-request-dropdown-toggle.dropdown-toggle.btn-success.btn-inverted.js-dropdown-toggle
{
type:
'button'
,
data:
{
dropdown:
{
trigger:
'#create-merge-request-dropdown'
}
}
}
=
icon
(
'caret-down'
)
.droplab-dropdown
%ul
#create-merge-request-dropdown
.create-merge-request-dropdown-menu.dropdown-menu.dropdown-menu-align-right.gl-show-field-errors
{
data:
{
dropdown:
true
}
}
-
if
can_create_merge_request
%li
.create-item.droplab-item-selected.droplab-item-ignore-hiding
{
role:
'button'
,
data:
{
value:
'create-mr'
,
text:
'Create merge request'
}
}
.menu-item.droplab-item-ignore-hiding
.icon-container.droplab-item-ignore-hiding
=
icon
(
'check'
)
.description.droplab-item-ignore-hiding
Create merge request and branch
%li
.create-item.droplab-item-ignore-hiding
{
class:
[
!
can_create_merge_request
&&
'droplab-item-selected'
],
role:
'button'
,
data:
{
value:
'create-branch'
,
text:
'Create branch'
}
}
.menu-item.droplab-item-ignore-hiding
.icon-container.droplab-item-ignore-hiding
=
icon
(
'check'
)
.description.droplab-item-ignore-hiding
Create branch
%li
.divider
%li
.droplab-item-ignore
Branch name
%input
.js-branch-name.form-control.droplab-item-ignore
{
type:
'text'
,
placeholder:
"#{@issue.to_branch_name}"
,
value:
"#{@issue.to_branch_name}"
}
%span
.js-branch-message.branch-message.droplab-item-ignore
%li
.droplab-item-ignore
Source (branch or tag)
%input
.js-ref.ref.form-control.droplab-item-ignore
{
type:
'text'
,
placeholder:
"#{@project.default_branch}"
,
value:
"#{@project.default_branch}"
,
data:
{
value:
"#{@project.default_branch}"
}
}
%span
.js-ref-message.ref-message.droplab-item-ignore
%li
.droplab-item-ignore
%button
.btn.btn-success.js-create-target.droplab-item-ignore
{
type:
'button'
,
data:
{
action:
'create-mr'
}
}
Create merge request
%li
.droplab-item-selected
{
role:
'button'
,
data:
{
value:
'create-mr'
,
text:
_
(
'Create merge request'
)
}
}
.menu-item
=
icon
(
'check'
,
class:
'icon'
)
=
_
(
'Create merge request and branch'
)
%li
{
class:
[
!
can_create_merge_request
&&
'droplab-item-selected'
],
role:
'button'
,
data:
{
value:
'create-branch'
,
text:
_
(
'Create branch'
)
}
}
.menu-item
=
icon
(
'check'
,
class:
'icon'
)
=
_
(
'Create branch'
)
%li
.divider.droplab-item-ignore
%li
.droplab-item-ignore.prepend-left-8.append-right-8.prepend-top-16
.form-group
%label
{
for:
'new-branch-name'
}
=
_
(
'Branch name'
)
%input
#new-branch-name
.js-branch-name.form-control
{
type:
'text'
,
placeholder:
"#{@issue.to_branch_name}"
,
value:
"#{@issue.to_branch_name}"
}
%span
.js-branch-message.help-block
.form-group
%label
{
for:
'source-name'
}
=
_
(
'Source (branch or tag)'
)
%input
#source-name
.js-ref.ref.form-control
{
type:
'text'
,
placeholder:
"#{@project.default_branch}"
,
value:
"#{@project.default_branch}"
,
data:
{
value:
"#{@project.default_branch}"
}
}
%span
.js-ref-message.help-block
.form-group
%button
.btn.btn-success.js-create-target
{
type:
'button'
,
data:
{
action:
'create-mr'
}
}
=
_
(
'Create merge request'
)
changelogs/unreleased/winh-new-branch-dropdown-style.yml
0 → 100644
View file @
9aed32b1
---
title
:
Cleanup new branch/merge request form in issues
merge_request
:
16854
author
:
type
:
fixed
spec/javascripts/droplab/drop_down_spec.js
View file @
9aed32b1
import
DropDown
from
'
~/droplab/drop_down
'
;
import
utils
from
'
~/droplab/utils
'
;
import
{
SELECTED_CLASS
,
IGNORE_CLASS
}
from
'
~/droplab/constants
'
;
import
{
SELECTED_CLASS
}
from
'
~/droplab/constants
'
;
describe
(
'
DropDown
'
,
function
()
{
describe
(
'
Drop
Lab Drop
Down
'
,
function
()
{
describe
(
'
class constructor
'
,
function
()
{
beforeEach
(
function
()
{
spyOn
(
DropDown
.
prototype
,
'
getItems
'
);
...
...
@@ -128,93 +128,131 @@ describe('DropDown', function () {
beforeEach
(
function
()
{
this
.
classList
=
jasmine
.
createSpyObj
(
'
classList
'
,
[
'
contains
'
]);
this
.
list
=
{
dispatchEvent
:
()
=>
{}
};
this
.
dropdown
=
{
hide
:
()
=>
{},
list
:
this
.
list
,
addSelectedClass
:
()
=>
{}
};
this
.
event
=
{
preventDefault
:
()
=>
{},
target
:
{
classList
:
this
.
classList
}
};
this
.
dropdown
=
{
hideOnClick
:
true
,
hide
:
()
=>
{},
list
:
this
.
list
,
addSelectedClass
:
()
=>
{},
};
this
.
event
=
{
preventDefault
:
()
=>
{},
target
:
{
classList
:
this
.
classList
,
closest
:
()
=>
null
,
},
};
this
.
customEvent
=
{};
this
.
closestElement
=
{};
this
.
dummyListItem
=
document
.
createElement
(
'
li
'
);
spyOn
(
this
.
event
.
target
,
'
closest
'
).
and
.
callFake
((
selector
)
=>
{
if
(
selector
===
'
li
'
)
{
return
this
.
dummyListItem
;
}
return
null
;
});
spyOn
(
this
.
dropdown
,
'
hide
'
);
spyOn
(
this
.
dropdown
,
'
addSelectedClass
'
);
spyOn
(
this
.
list
,
'
dispatchEvent
'
);
spyOn
(
this
.
event
,
'
preventDefault
'
);
spyOn
(
window
,
'
CustomEvent
'
).
and
.
returnValue
(
this
.
customEvent
);
spyOn
(
utils
,
'
closest
'
).
and
.
returnValues
(
this
.
closestElement
,
undefined
);
this
.
classList
.
contains
.
and
.
returnValue
(
false
);
});
it
(
'
should call event.target.closest
'
,
function
()
{
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
});
it
(
'
should call utils.closest
'
,
function
()
{
expect
(
utils
.
closest
).
toHaveBeenCalledWith
(
this
.
event
.
target
,
'
LI
'
);
expect
(
this
.
event
.
target
.
closest
).
toHaveBeenCalledWith
(
'
.droplab-item-ignore
'
);
expect
(
this
.
event
.
target
.
closest
).
toHaveBeenCalledWith
(
'
li
'
);
});
it
(
'
should call addSelectedClass
'
,
function
()
{
expect
(
this
.
dropdown
.
addSelectedClass
).
toHaveBeenCalledWith
(
this
.
closestElement
);
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
expect
(
this
.
dropdown
.
addSelectedClass
).
toHaveBeenCalledWith
(
this
.
dummyListItem
);
});
it
(
'
should call .preventDefault
'
,
function
()
{
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
expect
(
this
.
event
.
preventDefault
).
toHaveBeenCalled
();
});
it
(
'
should call .hide
'
,
function
()
{
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
expect
(
this
.
dropdown
.
hide
).
toHaveBeenCalled
();
});
it
(
'
should construct CustomEvent
'
,
function
()
{
expect
(
window
.
CustomEvent
).
toHaveBeenCalledWith
(
'
click.dl
'
,
jasmine
.
any
(
Object
));
});
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
it
(
'
should call .classList.contains checking for IGNORE_CLASS
'
,
function
()
{
expect
(
this
.
classList
.
contains
).
toHaveBeenCalledWith
(
IGNORE_CLASS
);
expect
(
window
.
CustomEvent
).
toHaveBeenCalledWith
(
'
click.dl
'
,
jasmine
.
any
(
Object
));
});
it
(
'
should call .dispatchEvent with the customEvent
'
,
function
()
{
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
expect
(
this
.
list
.
dispatchEvent
).
toHaveBeenCalledWith
(
this
.
customEvent
);
});
describe
(
'
if the target is a UL element
'
,
function
()
{
beforeEach
(
function
()
{
this
.
event
=
{
preventDefault
:
()
=>
{},
target
:
{
tagName
:
'
UL
'
,
classList
:
this
.
classList
}
};
spyOn
(
this
.
event
,
'
preventDefault
'
);
utils
.
closest
.
calls
.
reset
();
this
.
event
.
target
=
document
.
createElement
(
'
ul
'
);
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
spyOn
(
this
.
event
.
target
,
'
closest
'
);
});
it
(
'
should return immediately
'
,
function
()
{
expect
(
utils
.
closest
).
not
.
toHaveBeenCalled
();
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
expect
(
this
.
event
.
target
.
closest
).
not
.
toHaveBeenCalled
();
expect
(
this
.
dropdown
.
addSelectedClass
).
not
.
toHaveBeenCalled
();
});
});
describe
(
'
if the target has the
IGNORE_CLASS
class
'
,
function
()
{
describe
(
'
if the target has the
droplab-item-ignore
class
'
,
function
()
{
beforeEach
(
function
()
{
this
.
event
=
{
preventDefault
:
()
=>
{},
target
:
{
tagName
:
'
LI
'
,
classList
:
this
.
classList
}
};
this
.
ignoredButton
=
document
.
createElement
(
'
button
'
);
this
.
ignoredButton
.
classList
.
add
(
'
droplab-item-ignore
'
);
this
.
event
.
target
=
this
.
ignoredButton
;
spyOn
(
this
.
event
,
'
preventDefault
'
);
this
.
classList
.
contains
.
and
.
returnValue
(
true
);
utils
.
closest
.
calls
.
reset
();
spyOn
(
this
.
ignoredButton
,
'
closest
'
).
and
.
callThrough
();
});
it
(
'
does not select element
'
,
function
()
{
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
});
it
(
'
should return immediately
'
,
function
()
{
expect
(
utils
.
closest
).
not
.
toHaveBeenCalled
();
expect
(
this
.
ignoredButton
.
closest
.
calls
.
count
()).
toBe
(
1
);
expect
(
this
.
ignoredButton
.
closest
).
toHaveBeenCalledWith
(
'
.droplab-item-ignore
'
);
expect
(
this
.
dropdown
.
addSelectedClass
).
not
.
toHaveBeenCalled
();
});
});
describe
(
'
if no selected element exists
'
,
function
()
{
beforeEach
(
function
()
{
this
.
event
.
preventDefault
.
calls
.
reset
();
this
.
clickEvent
=
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
});
it
(
'
should return undefined
'
,
function
()
{
expect
(
this
.
clickEvent
).
toBe
(
undefined
);
this
.
dummyListItem
=
null
;
});
it
(
'
should return before .preventDefault is called
'
,
function
()
{
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
expect
(
this
.
event
.
preventDefault
).
not
.
toHaveBeenCalled
();
expect
(
this
.
dropdown
.
addSelectedClass
).
not
.
toHaveBeenCalled
();
});
});
describe
(
'
if hideOnClick is false
'
,
()
=>
{
beforeEach
(
function
()
{
this
.
dropdown
.
hideOnClick
=
false
;
this
.
dropdown
.
hide
.
calls
.
reset
();
});
it
(
'
should not call .hide
'
,
function
()
{
DropDown
.
prototype
.
clickEvent
.
call
(
this
.
dropdown
,
this
.
event
);
expect
(
this
.
dropdown
.
hide
).
not
.
toHaveBeenCalled
();
});
});
});
...
...
@@ -278,20 +316,23 @@ describe('DropDown', function () {
describe
(
'
addEvents
'
,
function
()
{
beforeEach
(
function
()
{
this
.
list
=
{
addEventListener
:
()
=>
{}
};
this
.
list
=
{
addEventListener
:
()
=>
{},
querySelectorAll
:
()
=>
[],
};
this
.
dropdown
=
{
list
:
this
.
list
,
clickEvent
:
()
=>
{},
closeDropdown
:
()
=>
{},
eventWrapper
:
{},
};
});
it
(
'
should call .addEventListener
'
,
function
()
{
spyOn
(
this
.
list
,
'
addEventListener
'
);
DropDown
.
prototype
.
addEvents
.
call
(
this
.
dropdown
);
});
it
(
'
should call .addEventListener
'
,
function
()
{
expect
(
this
.
list
.
addEventListener
).
toHaveBeenCalledWith
(
'
click
'
,
jasmine
.
any
(
Function
));
expect
(
this
.
list
.
addEventListener
).
toHaveBeenCalledWith
(
'
keyup
'
,
jasmine
.
any
(
Function
));
});
...
...
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